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

    this is the official support channel for MaLTE - Manager Log Time Extractor - for MODX revolution. As you found it, I assume you have an issue with it.

    Link to MODX repository: http://modx.com/extras/package/malte
    Current Version: 0.0.1-pl
    Works with: any version of MODX revolution, I guess

    What does MaLTE do?
    It reads the Manager Log and calculates the total time you have been working on the site. That does NOT include work on ftp files but only actions in the manager.

    Hot do I get help?
    Please let me know what you are trying to do, how you noticed that it doesnt work the way you want it to and what you have tried until this moment to solve it.

    Cheers! [ed. note: gallenkamp last edited this post 8 years, 5 months ago.]
    • Before I put it into the MODX repository, it hast to be good code. It would not pass the initial test to make it into the official package manager. But for me it is working already. So I will puplish it there until I find the time to clean it up (work with chunks, have a parameter for the chosen user, make nice dashboard widget).

      It's not pretty yet, I know! smiley

      So here is the thing (create new snippet and name it "malte"):
      <?php
      # Snippet to read the MODX ManagerLog and spill out your work time on the site
      # USAGE: [[malte? &timeout=`15`]]
      # author: [email protected]
      # Phase 1) read Manager Log - Phase 2) also read some folders for check for file changes (css for example)
      # Let me know if you add or change things, maybe I can add them to the package in a later version!
      
      //$modx->setDebug(true);
       
      // $timeout = how many minutes gap before closing the current workunit?
      $timeout = $modx->getOption('timeout', $scriptProperties, 15);
      $tableObject = 'modManagerLog';
      
      // thank you, sottwell!
      $user = $modx->getOption('user', $scriptProperties, $modx->getUser());
      $username = $user->get('username');
      echo "User " . $username;
      $worksteps = $modx->getIterator('modManagerLog', array('user' => $user));
      
      $timeoutsec = $timeout * 60;
      
      echo "<p>";
      foreach ($worksteps as $idx => $ws) {
          $thisTime = $ws->get('occurred');
        if (isset($lastTime)) {
             $date1 = new DateTime($thisTime);
             $date2 = new DateTime($lastTime);
             $diff = strtotime($thisTime) - strtotime($lastTime);
          }
          if ($diff>=$timeoutsec) {
              // the next step is more than $timeout seconds after than the current.
              // It's a new workunit. Something like yesterday - today or "before lunch"
              echo "<div>Current workunit: ".timeformat($workunit)."</div>";
              $totalseconds += $workunit;
              echo "<div>Total time: ".timeformat($totalseconds)."</div>";
              echo "</p><p><div>New Workunit</div>";
              $workunit = 0;
          }
          else {
              $workunit += $diff;
          }
          // mute the next line to save a lot of space on the output
          echo "<br/>Entry #{$idx} with timestamp $thisTime which is $diff seconds later";
          $lastTime = $ws->get('occurred');
      }
      echo "</p>";
      
      function timeformat($seconds)
      {
        return sprintf("%d days %02d:%02d:%02d", $seconds/60/60/24, ($seconds/60/60)%24, ($seconds/60)%60, $seconds%60);
      } 


      How to use:
      - Create a new ressource
      - DONT publish it!
      - Put [[malte? &timeout=`15`]] into the content area
      - View that page

      15 is the ammount of minutes you do not need to save anything but it's still the same workunit. If you have a gap of 20 minutes, it's a new unit.

      Please: use it, try it, let me know what you want/need/miss/like.

      Cheers,

      Guido [ed. note: gallenkamp last edited this post 8 years, 6 months ago.]
      • Very interesting. Would make a nice Dashboard widget, even better a small display as a main menu item. Perhaps replace the user image with a display... the possibilities keep expanding.

        Shows me I've worked on my MODXpo presentation site for 9 hours!

        Hmmm... could also be configured to show what you spend all that time doing. What fun!

        So... needs a lexicon file, which means it needs a workspace and all of that stuff, needs to gather up output and use it in a getChunk() call, with a default chunk. Not too bad.

        Save this, to file or to a database table, and you have the basis of a billing/invoice application. Save it to file in .csv format and it pops right into a spreadsheet. Again, lots and lots of possibilities.

        Needs to have some consideration for the manager log getting cleared. File-based or database-based storage of at least some of the output. Number of units, first date, total time perhaps.

        So the "workunit" isn't based on the time working, it's based on the time NOT working. Took me a few minutes looking at the output to make sense of that.

        Wow. Once I figured out just what I'm looking at, I can see exactly what I've done on the expo presentation site since I first logged in to it. This is really interesting. [ed. note: sottwell last edited this post 8 years, 6 months ago.]
          Studying MODX in the desert - http://sottwell.com
          Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
          Join the Slack Community - http://modx.org
        • Am I correct in thinking that it only shows the record for the default Admin user (#1)? Wouldn't it be better for it to show the current user by default, with an optional property of the user to display?
          $user = $modx->getOption('user', $scriptProperties, $modx->getUser());
          $username = $user->get('username');
          echo "User " . $username;
          ...
          $worksteps = $modx->getIterator('modManagerLog', array('user' => $user));
          

          Have several people working on a site? Just create a resource for each one, with the 'user' property specifying that user. [ed. note: sottwell last edited this post 8 years, 6 months ago.]
            Studying MODX in the desert - http://sottwell.com
            Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
            Join the Slack Community - http://modx.org
          • You should put this on github, so people can work on it and make pull requests.
              Studying MODX in the desert - http://sottwell.com
              Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
              Join the Slack Community - http://modx.org
            • $detail = $modx->getOption('detail', $scriptProperties, false);
              ...
                if($detail) {
                  echo "<br/>Entry #{$idx} with timestamp $thisTime which is $diff seconds later";
                }
              
                Studying MODX in the desert - http://sottwell.com
                Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
                Join the Slack Community - http://modx.org
              • Hi Susan,

                happy you like it! I certainly do as well, but my coding skills got a bit rusty. I just published this to have a starting point. Very glad you are picking it up! I will look how to put it on github and add your changes to the initial post.

                Thank you!
                  • 3749
                  • 24,544 Posts
                  Since you're cranking out all these great extras, you might look at MyComponent, which makes it a lot easier to maintain them once you get used to it. wink
                    Did I help you? Buy me a beer
                    Get my Book: MODX:The Official Guide
                    MODX info for everyone: http://bobsguides.com/modx.html
                    My MODX Extras
                    Bob's Guides is now hosted at A2 MODX Hosting
                  • Another great feature would be a date filter. For example, time spent today, this week, last month, etc. You could probably use modSystemLogGetListProcessor. Very cool!

                    UPDATE

                    Something like the following (utilizing runProcessor()) would allow you to use all the same filters you can on Reports > Manager Actions:

                    e.g. Year to Date (2015 forward):
                    [[malte? &timeout=`15` &detail=`0` &dateStart=`2015-01-01`]]


                    You can now also pass in user by username or user id. Also, it has been converted to proper Snippet form (return vs. echo)

                    <?php
                    
                    # Snippet to read the MODX ManagerLog and spill out your work time on the site
                    # USAGE: [[malte? &timeout=`15`]]
                    # author: [email protected]
                    # Phase 1) read Manager Log - Phase 2) also read some folders for check for file changes (css for example)
                    # Let me know if you add or change things, maybe I can add them to the package in a later version!
                    
                    //$modx->setDebug(true);
                    
                    // thank you, sottwell!
                    $user = $modx->getOption('user', $scriptProperties, $modx->getUser());
                    if (!($user instanceof modUser)) {
                        $key = is_numeric($user) ? 'id' : 'username';
                        $user = $modx->getObject('modUser', array($key => $user));
                        if (!($user instanceof modUser)) {
                            return 'Defined user was not found.';
                        }
                    }
                    // Snippet properties
                    $timeout = $modx->getOption('timeout', $scriptProperties, 15); // gap (in minutes) before closing the current workunit
                    $detail = $modx->getOption('detail', $scriptProperties, false);
                    
                    // Processor properties
                    $properties = array(
                        'user' => $user->get('id'),
                        'limit' => $modx->getOption('limit', $scriptProperties, 0), // Unlimited
                        'start' => $modx->getOption('start', $scriptProperties, 0),
                        'dateStart' => $modx->getOption('dateStart', $scriptProperties, false),
                        'dateEnd' => $modx->getOption('dateEnd', $scriptProperties, false),
                        'actionType' => $modx->getOption('actionType', $scriptProperties, false),
                        'sort' => $modx->getOption('sort', $scriptProperties, 'occurred'),
                        'dir' => $modx->getOption('dir', $scriptProperties, 'ASC'),
                        'dateFormat' => 'Y-m-d H:i:s',
                    );
                    
                    // Fetch log data
                    $response = $modx->runProcessor('system/log/getlist', $properties);
                    
                    if ($response->hasMessage()) {
                        $message = $response->getMessage();
                    }
                    
                    $success = true;
                    $errors = array();
                    if ($response->isError()) {
                        foreach ($response->getFieldErrors() as $error) {
                            $errors[] = $error->message;
                        }
                        $success = false;
                    }
                    
                    if ($success) {
                        $results = $modx->fromJSON($response->getResponse());
                        $output = '<h4>'.$user->get('username').'</h4>';
                        $timeoutsec = $timeout * 60;
                    
                        $output .= '<p>';
                        foreach ($results['results'] as $log) {
                            $thisTime = $log['occurred'];
                            if (isset($lastTime)) {
                                $date1 = new DateTime($thisTime);
                                $date2 = new DateTime($lastTime);
                                $diff = strtotime($thisTime) - strtotime($lastTime);
                            }
                            if ($diff >= $timeoutsec) {
                                // the next step is more than $timeout seconds after than the current.
                                // It's a new workunit. Something like yesterday - today or "before lunch"
                                $output .= '<div>Current workunit: '.timeformat($workunit).'</div>';
                                $totalseconds += $workunit;
                                $output .= '<div>Total time: '.timeformat($totalseconds).'</div>';
                                $output .= '</p><p><div>New Workunit</div>';
                                $workunit = 0;
                            } else {
                                $workunit += $diff;
                            }
                            // mute the next line to save a lot of space on the output
                            if ($detail) {
                                $output .= "<br/>Entry #{$log['id']} with timestamp $thisTime which is $diff seconds later";
                            }
                            $lastTime = $log['occurred'];
                        }
                        $output .= '</p>';
                    
                        return $output;
                    } else {
                        $log = $message.' '.print_r($errors, true);
                        $modx->log(modX::LOG_LEVEL_ERROR, $log);
                    
                        return $log;
                    }
                    
                    function timeformat($seconds)
                    {
                        return sprintf('%d days %02d:%02d:%02d', $seconds / 60 / 60 / 24, ($seconds / 60 / 60) % 24, ($seconds / 60) % 60, $seconds % 60);
                    }
                    
                    [ed. note: pixelchutes last edited this post 8 years, 5 months ago.]
                      Mike Reid - www.pixelchutes.com
                      MODx Ambassador / Contributor
                      [Module] MultiMedia Manager / [Module] SiteSearch / [Snippet] DocPassword / [Plugin] EditArea / We support FoxyCart
                      ________________________________
                      Where every pixel matters.
                    • Hi Mike,

                      thank you for the update! Admitting I dont know what people really need, I tend to leave all the options away that I would not need or those that does not make sense to me. Limit, start, sort are some of those, like they refer to the single action that is writtern in the database. I cant think of a case where I would need that.

                      I kept it in the code as it does no harm, but I'd like to know how those can be useful smiley

                      An hour before, I made a MODX EXtra of it and umpladed it to the official repository. Hoping it passes the testing. I will keep you updated here of course!

                      Cheers and thank you for the support!

                      Guido