We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 45367
    • 12 Posts
    Task
    Given: Resources with TV type “tags”. Tags are entered in the following way – Tag1,Tag2…etc
    Looking for: How to display a list of tags that start with the letter “a”, resp. on another page a list of tags that begin with the letter “b”.
    Decision: =?


    Thanks in advance
      • 45367
      • 12 Posts
      Maybe the community needs a little more clarification.

      I have:

      1. Resources with ID=76. It contains following code:
      [[!getResources? &parents=`1` &tpl=`tag_result` &toPlaceholder=`resultss` &showHidden=`1` &limit=`50` &hideContainers=`true`]]
      [[!+resultss]]

      2. Chung named “tag_result” . It contains following code:
      <li>
      <a href="[[~[[+id]]]]"><strong>[[+pagetitle]]</strong></a>
      </li>

      3. Chung named “cloud”. It contains following code:
      [[!tagLister? &parents=`1` &target=`76` &sortBy=`tag` &limit=`50` &tv=`tagove` &tpl=`tag_user`]]

      4. Chung named “tag_user”. It contains following code:
      <a href="[[+url]]" class="[[+cls]]">[[+tag]]</a>,

      Of these codes as a result I get a list of all tags. – Air, Arm, Arbiter, Bear, Bets, Cat, Diadem …. etc.
      But I like to get a list of tags that start with the letter “A” only - – Air, Arm, Arbiter,.. etc.
      Or a list of tags that start with the letter “B” only - Bear, Bets, … etc.
      Is there anyone who knows how to do it?

      thanks
        • 3749
        • 24,544 Posts
        Because there can be multiple tags in the "tags" TV, I don't think you can do it without some custom code. AKAIK, TagLister doesn't have the ability to specify criteria.

        Here's a kind of goofy way to do it (untested, and probably flawed):

        [[!GetTags? &letter='A']]


        <?php
        /* GetTags snippet */
        
        
        $letter = $scriptProperties['letter'];
        $output = '';
        $tagListerProps = array(
          'parents' => '1',
          'target' => '76',
           'sortby' => 'tag',
           'limit' => '50',
           'tv' => 'tagove',
           'tpl' => 'tag_user',
        );
        
        $results = $modx->runSnippet('TagLister', $tagListerProps);
        
        /* This assumes that TagLister ends each element with "\n" */
        $resultArray = explode("\n", $results);
        
        /* For debugging. If this is 0 or 1, we're out of luck */
        echo "<p>COUNT: " . count($resultArray) . "</p>\n";
        
        $pattern = '/<a href.+>([a-zA-Z])/';
        foreach($resultArray as $result) {
        
           preg_match($pattern, $result, $matches);
        
           if ($matches[1] == $letter) {
               $output .= "\n" . $result;
           }
        }
        
        return $output;
        



        This assumes that all tags start with an uppercase letter. If not, the if statement can be changed to:

        if (($matches[1] == $letter) || ($matches[1] == strtolower($letter)) ) {
        
        }
        

        [ed. note: BobRay last edited this post 12 years, 11 months ago.]
          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
          • 45367
          • 12 Posts
          This code returns the following response: COUNT: 7

          But the desired result should be a list of tags.
            • 4172
            • 5,888 Posts
            you can also collect all tags in a custom-table with a plugin like that:

            <?php
            
            /**
             * helper method for missing params in events
             * @param modX $modx
             * @param array $children
             * @param id $parent
             * @return boolean
             */
            function tagManGetChildren(&$modx, &$children, $parent) {
                $success = false;
                $kids = $modx->getCollection('modResource', array('parent' => $parent, ));
                if (!empty($kids)) {
                    foreach ($kids as $kid) {
                        $children[] = $kid->toArray();
                        tagManGetChildren($modx, $children, $kid->get('id'));
                    }
                }
                return $success;
            }
            
            function tagManSetTagsArray(&$modx, $tvname, $resourceArray) {
            
                if ($tv = $modx->getObject('modTemplateVar', array('name' => $tvname))) {
                    $tagsArray = array();
                    $tagsArray['add_tags'] = $resourceArray['deleted'] == 0 ? true : false;
                    $tagsArray['id'] = $resourceArray['id'];
                    $tagsArray['tags'] = $tv->renderOutput($resourceArray['id']);
                    $modx->log(modX::LOG_LEVEL_DEBUG, 'Indexing ' . $tv->get('name') . ': ' . $tagsArray['tags']);
                    return $tagsArray;
                }
                return false;
            }
            
            
            $tvname = 'migxtagmanager_tags';
            $action = 'activate';
            $resourcesToIndex = array();
            
            switch ($modx->event->name) {
                case 'OnDocFormSave':
                    $resourceArray = $resource->toArray();
                    if ($tagsArray = tagManSetTagsArray($modx, $tvname, $resourceArray)) {
                        $resourcesToIndex[] = $tagsArray;
                    }
            
                    break;
                case 'OnResourceDuplicate':
                    $resourceArray = $newResource->toArray();
                    if ($tagsArray = tagManSetTagsArray($modx, $tvname, $resourceArray)) {
                        $resourcesToIndex[] = $tagsArray;
                    }
                    $children = array();
                    tagManGetChildren($modx, $children, $resourceArray['id']);
                    foreach ($children as $child) {
                        if ($tagsArray = tagManSetTagsArray($modx, $tvname, $child)) {
                            $resourcesToIndex[] = $tagsArray;
                        }
                    }
                    break;
                case 'OnResourceDelete':
                case 'OnResourceUndelete':
                    $resourceArray = $resource->toArray();
                    if ($tagsArray = tagManSetTagsArray($modx, $tvname, $resourceArray)) {
                        $resourcesToIndex[] = $tagsArray;
                    }
                    $children = array();
                    tagManGetChildren($modx, $children, $resourceArray['id']);
                    foreach ($children as $child) {
                        if ($tagsArray = tagManSetTagsArray($modx, $tvname, $child)) {
                            $resourcesToIndex[] = $tagsArray;
                        }
                    }
                    break;
            }
            
            
            if (count($resourcesToIndex) > 0) {
            
                $packageName = 'migxtagmanager';
                $classname = 'mtmResourceTags';
            
                $packagepath = $modx->getOption('core_path') . 'components/' . $packageName . '/';
                $modelpath = $packagepath . 'model/';
                if (is_dir($modelpath)) {
                    $modx->addPackage($packageName, $modelpath, $prefix);
            
                    foreach ($resourcesToIndex as $resourceArray) {
                        $tags = $modx->getOption('tags', $resourceArray, '');
                        $id = $modx->getOption('id', $resourceArray, 0);
                        $add_tags = $modx->getOption('add_tags', $resourceArray, false);
            
                        if (!empty($id)) {
                            $tags = explode(',', str_replace('||', ',', $tags));
                            //get existing tags
                            $existing = array();
                            $c = $modx->newQuery($classname, array('resource_id' => $id));
                            if ($collection = $modx->getCollection($classname, $c)) {
                                foreach ($collection as $object) {
                                    $existing[$object->get('tag')] = $object;
                                }
                            }
            
                            if ($add_tags) {
                                foreach ($tags as $tag) {
                                    if (isset($existing[$tag])) {
            
                                    } else {
                                        $object = $modx->newObject($classname);
                                        $object->set('tag', $tag);
                                        $object->set('resource_id', $id);
                                        $object->save();
                                        
                                    }
                                    unset($existing[$tag]);
                                }
                            }
            
                            foreach ($existing as $object) {
                                $object->remove();
                            }
            
                        }
                    }
                }
            
            
            }
            
            
            return;
            
            


            the xpdo-schema for the table:

            <?xml version="1.0" encoding="UTF-8"?>
            <model package="migxtagmanager" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM">
            
            	<object class="mtmResourceTags" table="migxtagmanager_tags" extends="xPDOSimpleObject">
            		<field key="tag" dbtype="varchar" precision="100" phptype="string" null="false" default="" index="index" />
                    <field key="resource_id" dbtype="int" precision="11" phptype="integer" null="false" default="0" index="index" />       
                    
                    <aggregate alias="Resource" class="modResource" local="resource_id" foreign="id" cardinality="one" owner="foreign" />
            	</object>       
                
            </model>


            this is in a package named 'migxtagmanager'

            you can create this package-directory and the classes and table in some minutes with help of MIGX

            Than you can get the Tags with:

            [[!migxLoopCollection? 
            &packageName=`migxtagmanager` 
            &classname=`mtmResourceTags`
            &joins=`[{"alias":"Resource","selectfields":"id"}]`
            &where =`{"tag:LIKE":"B%","Resource.published":"1"}`
            &groupby = `tag`
            &sortConfig = `[{"sortby":"tag"}]`
            ]]


            don't forget to change the TV-name in this line:

            $tvname = 'migxtagmanager_tags';


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

              you can buy me a beer, if you like MIGX

              http://webcmsolutions.de/migx.html

              Thanks!
              • 3749
              • 24,544 Posts
              Quote from: gali11 at Nov 18, 2013, 02:35 AM
              This code returns the following response: COUNT: 7

              But the desired result should be a list of tags.

              Do a "View Source" on it and see if any parts of the tags are there in the source code.
                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
                I just tested it and it works perfectly for me. Does the TagLister tag above work for you? I took the parameters from your example:

                [[!tagLister? &parents=`1` &target=`76` &sortBy=`tag` &limit=`50` &tv=`tagove` &tpl=`tag_user`]]


                You might try putting the GetTags tag directly in the template or page content rather than in a chunk.
                  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
                  • 45367
                  • 12 Posts
                  Yes, tagLister work for me.
                  I tried to put [[!GetTags? &letter='A']] directly into the template and in the content of the document but the result is again - COUNT: ... /the number of tags/.
                    • 3749
                    • 24,544 Posts
                    That's very strange. If the runSnippet() call wasn't working, the count wouldn't equal the number of tags.

                    There must be a mismatch between the $pattern for the preg_match() statement and your Tpl chunk.

                    You could add a line just after the runSnippet() call:

                    echo $result;


                    That will tell us what's coming back from runSnippet().
                      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
                      • 45367
                      • 12 Posts
                      Here, I did what you say

                      /* GetTags snippet */
                       
                       
                      $letter = $scriptProperties['letter'];
                      $output = '';
                      $tagListerProps = array(
                        'parents' => '1',
                        'target' => '76',
                         'sortby' => 'tag',
                         'limit' => '50',
                         'tv' => 'tagove',
                         'tpl' => 'tag_user',
                      );
                       
                      $results = $modx->runSnippet('TagLister', $tagListerProps);
                      echo $result;
                       
                      /* This assumes that TagLister ends each element with "\n" */
                      $resultArray = explode("\n", $results);
                      
                      /* For debugging. If this is 0 or 1, we're out of luck */
                      echo "<p>COUNT: " . count($resultArray) . "</p>\n"; 
                       
                      $pattern = '/<a href.+>([a-zA-Z])/';
                      foreach($resultArray as $result) {
                       
                         preg_match($pattern, $result, $matches);
                       
                         if ($matches[1] == $letter) {
                             $output .= "\n" . $result;
                         }
                      }
                       
                      return $output;



                      The result is the same: the number of all existing tags in resource.

                      If I delete the rows after the number 18 in the above code - no result displayed.