We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 17035
    • 36 Posts
    Hi There,

    We're using MODx with Foxycart to create a subscription based website that gives users access to certain sections of the website once they sign up. This is all now active but we were wondering if there was a way that we could run a report to find all the subscribed customer (or just all users) and when they last logged in?

    Or a report that allows us to see who has logged into the site during a specific date range.

    I know that I can go in to each user one by one and see when they last logged in, but It would be great if we could generate a report to see when each user logged in and the level of activity on the website.

    Any help with this would be fantastic. Thank you in advance.

    Kind Regards
    Lewis
      • 36906
      • 34 Posts
      Hi Lewis,
      Yes you could do that very easily using a custom manager action.

      The last login timestamp is in the 'user_attributes' table for native Modx users, not sure if FoxyCart uses the same one though...

      You could loop these DB rows and use fputcsv() to generate a .csv format (Excel friendly) report that can be initiated at any time via a custom manager action.

      They could also be displayed on screen for you to review.

      Are you a programmer? I'm happy to bash out some code examples if it helps.

      [ed. note: thenewmanifesto last edited this post 14 years, 11 months ago.]
        • 17035
        • 36 Posts
        Hi,

        Thanks for your help!

        I'm not a PHP Programmer, I know HTML and CSS pretty well but that won't help me in this situation unfortunately!

        I've just had a look in phpmyadmin at the tables and it looks like it's using the 'lastlogin' section within the 'modx_web_user_attributes' table. I should probably have explained I'm using MODx Evolution rather than Revo too.. Not sure if that makes a difference to your previous post?

        Any assistance you can provide would be fantastic.

        Many thanks
        Lewis
          • 36906
          • 34 Posts


          Hi Lewis,

          Sorry, I didn't realise - only used Evo once and it was ages ago.


          It shouldn't make a massive difference for a reporting script in terms of what it needs to do (grab.loop,csv,output), but there will likely be differences in the way Evo/Revo handles custom manager actions.

          Have you used custom manager pages in Evo previously?
          I'll try and install Evo and then get back to you...




            • 36906
            • 34 Posts
            Hi Lewis,

            The script below should give you an outline of the csv generation, but there are a few things you'll need to check out for Evo (tested on Revo then partially ported to Evo - untested).

            Hoping I'm not going to confuse the issue further!


            a) Check how to create/integrate custom manager pages in Evo.
            b) Check the table names (User Attributes and User Data - Evo equivalents)
            c) Check the table field names for both tables (I didn't install Evo to check)
            e) Check how to issues SQL queries in Evo


            
            <?php
            /**
            
            1) Make sure we have our Modx Object.
            2) Table names - adjust for Evo.
            3) SQL with the fields we need - adjust for Evo.
            4) Get a file handle.
            5) Set the header so it outputs as csv.
            6) Loop the results.
            7) On the first iteration, set the csv headers from the DB field names.
            8) Create csv row.
            9) Output to browser.
            
            */
            
            // 1)
            if($modx) {
            
                // 2)
                $table1 =  $modx->getFullTableName("user_attributes");
                $table2 =  $modx->getFullTableName("users");
                
                // 3)
                $sql = "SELECT
                        `ua`.`fullname`, 
                        `ua`.`email`, 
                        `ua`.`logincount`, 
                        `ua`.`failedlogincount`, 
                        DATE_FORMAT(FROM_UNIXTIME(`ua`.`lastlogin`),'%W, %M %e, %Y @ %h:%i %p') as `previous_login`,
                        DATE_FORMAT(FROM_UNIXTIME(`ua`.`thislogin`),'%W, %M %e, %Y @ %h:%i %p') as `last_login`           
                        FROM $table1 `ua` 
                        JOIN $table2 `u`
                        ON (`u`.`id` = `ua`.`id`)
                        WHERE `u`.`active` = '1' 
                        ORDER BY `ua`.`fullname` ASC";
                   
                // You could check/refine the query in PhpMyAdmin...     
                // die($sql);
                        
                $result = $modx->db->query($sql);
                if($modx->db->getRecordCount($result) >= 1) {
            
                   // 4)
                   $stdout = fopen('php://output', 'w');
                   
                   // 5)    
                   header('Content-type: application/csv');
                   header('Content-Disposition: attachment; filename="export_userlogins_' . date("d-m-Y") . '.csv"');
                   	
                   $c = 0;
                   
                   // 6)
                   while($row = $modx->db->getRow($result)) {
                   
                       // 7)
                       if($c == 0) { fputcsv($stdout, array_keys($row)); }
                       
                       // 8)
                       fputcsv($stdout, $row); 
                       
                       $c++;
                   }
            
                } else {
                    return "None found";
                }
                    
                // 9)
                fclose($stdout); 
                exit; 
            
            } else {
                return "Missing Modx Object";
            }
            
            ?>
            


            You can see the script itself is very basic (plenty of scope for improvement), but it should give you some ideas on how to approach the csv output aspect.

            I set it up on Revo to work when the user clicks on a custom manager menu item in case you're wondering how to call it. It should output to your 'downloads folder' or Desktop.


            References:
            http://wiki.modxcms.com/index.php/API:DBAPI:getRow
            http://www.w3schools.com/sql/func_date_format.asp

            If you do get stuck, or something is unclear/not working let us know.


            Thanks
            Danny
              • 17035
              • 36 Posts
              Hi Danny,

              Woah! Thanks for all the help.

              Ok, I've gone through the file and edited it so that all the tables now match what is in MODx Evolution along with the custom prefixs I have setup.

              I assume if I upload this file to the website and then just call it via by browser, it will run and export? I can then add a link within MODx as you said above once I'm confident it'll work?

              Is that correct? Many thanks for your help!

              Kind Regards
              Lewis
                • 36906
                • 34 Posts
                Hi Lewis,

                You might not be able to call it directly in your browser because it needs the Modx object's DB methods, but you could put it in a Snippet inside a Resource whilst you test it…

                You could also test the query itself in PhpMyAdmin.

                If you need it as a standalone script (for example to call via CRON each day), then it would only need minor adjustments to grab the config file and the Modx object at the top of the script, and then to write the csv file to disc, and/or email it to yourself.

                To write it to disc, instead of using the PHP output stream you would just use a physical file handle.
                // $stdout = fopen('php://output', 'w');
                // Would become...
                $stdout = fopen("/var/www/lewis/reports/user/exportusers_" . date("d-m-Y-His") . ".csv", "w"); 
                


                This standalone script example is for REVO, but you'll get the idea and be able to Google the EVO equivalent.

                Please note this is from memory, but essentially you just need the config, and then the main Modx class before continuing as normal.

                // Define the correct core path
                if (!defined('MODX_CORE_PATH')) define('MODX_CORE_PATH', '/var/www/lewis/core/');
                
                // Grab config file
                include(MODX_CORE_PATH . 'config/config.core.php');
                
                // Grab Modx class
                include_once MODX_CORE_PATH . 'model/modx/modx.class.php';
                
                // Init Modx
                $modx= new modX();
                $modx->initialize('mgr');
                
                // Rest of original script here... 
                
                


                There should be a few examples of standalone Evo scripts knocking about to get the correct syntax for the above...


                Let us know if you need any specific pointers as you move forward.


                In a bizzle…
                Danny
                [ed. note: thenewmanifesto last edited this post 14 years, 11 months ago.]
                  • 17035
                  • 36 Posts
                  Hi Danny,

                  Thanks very much for all your help!

                  I've spoken to another PHP Developer I know who works with MODx Evolution quite a lot. He has added the script in for me (you have to create a 'module' in Evo). I can now run the module and it works like a charm.

                  Thanks for all your help! I'm going to have a look at the php and see if I can modify it slightly to work for our needs better, but all your help has been fantastic.

                  Thanks very much
                  Lewis
                    • 36906
                    • 34 Posts

                    No probs dude,

                    With a bit of tinkering you'd probably be able to JOIN onto your FoxyCart tables to get an overview of what people have spent etc.

                    In a bit,
                    Danny
                      • 17035
                      • 36 Posts
                      Hi Danny,

                      Thats what I'm trying to do at the moment. So far I've got this:

                      /**
                       
                      1) Make sure we have our Modx Object.
                      2) Table names - adjust for Evo.
                      3) SQL with the fields we need - adjust for Evo.
                      4) Get a file handle.
                      5) Set the header so it outputs as csv.
                      6) Loop the results.
                      7) On the first iteration, set the csv headers from the DB field names.
                      8) Create csv row.
                      9) Output to browser.
                       
                      */
                       
                      // 1)
                      if($modx) {
                       
                          // 2)
                          $table1 =  $modx->getFullTableName("web_user_attributes");
                          $table2 =  $modx->getFullTableName("web_users");
                          $table3 =  $modx->getFullTableName("foxycart_pins");
                          $table4 =  $modx->getFullTableName("foxycart_subscriptions");
                           
                          // 3)
                          $sql = "SELECT
                                  `ua`.`fullname`, 
                                  `ua`.`email`, 
                                  `ua`.`logincount`, 
                                  `ua`.`failedlogincount`, 
                                  `ub`.`pin`, 
                                  `uc`.`start_date`, 
                                  `uc`.`exp_date`, 
                                  `uc`.`frequency`, 
                                  `uc`.`status`, 
                                  DATE_FORMAT(FROM_UNIXTIME(`ua`.`thislogin`),'%W, %M %e, %Y @ %h:%i %p') as `last_login`           
                                  FROM $table1 `ua` 
                                  JOIN $table3 `ub`, $table4 `uc`, $table2 `u`
                                  ON (`u`.`id` = `ua`.`id`)
                                  ORDER BY `ua`.`fullname` ASC";
                              
                          // You could check/refine the query in PhpMyAdmin...     
                          // die($sql);
                                   
                          $result = $modx->db->query($sql);
                          if($modx->db->getRecordCount($result) >= 1) {
                       
                             // 4)
                             $stdout = fopen('php://output', 'w');
                              
                             // 5)    
                             header('Content-type: application/csv');
                             header('Content-Disposition: attachment; filename="export_userlogins_' . date("d-m-Y") . '.csv"');
                               
                             $c = 0;
                              
                             // 6)
                             while($row = $modx->db->getRow($result)) {
                              
                                 // 7)
                                 if($c == 0) { fputcsv($stdout, array_keys($row)); }
                                  
                                 // 8)
                                 fputcsv($stdout, $row); 
                                  
                                 $c++;
                             }
                       
                          } else {
                              return "None found";
                          }
                               
                          // 9)
                          fclose($stdout); 
                          exit; 
                       
                      } else {
                          return "Missing Modx Object";
                      }
                       
                      


                      Just trying to figure out what I'm doing wrong... I guess it's to do with the ON statement, but I'm having a play now to try and extend my PHP knowledge (which at the minute is nothing!)

                      Cheers
                      Lewis