We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 44922
    • 131 Posts
    Hi. In Modx 2.2.14, we've successfully created a snippet which compares a resource's TV value with the [[Profile]] extras user extended fields. If they match, an email is sent. Great! But we now want this to work also where:
    #an extended field has multiple values and the TV has just one
    and also where
    #an extended field has multiple values and the TV also has multiple

    We have got the User Profile to accept multiple values by using <select id="Sector" name="Sector[]" multiple> as part of the form on the UpdateProfile page. We can extend the TV by using Multi-select and double pipe all the different options.
    In php, with arrays you could use "in_array" to find one value in an array and "array_intersect to return True if there's a match between two arrays. In Modx, I'm stuck!

    When the TV and the extended field both have just one value:
    $Sector = $resource->getTVValue('Sector');
    $Function = $resource->getTVValue('Function');
    //gets the TV value

    $profiles = $modx->getCollection('modUserProfile');
    foreach ($profiles as $profile) {
    $extended = $profile->get('extended');
    // Loop though the Profiles and select qualified users & Get extended profile

    if ($extended['Sector'] == $Sector || $extended['Function'] == $Function)
    {send an email}
    // sends email if either sector or function TV of a published resource matches the extended user profile field

    Could anybody point us in the right direction if we wanted to return "true" for a match from multiple values for an extended field with either a single TV or a TV with multi-select options?
    xPDO Revo Object methods are a little complex for my understanding. Thanks!
      • 4172
      • 5,888 Posts
      I think your best option would be to store the extended fields into a custom-table,
      one way is to use Bob Ray's classExtender.

      Than its easy to get them with something link that:

      <?php
      
      $sectors = explode('||',str_replace(',','||',$resource->getTVValue('Sector')));
      $functions = explode('||',str_replace(',','||',$resource->getTVValue('Function')));
      
      $userClass = $modx->getOption('userDataClass', $sp, 'userData');
      
      $c = $modx->newQuery($userClass);
      $c->where(array($userClass.'.sector:IN'=>$sectors,$userClass.'.function:IN'=>$functions));
      
      if ($users = $modx->getCollectionGraph($userClass, '{"Profile":{},"User":{}}', $c)){
          foreach ($users as $user){
              //do something with the user here:
              $user_array = $user->toArray();
          }
      }



        -------------------------------

        you can buy me a beer, if you like MIGX

        http://webcmsolutions.de/migx.html

        Thanks!
        • 4172
        • 5,888 Posts
        sorry, I think I did missread your question, I think it should be more like that:

        <?php
        
        $sector = $resource->getTVValue('Sector');
        $function = $resource->getTVValue('Function');
        
        $userClass = $modx->getOption('userDataClass', $sp, 'userData');
        
        $c = $modx->newQuery($userClass);
        $c->where(array($userClass.'.sector:LIKE'=>'%'.$sector.'%',$userClass.'.function:LIKE'=>'%'.$function.'%'));
        
        if ($users = $modx->getCollectionGraph($userClass, '{"Profile":{},"User":{}}', $c)){
            foreach ($users as $user){
                //do something with the user here:
                $user_array = $user->toArray();
            }
        }
        
          -------------------------------

          you can buy me a beer, if you like MIGX

          http://webcmsolutions.de/migx.html

          Thanks!
          • 44922
          • 131 Posts
          Thanks Bruno. Bob's ClassExtender indeed looks useful and wish I'd come across this sooner. I can see this being extremely useful in future projects. Looks like a steep learning curve for us tho at this stage of the project! It's an amendment to a live site and I'm scared about changing too much at this stage....
          One thing I notice with $sector = $resource->getTVValue() is that it pulls through the delimiter as set in the "Output" of the TV and not the double pipes. Presumably, when Modx does this, it's retrieving this as a string not an array?
          Would using " = $object->toArray();" output TV and extended fields to a typical comma delimited array?
            • 4172
            • 5,888 Posts
            to get the raw value you can use

            $tvid = 'yourTvId';
            if ($tv = $modx->getObject('modTemplateVarResource',array('contentid'=>$resource->get('id'),'tmplvarid'=>$tvid))){
                $sections = explode('||',$tv->get('value'));
            }


            which you can explode to an array then.

            if you have multiple sectors for each user as commasepareted values, you can try this way then:

            <?php
            
            $profiles = $modx->getCollection('modUserProfile');
            foreach ($profiles as $profile) {
                $sendmail = false;
                $extended = $profile->get('extended');
                $usersectors = explode(',',$extended['Sector']);
                foreach($sections as $section){
                    if (in_array($section,$usersectors)){
                        $sendmail = true;
                    }
                }
                if ($sendmail){
                    sendmail();
                }   
            }


            But also, if you don't want or can not extend the users at this stage, you could still create a parallel table and store some extended userfields there in parallel by a plugin, which listens to OnUserFormSave and on OnUserRemove for faster searching.


              -------------------------------

              you can buy me a beer, if you like MIGX

              http://webcmsolutions.de/migx.html

              Thanks!
              • 44922
              • 131 Posts
              Thank you, Bruno. I couldn't get the raw value working, so what I did was use the output from getTVValue, which was delimited in the TV Output Options with ", ":
              For checking a single "Sector" TV value against an array of multiple values in the user Sector extended fields OR checking if one value of a multi-select TV "Function" is also present in an array of multiple values in the user Function extended fields, I used

              $Sector = $resource->getTVValue('Sector');
              $Function = explode(', ',$resource->getTVValue('Function');
              $profiles = $modx->getCollection('modUserProfile');
              foreach ($profiles as $profile) {
              $extended = $profile->get('extended');	
               $usersector = $extended['Sector'];
              $userfunction = $extended['Function'];
               $intersection = array_intersect($Function, $userfunction);
              // Loop though the Profiles and select qualified users & Get extended profile
              
              if (in_array($Sector,$usersector) || !empty($intersection))
              {send an email}


              It's probably not ideal, but it works! Thanks for your help.
                • 52945
                • 1 Posts
                Quote from: lancipoos at Nov 19, 2014, 12:41 AM
                Thank you, Bruno. I couldn't get the raw value working, so what I did was use the output from getTVValue, which was delimited in the TV Output Options with ", ":
                For checking a single "Sector" TV value against an array of multiple values in the user Sector extended fields OR checking if one value of a multi-select TV "Function" is also present in an array of multiple values in the user Function extended fields, I used

                $Sector = $resource->getTVValue('Sector');
                $Function = explode(', ',$resource->getTVValue('Function');
                $profiles = $modx->getCollection('modUserProfile');
                foreach ($profiles as $profile) {
                $extended = $profile->get('extended');	
                 $usersector = $extended['Sector'];
                $userfunction = $extended['Function'];
                 $intersection = array_intersect($Function, $userfunction);
                // Loop though the Profiles and select qualified users & Get extended profile
                
                if (in_array($Sector,$usersector) || !empty($intersection))
                {send an email}


                It's probably not ideal, but it works! Thanks for your help.