We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 26503
    • 620 Posts
    So I have extended modUser [successfully] but I also need to make use of the modActiveDirectory extra, both work great, but not together... the problem is that while creating a user account with the register extra I have a post hook that changes the user's class key to 'extUser' when a user logs in using their Active Directory credentials they are added with a class key of 'modActiveDirectoryUser'. Naturally none of the extUser functions or additions are available to these users!

    How do I allow modActiveDirectoryUser users access to the extUser classes???
      *** Not just websites, we also create signage, banners, print, trade show displays and more! ***

      Sean Kimball CLP, CLS.
      Technical Director / Sr. Developer | BigBlock Studios
      ._______________________________________________.
      Bigblock Studios http://www.bigblockstudios.ca Web site design & development.
      27-1300 King Street East. Box 167 Oshawa, Ontario L1H8J4 Canada.
      phone/fax: 905-426-5525
      • 3749
      • 24,544 Posts
      I don't know anything about modActiveDirectory, but it sounds like it also extends modUser. I don't know of any way that a user can be both a modActiveDirectoryUser and an extUser at the same time.
        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
        • 26503
        • 620 Posts
        I'm not sure what exactly needs doing, but right from the docs:

        http://rtfm.modx.com/revolution/2.x/developing-in-modx/advanced-development/extending-moduser

        It is completely possible to have multiple extended modUser systems active at the same time. It would even be feasible to extend Jason Coward's rpx extension into a hybrid system utilizing the benefits of both systems. It is also completely possible to have multiple extended modUser applications running autonomously. This is simply done by following this process for each of your extensions, changing only the "class_key" field to reflect the extended class belonging to each respective user.

        I'm guessing we have to modify:

        class modActiveDirectoryUser extends modUser {
        
            function __construct(xPDO & $xpdo) {
                parent :: __construct($xpdo);
                $this->set('class_key','modActiveDirectoryUser');
            }



        Actually after a bit of testing, there is a bit in onauthentication.php which checks to see if a user has the modActiveDirectoryUser class key & dies if they don't. we need to get rid of this [as I don't see any other purpose for it!!]

        /* if not an AD user, skip */
        /*
        if ($user->get('class_key') != 'modActiveDirectoryUser') {
            $username = is_object($user) ? $user->get('username') : $user;
            $modx->log(modX::LOG_LEVEL_INFO,'[ActiveDirectory] User "'.$username.'" is not a modActiveDirectoryUser and therefore is being skipped.');
            $modx->event->output(false);
            return;
        }
        */


        Then if we change the constructor in nodactivedirectoryuser.class.php

            function __construct(xPDO & $xpdo) {
                parent :: __construct($xpdo);
                //$this->set('class_key','modActiveDirectoryUser');
        	    $this->set('class_key','extUser');
            }


        That will save/create the new user with the correct class key [correct for our uses... right below the constructor is a function to sync the profile... all we need to do with that is to add the extUser fields & we should be good to go! [ed. note: sean69 last edited this post 12 years, 2 months ago.]
          *** Not just websites, we also create signage, banners, print, trade show displays and more! ***

          Sean Kimball CLP, CLS.
          Technical Director / Sr. Developer | BigBlock Studios
          ._______________________________________________.
          Bigblock Studios http://www.bigblockstudios.ca Web site design & development.
          27-1300 King Street East. Box 167 Oshawa, Ontario L1H8J4 Canada.
          phone/fax: 905-426-5525
          • 3749
          • 24,544 Posts
          I'll be interested to see if that works.

          If I'm understanding the docs you quote, it could be simpler than that as long as you don't need a user to be both at exactly the same time. If AD calls getObject('modActiveDirectoryUser', 12) and your other code calls getObject('extUser', 12), they might both get the same user object. They'd also both get their own related "profile" when calling $user->getOne('Whatever').

          If you *do* need the user to be both in the same code, you could always call getObject() twice and have both objects.

          A key question is whether getObject('extUser') would retrieve objects with the modActiveDirectoryUser class_key. It might, since both extend modUser. It's worth checking, and should be easy for you since you have both packages installed. I guess another key question is: if you leave the class_key as modUser, would something like this work:

          $user = modx->getObject('modUser', array('username' => 'bobray'));
          $user->set->('class_key','extUser');
          $fields = $user->getOne('Data'); /* (extUser extended fields alias) */


          Another way to go that would definitely work would be to have modActiveDirectoryUser extend extUser or vice versa. (I think I'd do the vice versa.) The resulting object should have both related objects with all their fields. As long as both packages are registered in extension_packages (or the new equivalent -- have a record in the modx_extension_packages table), they'd both be loaded at all times and any code you wrote should work with them.

          So your easiest fix, imo, would be:

          1. Leave your schemas and class files alone except for having extUser extend modActiveDirectoryUser
          2. Set the class_key to extUser when you create a new user (and set it for all existing users).

          The ActiveDirectory code can still call getObject('modActiveDirectgoryUser') since all the users are in a class descended from that and will have its related object(s),. All your other code will have extUsers to deal with and should work fine.
            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
            • 26503
            • 620 Posts
            Hi Bob;

            I did get it working as I set out in my previous post. but in order to get any extended user extensions working the onauthentication.php file needs to be modified. The little bit checking if the user is an AD user has to go.

            As far as setting the class_key to extUser in the modactivedirectoryuser.class.php, well I can probably leave the class file alone and force jack the extUser class_key in a plugin after login.

            Gonna make a feature enhancement/request to Shawn's github. [remove the AD user check and option to set the new user class_key after auth!]
              *** Not just websites, we also create signage, banners, print, trade show displays and more! ***

              Sean Kimball CLP, CLS.
              Technical Director / Sr. Developer | BigBlock Studios
              ._______________________________________________.
              Bigblock Studios http://www.bigblockstudios.ca Web site design & development.
              27-1300 King Street East. Box 167 Oshawa, Ontario L1H8J4 Canada.
              phone/fax: 905-426-5525
              • 3749
              • 24,544 Posts
              I agree on getting rid of the class_key check, but it seems like there should be a more generic solution to the main problem. It would be nice if people didn't have to be telling one extra to use another extra's class_key. I think that's bound to fail if you have more than two extras that extend modUser.
                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
                • 3749
                • 24,544 Posts
                BTW, I think I've found a method that lets you leave the class_key at modUser (or whatever). You can manage it so that your code doesn't care what the class_key is, though you have to be careful to save only the related objects (that's almost always all you want to save anyway).

                Basically, you create the kind of object you need from the modUser object on the fly, using toArray() and fromArray(). Then you can call your methods on that object at will.

                It works because when you extend modUser the way we do, your basically creating an extra profile without changing the user object fields. That makes it easy to create a duplicate object of the correct class for your code.

                I've tested it and it seems to work. It also avoids the hassle of crashing the Manager, crapping up the error log, or not being able to log in after you change the modUser class key, but before the cache is cleared. Better yet, it means that you can have lots of different extended user objects working together without conflict if they all use this method.

                Code examples here: https://forums.modx.com/thread/92481/extended-modx-objects-question#dis-post-505313
                  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
                  • 28042 ☆ A M B ☆
                  • 24,524 Posts
                  So which method are you talking about here? #3? This sounds like good Cookbook material.
                  $user = $modx->getObject('modUser', 1);
                  $fields = $user->toArray();
                  $fields['class_key'] = 'extUser';
                   
                  $extUser = $modx->newObject('extUser');
                  $extUser->fromArray($fields, "", true, true);
                   
                  $data = $extUser->getOne('Data');
                    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
                    Yes, but it's too soon for that. I'm still trying to work out how to do queries that work. You need to be able to find users based on the extra fields even though the class_key is 'modUser'. I've got that working, but I can't seem to get the extra fields out of the result.

                    This works to get me the correct user:

                    $c = $modx->newQuery('modUser');
                    $c->sortby($sortBy, $sortDir);
                    $c->innerJoin('userData', 'userData', array('modUser.id = userData.userdata_id'));
                    $c->leftJoin('modUserProfile', 'Profile');
                    $c->where(array('userData.firstName' => 'Bob'));
                    

                    But it falls down here:
                    $user = $modx->getCollection('modUser', $c);
                    
                    foreach($users as $user) {
                    
                    $fields = $user->toArray();  // fine so far;
                    
                       if ($user->Profile) {
                           $fields = array_merge($fields, $user->Profile->toArray());
                       } else {
                           echo 'No Profile';
                       }
                       /* Still OK  at this point */
                    
                       /* This prints 'No userData' */
                       if ($user->userData) {
                           $fields = array_merge($fields, $user->userData->toArray());
                       } else {
                           echo 'No userData';
                       }
                    }
                    


                    So I'm getting the fields from the profile, but not the extra fields. I think I need an xPDO query guru. I can convert the object using the code in your post above and use getOne('Data');, but I'm hoping to avoid an extra query for each user.

                      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
                      • 4172
                      • 5,888 Posts
                      I think (didn't test that) migxLoopCollection should build a working xpdo-query with this:

                      [[!migxLoopCollection? 
                        &classname=`modUser`
                        &joins=`[
                          {"alias":"userData","classname":"userData","on":"modUser.id = userData.userdata_id"},
                          {"alias":"Profile"}
                        ]`
                        &where=`{"userData.firstName":"Bob"}`
                      ]]


                      you should all placeholders for userData - fields have prefixed with userData_
                      and all Profile - fields with Profile_ in your tpl

                      I think your query is missing some

                      $c->select($modx->getSelectColumns('modUser'));
                      $c->select($modx->getSelectColumns('userData','userData','userData_'));
                      $c->select($modx->getSelectColumns('modUserProfile','Profile','Profile_'));


                      which does migx automatically with this line in its prepareJoins - method:

                      $c->select($this->modx->getSelectColumns($joinclass, $jalias, $jalias . '_', $selectfields));

                      [ed. note: Bruno17 last edited this post 12 years, 2 months ago.]
                        -------------------------------

                        you can buy me a beer, if you like MIGX

                        http://webcmsolutions.de/migx.html

                        Thanks!