Add user field [api]

Discussion in 'aMember Pro v.4' started by amonies, Dec 7, 2012.

  1. amonies

    amonies New Member

    Joined:
    Nov 30, 2012
    Messages:
    23
    Id like to add a field to the user object, similar to login, email, etc. However, I do NOT want this field to be something the user can edit - it must be for reference only.

    This will be used to keep track of what server each person is on. Id like to use the usual amember API so I may integrate this during account creation and it will allow me to rotate account creation across multiple servers.

    Is there a 'best practice' for doing this? Or should I just open PHPMyAdmin and have at creating the field manually?

    Thanks

    Edit - Also, a second question.
    When the SubscriptionRemoved event is called, it also appears to call SubscriptionDeleted. Triggering both of these events is confusing my server you could say.
    How could I explicitly check which function was called, so I may prevent this?
  2. alex

    alex Administrator Staff Member

    Joined:
    Jan 24, 2004
    Messages:
    6,020
    1. Just add a field from aMember CP -> Add Fields. Choose SQL field, and you can access it like any existing amember am_user table fields. It will not appear in signup/profile forms until you manually add it in form editor.

    2. Sorry for confusing names.
    subscriptionDeleted is called when customer loses access to a subscription (for example access expired). User may still have access to other products in the same time.

    subscriptionRemoved is called when entire customer records is removed from database! So you may choose to also remove user and related info from integrated database.
  3. amonies

    amonies New Member

    Joined:
    Nov 30, 2012
    Messages:
    23
    you
    thank on the field question
    the events, i meant that manually deleting someone from the admin cp calls both events, not just the removed event. this confuses my script. how can i differentiate between which event was originally triggered?to my understandig the deleted event is only called when an subscription is unpaid for ot expires naturally. removed is only called when manually removed from the user list in the admin panel. right?
  4. amonies

    amonies New Member

    Joined:
    Nov 30, 2012
    Messages:
    23
    my phone doesnt seem to like this post field :(
  5. alex

    alex Administrator Staff Member

    Joined:
    Jan 24, 2004
    Messages:
    6,020
    aMember first deletes all subscriptions for user (which triggers deleted events), then removes the user record itself. It happens in the same session, in the same run of PHP script, so you may use a variable to determine and avoid double run.
  6. amonies

    amonies New Member

    Joined:
    Nov 30, 2012
    Messages:
    23
    Well thats good to know, thanks!
    And lastly, what is the preferred method to update the field?
    Obviously I can use sql statement but so far I see the db functions for reading but not writing yet.

    thanks, again!
  7. amonies

    amonies New Member

    Joined:
    Nov 30, 2012
    Messages:
    23
    Nevermind, got it.
    Heres what my PHP line looks like for future reference:

    Code:
    $setServer = Am_Di::getInstance()->db->query("UPDATE `am_user` SET server = '". $server[$srv]. "' WHERE login = '". $user->login. "'");
    
  8. alex

    alex Administrator Staff Member

    Joined:
    Jan 24, 2004
    Messages:
    6,020
    There are better methods to do the same.

    The same with vars auto-escaping:
    PHP:
    $db  Am_Di::getInstance()->db;
    $db->query("UPDATE ?_user SET server=? WHERE login=?",
            
    $server[$srv], $user->login);
    and how aMember do it inside - update entire user record, all changes will be saved:
    PHP:
    $user->server $server[$srv];
    $user->update();
    or update one field only (will result to same query as you introduced):
    PHP:
    $user->updateQuick('server'$server[$srv]);
  9. amonies

    amonies New Member

    Joined:
    Nov 30, 2012
    Messages:
    23
    Thank you for all the help Alex!

    I really need a way to track the exact triggering/initial event.

    For example, removing their membership first causes their 3rd party account to be suspended, then their user records are deleted causing them to be deleted on the other site too. Essentially double the overhead and messy making remote calls.

    Also, when a user subscribes it calls the change password event first. This is fine and I can get the password fine - but now when it calls the subscriptionAdded event and I try to get the password, it gives me back the salted hash instead of the plaintext password. Driving me nuts.
    This is really another instance of a duplicate call that should be avoidable.

    Edit - $user->pass output example: $P$B6Xe/rQskEYOYRfWXSnHYfnWTWc.PQ0

    If you can make any future updates where we can track exactly what the initial event is that would be great.
    And if you have any idea on how I can read the password again or why its doing that please let me know.

    Thanks as always
  10. amonies

    amonies New Member

    Joined:
    Nov 30, 2012
    Messages:
    23
    As an update, I tried commenting out my hook function for changepassword and it is still giving me the non-plaintext password output.

    Cant think of anything that would have caused this. It was working before, and now it randomly isnt. o.0
  11. alexander

    alexander Administrator Staff Member

    Joined:
    Jan 8, 2003
    Messages:
    6,274
    Plain text password is available only when user specify it (in signup, login or change password form ).
    In all other cases it will not be available.
    If you need plain_text password every time in your plugin add this:
    PHP:
        public function getPasswordFormat()
        {
            return 
    SavedPassTable::PASSWORD_PLAIN;
        }
    then in your plugin code whereever you need to access plain text password use this:
    $pass = Am_Di::getInstance()->savedPassTable->findSaved($user, SavedPassTable::pASSWORD_PLAIN);
  12. amonies

    amonies New Member

    Joined:
    Nov 30, 2012
    Messages:
    23
    Unfortunately, that is not working for me.
    I even tried
    Code:
    $pass = Am_Di::getInstance()->savedPassTable->findSaved($user, SavedPassTable::PASSWORD_PLAIN)->pass
    
    which apparently worked for someone else here.

    If it matters, I do not have my plugin setup as a class/extension at this time.
  13. amonies

    amonies New Member

    Joined:
    Nov 30, 2012
    Messages:
    23
    For reference, I am not showing it is returning any value at all either way.
  14. alexander

    alexander Administrator Staff Member

    Joined:
    Jan 8, 2003
    Messages:
    6,274
    Can you paste exact code which you are truing to use then? And also explain where do you have that code.
  15. amonies

    amonies New Member

    Joined:
    Nov 30, 2012
    Messages:
    23
    It is in the plugins/misc folder.
    Looks pretty much like this:
    Code:
    function  createAccount(Am_Event_SubscriptionAdded $event) {
        $user = $event->getUser();
        $pass = Am_Di::getInstance()->savedPassTable->findSaved($user, SavedPassTable::PASSWORD_PLAIN);
    }
     
    Am_Di::getInstance()->hook->add(Am_Event::SUBSCRIPTION_ADDED, 'createAccount');
    
    Simple enough - pass is always null. I tried adding the getPasswordFormat function as well to no luck. I am guessing that is an event that is supposed to be caught by extending a class?
  16. alex

    alex Administrator Staff Member

    Joined:
    Jan 24, 2004
    Messages:
    6,020
  17. alex

    alex Administrator Staff Member

    Joined:
    Jan 24, 2004
    Messages:
    6,020
    Universal solution, how to get plain text password saved and retreived

    application/default/plugins/misc/plaintext-pass.txt
    PHP:
    class Am_Plugin_PlaintextPass extends Am_Plugin
    {
       function 
    onSetPassword(Am_Event_SetPassword $event)
       {
           
    $db $this->getDi()->db;
           
    $db->query("INSERT INTO ?_saved_pass SET
                   user_id=?d, format='plain', pass=?, salt=null
                   ON DUPLICATE KEY UPDATE
                          pass=VALUES(pass)
                  "
    ,
                    
    $event->getUser()->user_id,  $event->getPassword());
       }
     
      
    // to trigger this event, add or delete "access" at: Edit User -> Payments, scroll down
       
    function onSubscriptionChanged($event)
      {
            
    $user $event->getUser();
            
    $pass $this->getDi()->savedPassTable->findSaved($user'plain');
            
    $this->getDi()->errorLogTable->log("pass: $pass");  // look at aMember Cp -> Logs
      
    }
    }
     
     
  18. amonies

    amonies New Member

    Joined:
    Nov 30, 2012
    Messages:
    23
    This worked beautifully.

    For reference, didnt everything run in the same instance? I tried to use a global variable to hold the plaintext password temporarily since setpassword is apparently called before subscriptionadded, but it didnt work.

    This certainly will and does, I just want to check and make sure before and continue with this 'heavier' solution. If so, Ill just remove the plaintext entry after I grab it as I only need it as a 1 time thing during setup.
  19. alexander

    alexander Administrator Staff Member

    Joined:
    Jan 8, 2003
    Messages:
    6,274
    No it is not executed in the same instance. So you can't do this via global variables.
  20. amonies

    amonies New Member

    Joined:
    Nov 30, 2012
    Messages:
    23
    Thanks.

    Now, Im adding other fields I do not need to store.
    For the DATA (non-sql fields) how do I access this value from my hook? I only need to access this value once during checkout in the subscription added event.

Share This Page