We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 14877
    • 110 Posts
    Following along with refining the "User System" for my first MODx site (a hand-coded site I’m converting)...

    The "system" is successfully sending notification e-mail messages to an administrative account when a user registers and when a user updates his profile. Both e-mail messages contain the relevant information about the user (username, fullname, email, etc.). Now I’m attempting the final step, which is to send a notification e-mail message when the user activates his account (so that an admin can decide whether to add the user to a special user group).

    Having RTFM (rtfm.modx.com smiley ), the way to do this appeared straightforward:

    - Write a plugin
    - Have it listen for the "OnUserActivate" event

    So, I did that (see code below). The notification e-mail message is sent, but the user information was not being displayed (the placeholder tags were unresolved).

    I then added some debug code to display "stuff" at the end of the e-mail message (the first debugging technique I ever learnt!). It appeared my $formPlaceHolderPairs array only had the date entry I was adding as a time-stamp. So I then dumped the $scriptProperties array using the "foreach" technique shown in the code below. That confirmed, as per the documentation, that a "KEY: user" was being passed; but, of course, the value could not be converted to a string (it’s a handle) and nothing was displayed for the "VALUE:".

    Then (back) to the current form of the plugin code (shown in full).

    <?php
    /* Plugin for Login:Activation. Sends an e-mail message regarding the activation to the membership committee.
    
    Notes:
      1. Refer to the documentation for the "login" extra for basic documentation.
      2. Refer to the documentation for "plugins" (under Basic Development).
    
    Notes:
      1. This code is to be run when the system event, "OnUserActivate" is fired.
      2. Its single "user" paramete contains the newly-activated modUser object.
    */
    
    $actUser = $modx->getOption('user', $scriptProperties, '');
    $formPlaceHolderPairs = $actUser->getSettings();
    
    $formPlaceHolderPairs['date'] = date('Y-m-d H:i');
    
    /* TESTING */
    
    $output = 'formPlaceHolderPairs...<br />';
    foreach($formPlaceHolderPairs as $PHKey => $PHValue) {
      $output .= '(KEY: ' . $PHKey . ', VALUE: ' . $PHValue . ');<br />';
    }
    /* END TESTING */
    
    $formTpl = $modx->getObject('modChunk', array( 'name' => 'wccrUserActiveNotifyTpl'));
    $message = $formTpl->process($formPlaceHolderPairs);
    
    /* TESTING */
    $message .= '<p> <br />' . $output . '</p>';
    /* END TESTING */
    
    $emailSender = $modx->getOption('emailsender');
    $wccrLoginNotify = $modx->getOption('wccr_login_notify');
    
    $modx->getService('mail', 'mail.modPHPMailer');
    $modx->mail->set(modMail::MAIL_BODY, $message);
    $modx->mail->set(modMail::MAIL_FROM, $emailSender);
    $modx->mail->set(modMail::MAIL_FROM_NAME, 'WCCR Web Site User Admin');
    $modx->mail->set(modMail::MAIL_SENDER, 'WCCR Web Site User Admin');
    $modx->mail->set(modMail::MAIL_SUBJECT, 'WCCR: New User Activated');
    $modx->mail->address('to', $wccrLoginNotify);
    $modx->mail->setHTML(true);
    if (!$modx->mail->send()) {
        $modx->log(modX::LOG_LEVEL_ERROR,'An error occurred while trying to send the email: '.$err);
    }
    $modx->mail->reset();
    
    return true;


    I wonder if someone can confirm my understanding of my critical lines (reproduced below) which are meant to implement what the documentation says: "ConfirmRegister also fires the OnUserActivate plugin event after the User is activated, and passes in a ’user’ parameter, which contains the newly-activated modUser object."

    The first line gets the modUser object (i.e. a handle to the object).
    The second line creates an associative array of attribute-name, attribute-value pairs (i.e. "username", "fullname", etc.).

    Or do I just not understand at all what is going on?

    $actUser = $modx->getOption('user', $scriptProperties, '');
    $formPlaceHolderPairs = $actUser->getSettings();


    Oh, it will (perhaps?) help to know that when the activation link is clicked and the activation page displayed (with the user logged in), the following two lines are added to the Error Log:

    [2010-12-27 23:26:56] (ERROR @ /index.php) No foreign key definition for parentClass: modUser using relation alias: modUserSetting
    [2010-12-27 23:26:56] (ERROR @ /index.php) [OnUserActivate]1


      __________________
      JRG
      • 3749
      • 24,544 Posts
      It’s a logical assumption, but in the plugin, the user object is available as $user and $scriptProperties is not available.

      This should work as the first line:

      $formPlaceHolderPairs = $user->getSettings();
        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
        • 14877
        • 110 Posts
        Well, I’d got the code working before I saw Bob’s response. I haven’t checked out Bob’s suggestion, but I suspect there may be a problem. Also, it bothers me that it relies on a Global variable rather than using a parameter passed to the "listener".

        After spending time scanning the documentation (again!) and browsing some of the code, I came up with a solution that works and relies on the parameter being passed (there surely is a reason for passing the parameter!).

        <?php
        /* Plugin for Login:Activation. Sends an e-mail message regarding the activation to the membership committee.
        
        Notes:
          1. Refer to the documentation for the "login" extra for basic documentation.
          2. Refer to the documentation for "plugins" (under Basic Development).
        
        Notes:
          1. This code is to be run when the system event, "OnUserActivate" is fired.
          2. Its single "user" paramete contains the newly-activated modUser object.
        */
        
        $actUser = $modx->getOption('user', $scriptProperties, '');
        $modx->user = &$actUser;
        $modx->getUser();
        $profile = $modx->user->getOne('Profile');
        if (empty($profile)) {
            $modx->log(modX::LOG_LEVEL_ERROR,'OnUserActivate Error: Could not retrieve profile for user: ' . $modx->user->get('username'));
            return true;
        }
        
        $formPlaceHolderPairs = $profile->toArray();
        $formPlaceHolderPairs['username'] = $modx->user->get('username');
        $formPlaceHolderPairs['date'] = date('Y-m-d H:i');
        
        $formTpl = $modx->getObject('modChunk', array( 'name' => 'wccrUserActiveNotifyTpl'));
        $message = $formTpl->process($formPlaceHolderPairs);
        
        $emailSender = $modx->getOption('emailsender');
        $wccrLoginNotify = $modx->getOption('wccr_login_notify');
        
        $modx->getService('mail', 'mail.modPHPMailer');
        $modx->mail->set(modMail::MAIL_BODY, $message);
        $modx->mail->set(modMail::MAIL_FROM, $emailSender);
        $modx->mail->set(modMail::MAIL_FROM_NAME, 'WCCR Web Site User Admin');
        $modx->mail->set(modMail::MAIL_SENDER, 'WCCR Web Site User Admin');
        $modx->mail->set(modMail::MAIL_SUBJECT, 'WCCR: New User Activated');
        $modx->mail->address('to', $wccrLoginNotify);
        $modx->mail->setHTML(true);
        if (!$modx->mail->send()) {
            $modx->log(modX::LOG_LEVEL_ERROR,'An error occurred while trying to send the email: '.$err);
        }
        $modx->mail->reset();
        
        return false;


        Does anyone know if there are either built-in PHP constants or ones globally defined in MODx for "SUCCESS" and "FAILURE"? I prefer my code to return something meaningful and "return false;" is counter-intuitive. I’d prefer something like "return SUCCESS;" (if not returning a specific value) and "return FAILURE;".
          __________________
          JRG
        • PHP functions usually return 1 or 0.
            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
            • 3749
            • 24,544 Posts
            You definitely don’t want to be reassigning $modx->user, which is set by MODx to be you.

            Instead of all this this:

            $actUser = $modx->getOption('user', $scriptProperties, '');
            $modx->user = &$actUser;
            $modx->getUser();
            $profile = $modx->user->getOne('Profile');
            

            Try this:

            $profile = $user->getOne('Profile');


            I suspect that the return value is ignored, though I haven’t checked. To be on the safe side, plugins should generally return true on success and false on failure.
              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
              • 14877
              • 110 Posts
              Quote from: BobRay at Dec 28, 2010, 07:41 PM

              You definitely don’t want to be reassigning $modx->user, which is set by MODx to be you.

              Instead of all this this:

              $actUser = $modx->getOption('user', $scriptProperties, '');
              $modx->user = &$actUser;
              $modx->getUser();
              $profile = $modx->user->getOne('Profile');
              

              Try this:

              $profile = $user->getOne('Profile');


              I suspect that the return value is ignored, though I haven’t checked. To be on the safe side, plugins should generally return true on success and false on failure.

              This is Login Activation. The event handler being coded is supposedly being run after the user-id has been activated. Leaving aside whatever this event handler is going to do, one needs to deal with the following:


              • We are modifying how code involving security runs (this is an event handler in the Login system).
              • While in theory, one would expect the event handler to be running as the user who has just been activated, the event handler is actually still running as the "anonymous" user (I checked that by putting stuff in to the e-mail that I am using the event handler to send). Getting information about the anonymous user is, of course, not the objective.
              • At the end of the activation process (which is, in theory, where one is when onUserActivate is fired), the user is left in the logged in state. Try it out. According to comments in the Login system code, it is to allow users to be redirected to shopping cart software pages.
                __________________
                JRG
                • 14877
                • 110 Posts
                I wanted to give a reasoned reply to Bob, so I changed the code to exactly what he suggested. That’s putting aside that even if it works perfectly, I have an issue with using Global Variables (a no-no). I then did a registration and an "activation". The result of the activation was to report:

                User Name: (anonymous)
                Real Name: Petty Fogger
                E-mail Address: xxxxxxx
                Date: 20111-01-01 17:13

                So Bob’s nice one-liner reported most of the information I was interested in, but failed to identify the "user". Using the global, "$user", gave some of the data, but not all of it.

                I imagine there is a way around the "username", but I still have the same issue. I wish I could express this in a way that was understandable: Using a "global variable" is WRONG. We should be able to get all the data we are interested in by following a trail that starts out with the parameter being passed to the event handler. I’ve just, well I’m about to, change the code back to what I had.
                  __________________
                  JRG
                  • 3749
                  • 24,544 Posts
                  Good points jrg, but I don’t think the $user object qualifies as a global variable. As I understand it, it’s passed directly to the event handler as an argument in $modx->invokeEvent(), then on to the plugin itself. In theory, it is not the user who is visiting the site, it is the user that’s just been activated.

                  $modx->user, OTOH, is another animal. It’s created by MODx on each page request and it *is* the front-end user.

                  I’m not sure how you ended up with ’(anonymous’) for the username. That’s the username in $modx->user for users in the front end who are not logged in. I don’t think it should be there in $user->get(’username’) in a plugin that’s been sent the $user object, but I’m not sure.

                  If you were previewing from the Manager, BTW, that might have thrown things off.
                    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
                    • 14877
                    • 110 Posts
                    Quote from: BobRay at Jan 02, 2011, 04:16 AM

                    Good points jrg, but I don’t think the $user object qualifies as a global variable. As I understand it, it’s passed directly to the event handler as an argument in $modx->invokeEvent(), then on to the plugin itself. In theory, it is not the user who is visiting the site, it is the user that’s just been activated.

                    $modx->user, OTOH, is another animal. It’s created by MODx on each page request and it *is* the front-end user.

                    I’m not sure how you ended up with ’(anonymous’) for the username. That’s the username in $modx->user for users in the front end who are not logged in. I don’t think it should be there in $user->get(’username’) in a plugin that’s been sent the $user object, but I’m not sure.

                    If you were previewing from the Manager, BTW, that might have thrown things off.

                    Nope. Two complete separate browser invocations. Well, better than that: visiting the front-end via the Safari browser; visiting the manager via the Firefox browser.

                    I’m going to try and find the appropriate forum and start another thread. Some of the implications of our discussion here are bothering me. That post is: http://modxcms.com/forums/index.php/topic,59253.0.html
                      __________________
                      JRG
                      • 14877
                      • 110 Posts
                      OK Bob, the $user object does in fact work fine. I still had a reference to modx->user in order to retrieve the "username" which is not included (for some reason) as part of the "Profile". I changed that to also be $user and everything is working.

                      I still have the issue with globals (see the separate thread I referenced) and the fact I was not able, for some reason I don’t fathom, to use the parameter being passed to access the information instead of having to know about "$user". Perhaps I’m missing some level of indirection/dereferencing. I’ll try and sort that out.
                        __________________
                        JRG