• Resolved mrapi

    (@mrapi)


    Hi !
    I’m new using WordPress.In my site I have a menu that links directly to a setup file,for downloading.I want to hook an action/filter on writing a function that inserts into a database the time when the setup was downloaded/menu accessed.
    I know I could find a plugin but I want to create my own,I also want to customize that on every new week to send info to my mail about last week downloads activity.
    All I need now is how to hook that in wordpress?

    Thanks!

Viewing 14 replies - 1 through 14 (of 14 total)
  • Moderator bcworkz

    (@bcworkz)

    Direct links to files outside of WordPress’ purview do not involve WordPress processes in any way, so there is nothing to hook into. In order to log downloads and mail reports,the menu should actually result in an AJAX request. If that request succeeds, the user is then forwarded to the download file by the AJAX callback.

    Thus the hook you use is a custom ajax action that logs the download and sends mail as needed before responding to the request with either a success indication or an error message. Ref: AJAX in Plugins

    Thread Starter mrapi

    (@mrapi)

    Thanks for your answer,i’ll see your link.

    Thread Starter mrapi

    (@mrapi)

    I’ve read your link,I understood AJAX is for getting data from sever without refreshing the page,also WP does this by admin-ajax.php

    in your example data sent to server is
    var data = {
    action: ‘my_action’,
    whatever: 1234
    };

    this function: my_action_callback returns $_POST[‘whatever’] increased with 10

    I don’t know how to put this in my case : how to call server from the download menu using ajax in order to call my function and also to download the file
    ??

    thanks.

    Moderator bcworkz

    (@bcworkz)

    It’s best to use jQuery to make AJAX calls. So the download “link” isn’t really a link, it invokes a jQuery function, either by event listener or direct call, that makes the AJAX request, receives the server response, and either displays a message on failure, or forwards the user to the download file. I believe you can just do window.location.assign("http{colon}//example.com/path/to/file.ext"); in javascript to proceed with the download, but I could be wrong, I’m traveling and don’t have access to my usual references.

    (I typed the word “colon” instead of the character because I hate how the parser linkifies anything that looks like an URL, even if it’s invalid ?? )

    Thread Starter mrapi

    (@mrapi)

    I don’t know jquery,i’ll study some..
    Thanks!

    Thread Starter mrapi

    (@mrapi)

    I’ve done some study and I’m near to solve this.
    When a user click on exe setup link,I want to insert some data into a table (date+time and file name downloaded)
    I also have a child theme, in functions.php I put:

    <?php
    wp_enqueue_script('jquery');
    
    function fn_download_AddtoCount()
     {
    
         global $wpdb;
    
         $filename=$_POST['dw_file_name'];
    
       $wpdb->insert( $wpdb->prefix.'es_download_counter',
                  array( 'download_name' => $filename, 'time' => current_time('mysql')),
                  array( '%s',  '%s' )
                          );
     }
    add_action('wp_ajax_fn_download_AddtoCount', 'fn_download_AddtoCount');
    add_action('wp_ajax_nopriv_fn_download_AddtoCount', 'fn_download_AddtoCount');

    in header.php,at the bottom :

    .....
     <script type="text/javascript"
                        src="<?php echo get_stylesheet_directory_uri("template_url"); ?>/js/dwcounter.js">
    
                </script>

    and dwcounter.js:

    var $j = jQuery.noConflict();
    
    $j(function()
       {
           $j('a[href$=".exe"]').on('click',
                 function(e)
                   {
                       var aryFd = $j(this).attr('href').split("/");
    
                      console.log('is here');
    
                       $j.ajax({
                           type:"POST",
                           url: "/wordpress/wp-admin/admin-ajax.php",
                           data: {
                                  action: 'fn_download_AddtoCount',
                                  dw_file_name: aryFd[aryFd.length - 1]
                                 }
    
                               });
    
                     }
    
                          );
       });

    table structure:
    CREATE TABLE IF NOT EXISTSwp_es_download_counter` (
    id mediumint(9) NOT NULL AUTO_INCREMENT,
    time datetime NOT NULL DEFAULT ‘0000-00-00 00:00:00’,
    download_name text NOT NULL,
    UNIQUE KEY id (id)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;`

    The problem is: that only works now and then: I have to click 3 times, with pause between, to see a new record added into table,sometime after 3-4 clicks,no record ??

    console.log(‘is here’) it is always executed,there must be something wrong in ajax call or my php function
    any help?
    thanks!

    Moderator bcworkz

    (@bcworkz)

    I think the only problem is how you’ve linked your dwcounter.js file. If this were not a WP site, you’d have done everything correctly, you have learned well! As it happens, AJAX in WP has a few quirks that you need to adapt to for success.

    You did POST to admin-ajax.php, which is correct, congratulations, many people miss that quirk.

    What you need to change is instead of enqueuing jquery, enqueue your dwcounter.js file and specify jquery as a dependency. This will place the meta link in the page head where it belongs along with the jquery link. Thus you can delete the script block link you added to header.php.

    Inconsistent behavior is exactly what happens when scripts are not enqueued properly. It drives people crazy because sometimes things work, other times no. I hope you didn’t struggle too much before asking for help. Other than that, everything looks good. Well learned!

    Thread Starter mrapi

    (@mrapi)

    Thanks bcworkz for your answer.I have lots of thinks to learn.. ??

    I’ve removed script block from header.php and how you suggested I’ve
    found how to specify jquery as a dependency
    https://www.ericmmartin.com/5-tips-for-using-jquery-with-wordpress/

    so in my functions.php
    I removed the line:
    wp_enqueue_script('jquery');

    and I added:

    function my_script_init()
    {
    
    		wp_deregister_script('jquery');
    		wp_register_script('jquery', 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js', false, '1.3.2', true);
    		wp_enqueue_script('jquery');
    	wp_enqueue_script('dwcounter',get_stylesheet_directory_uri()."/js/dwcounter.js", array('jquery'), '1.0', true);
    
    }
    
    add_action('init', 'my_script_init');

    script is executed as I can see in console,also no error in console but things are just the same : no record added ??

    thanks!

    Moderator bcworkz

    (@bcworkz)

    I would suggest you let WP use it’s version of jQuery unless you have a specific need requiring a different version. Thus you do not need the first three lines switching versions. The one line enqueueing your script and specifying jquery as a dependency will be all that is needed.

    We also do not enqueue from ‘init’ any more. There are now specific hooks depending on what sort of page the script is for. This is similar but different from the wp_ajax_ and wp_ajax_nopriv_ hook prefixes. In this case the criteria is not if the user is logged in, it is front end vs. back end pages. If this is a front end page, enqueue from ‘wp_enqueue_scripts’. For back end admin pages enqueue from ‘admin_enqueue_scripts’. The login page gets its own, ‘login_enqueue_scripts’

    I’m not sure any of that is the reason for your script not working, but you may as well do everything the proper way. The real problem, which I missed during my previous review is the url parameter. It needs to be a complete URL including https://, domain, everything. jQuery has no idea where your server is. For that matter, you may be querying some 3rd party API on a different server. jQuery doesn’t care, but it does need full information.

    It’s actually sort of poor practice to hardcode URLs like that, but that’s from the standpoint of distributable themes and plugins. For your own use hardcoding will suffice. FYI, for back end pages, WP provides a handy global variable, ajaxurl containing the full URL to admin-ajax.php. For front end pages you need to pass PHP values to jQuery in a localized object. This is more complication that you do not need right now, but you should at least be aware there’s a way to address portability in all of this.

    Anyway, unless I’ve missed something still, I believe providing a complete hardcoded URL should at least get everything working.

    Thread Starter mrapi

    (@mrapi)

    Hi bcworkz,thanks again for your answer,my code look now like this:

    functions.php

    <?php
    
    function fn_my_script_enqueuer() {
       wp_enqueue_script('dwcounter',get_stylesheet_directory_uri()."/js/dwcounter.js", array('jquery'), '1.0', true);
    }
    
    add_action('wp_enqueue_scripts', 'fn_my_script_enqueuer');
    
    function fn_download_AddtoCount()
     {
    
         global $wpdb;
    
         $filename=$_POST['dw_file_name'];
    
       $wpdb->insert( $wpdb->prefix.'es_download_counter',
                  array( 'download_name' => $filename, 'time' => current_time('mysql')),
                  array( '%s',  '%s' )
                          );
    
        //echo('inserted');
       // die();
    
     }
    
    add_action('wp_ajax_fn_download_AddtoCount', 'fn_download_AddtoCount');
    add_action('wp_ajax_nopriv_fn_download_AddtoCount', 'fn_download_AddtoCount');

    js:

    var $j = jQuery.noConflict();
    
    $j(function()
       {
           $j('a[href$=".exe"]').on('click',
                 function(e)
                   {
                       var aryFd = $j(this).attr('href').split("/");
    
                       $j.ajax({
                           type:"POST",
                           url: "https://www.softexpertcta.info/wordpress/wp-admin/admin-ajax.php",
                           data: {
                                  action: 'fn_download_AddtoCount',
                                  dw_file_name: aryFd[aryFd.length - 1]
                                 },
                            success:function(response)
                             {
                               alert('Got this from the server: '+ response);
                             }
    
                               });
    
                     }
    
                          );
       });

    I make tests for 2 days,but no look
    I suspected php procedure when insering data so I replace that with writing something into a txt file,and just the same behavoiur,
    js file is always executed,I debug that with alert() so 99% problem,as you said is ajax call
    I put there the complete url as in the code above,nothing fixed
    I also tested on a localhost checking php log file:no error

    A strange thing also: if I uncomment these lines:
    //echo(‘inserted’);
    // die();
    alert from js success: is not reached

    in console on load page I have this warning:
    event.returnValue is deprecated. Please use the standard event.preventDefault() instead.

    also on every click I can see this warning :

    Resource interpreted as Document but transferred with MIME type application/x-msdownload: “https://www.softexpertcta.info/dmdocuments/installAllnetSFXP.exe&#8221;

    my site is this
    download link is on red button on right corner above “Descarca acum”

    thanks!

    Moderator bcworkz

    (@bcworkz)

    The PHP code does not die because it is never executed. Yet it appears the request is sent correctly. What happened to me when I tried to do the download is the AJAX request was instantly aborted due to the GET request for the download file. AJAX never reached the server.

    I believe jQuery is supposed to prevent this with .preventDefault(). But notice the warning related to this is a jQuery file, not anything you did. Try inserting this line just before the $j.ajax() call: e.preventDefault();

    If that doesn’t help, I’m not sure what to suggest, this sort thing is outside my expertise. What led to this discovery is I used HttpFox for Firefox to monitor the HTTP traffic between my browser and your server. The AJAX request resulted in a “NS_BINDING_ABORTED” error in the “Type” column that normal lists MIME types.

    If you are still having trouble, search for NS_BINDING_ABORTED and see if any other suggestions found are worth trying. Another possibility is instead of a simple download link, have JavaScript send the download request after it gets an AJAX response.

    The MIME type warning is because a link is expected to be for a document but in your case it is an executable file. I’ve no idea how one would specify a MIME type for a link, which may be an argument for letting JavaScript make the request. But consider that when it comes to what browsers do internally, I don’t know what I’m talking about.

    I do know that your AJAX code appears to be in order now, if we can only get it to be actually sent.

    Thread Starter mrapi

    (@mrapi)

    Hi bcworkz,thanks again for your help,seems to me that I solved the problem.

    I used e.preventDefault(),in this case I used window.location to start the download

    My first intention was to put window.location just after ajax call,and I’ve seen that canceled the call,so I decided to put it into
    success:function() and that worked,I can’t explain why …
    For this moment that seems to work fine.
    Just one question:would be hard to create a plugin for this,maybe I will change the theme and plugin will be a good solution.

    Just a curiosity:are you from wordpress team?
    Thanks for your time and help!!!

    this is the final js code:

    var $j = jQuery.noConflict();
    
    $j(function()
       {
           $j('a[href$=".exe"]').on('click',
                 function(e)
                   {
                       var aryFd = $j(this).attr('href').split("/");
    		   var link = $j(this).attr('href');
    
                        e.preventDefault();
    
                       $j.ajax({
                           type:"POST",
                           url: "https://www.softexpertcta.info/wordpress/wp-admin/admin-ajax.php",
                           data: {
                                  action: 'fn_download_AddtoCount',
                                  dw_file_name: aryFd[aryFd.length - 1]
                                 },
                            success:function(response)
                             {
    
                               window.location=link;
                             }
    
                               });
    
                     }
    
                          );
       });

    Moderator bcworkz

    (@bcworkz)

    Awesome! I wouldn’t have known where to go next if that didn’t work out. I’m glad you were able to fill in the gaps of my suggestion.

    Just about anything that doesn’t have to do with theme templates can be made into a plugin, including your download counter. For a fully fledged plugin, you would need to do more, such as create the counter table when the plugin is activated, and optionally delete it when the plugin is deleted, perhaps a settings page to manage what to count, etc. But as a plugin for your own use on your site it’s a cinch. Create a page with the proper comment header, move all related code to that page, place it in its folder in /plugins/, then activate.

    Am I part of the WordPress team? Depends on what you mean by team. If you mean the hundreds of random volunteers that donate their time to the cause, then yes. But I have no special privileges, I am not a moderator or anything like that. Besides this support forum I do some documentation writing, but I am not involved with core development or anything like that. I’m really just someone that gets joy from helping others, nothing more.

    Thread Starter mrapi

    (@mrapi)

    Hi,thanks for your answer,I’ll study also plugins development.
    That is great: you get joy from helping others,all the best for you !!!

Viewing 14 replies - 1 through 14 (of 14 total)
  • The topic ‘Hook on download link/accessing menu’ is closed to new replies.