How do I list a simple list of category and tag references?


#1

Friends, I clearly understand that the topic was discussed more than once, but not one of the outreach does not work.
The site has categories and tags (assigned to these categories). I just need to list the links of all categories on the site and under the categories specify a list of all assigned tags to these categories. That is, in fact, I need to output a simple listviews-tree-example-drupal


#2

#3

Perlkonig is very grateful for your reply. I know about this plugin, but when I insert the code:
{% include ‘partials/taxonomylist.html.twig’ with {base_url: my_url, taxonomy: ‘tag’, children_only: true} %}
Not what does not happen, and not what is not displayed.


#4

Not what is not happening at least so I insert
{% include ‘partials/taxonomylist.html.twig’ with {base_url: my_url, taxonomy: ‘tag’} %}

and so too:

{% include ‘partials/taxonomylist.html.twig’ with {base_url: my_url, taxonomy: ‘tag’, children_only: true} %}


#5

I need to output a banal list of all categories and tags under categories. Spent half a day, and nothing happens.


#6

Is this what you are trying to achieve?


#7

Thank you for your example. Yes, that’s it.


#8

Ok then I probably understood your requirements…

A note on the concept of taxonomy: The taxonomies listed in /user/config/site.yaml are not related. Tags cannot be assigned to categories. The list generated below shows which categories and which tags are assigned to the same page. The list is therefor only 2-levels deep, instead of the 3-levels in your sample.

Here is some rough code. It may (will) contain imperfections… And feedback is welcome.

Steps to create the plugin:

  • To install Devtools (if not already installed) , open a command prompt (terminal) and run the following command:
    $ bin/gpm install devtools
    
  • At the same command prompt run the following command to create a basic plugin skeleton:
    $ bin/plugin devtools newplugin
    
    The ‘wizard’ will ask you a few questions: plugin name, description, your name, GitHub ID (may be empty) and your email.
  • If you named your plugin ‘taxonomytree’, there will be a file named:
    /user/plugins/taxonomytree/taxonomytree.php.
  • In that file replace everything starting from line 33 down to and including line 62 (leave the last curly bracket in place) with the code below.
    public function onPluginsInitialized()
    {
        // Don't proceed if we are in the admin plugin
        if ($this->isAdmin()) {
            return;
        }
    
        // Enable the main event we are interested in
        $this->enable([
            'onPagesInitialized' => ['onPagesInitialized', 0],
            'onTwigSiteVariables' => ['onTwigSiteVariables', 0],
            'onTwigTemplatePaths' => ['onTwigTemplatePaths', 0],
        ]);
    }
    
    public function onPagesInitialized(Event $e)
    {
        $cache = Grav::instance()['cache'];
        $taxonomiesUsed = Grav::instance()['taxonomy']->taxonomy();
        $hash = hash('md5', serialize($taxonomiesUsed));
    
        // If no categories/tags have been added/removed from pages we can reuse cache
        if ($this->taxonomyTree = $cache->fetch($hash) ?: []) {
            return;
        } else {
            // Get all pages in the site
            $pages = $e['pages'];
    
            // Loop through all pages
            foreach ($pages->all() as $page) {
                $taxonomy = $page->taxonomy();
                if (array_key_exists('category', $taxonomy)) {
                    if (is_array($taxonomy['category'])) {
                        foreach($taxonomy['category'] as $category) {
                            if (!array_key_exists($category, $this->taxonomyTree)) {
                                $this->taxonomyTree[$category] = [];
                            }
                            $this->addTags($taxonomy, $category);
                        }
                    } else {
                        $category = $taxonomy['category'];
                        if (!array_key_exists($category, $this->taxonomyTree)) {
                            $this->taxonomyTree[$category] = [];
                        }
                        $this->addTags($taxonomy, $category);
                    }
                }
            }
            // Store tree in cache for reuse
            $cache->save($hash, $this->taxonomyTree);
        }
    }
    
    protected function addTags($taxonomy, $category)
    {
        // If field taxonomy has a subfield 'tag', continue
        if (array_key_exists('tag', $taxonomy)) {
            if (is_array($taxonomy['tag'])) {
                foreach($taxonomy['tag'] as $tag) {
                    if (!array_key_exists($tag, $this->taxonomyTree[$category])) {
                        $this->taxonomyTree[$category][$tag] = $tag;
                    }
                }
            } else if (!array_key_exists($tag, $this->taxonomyTree[$category])) {
                $this->taxonomyTree[$category][$tag] = $tag;
            }
        }
    }
    
    public function onTwigSiteVariables(Event $e)
    {
        $this->grav['twig']->twig_vars['taxonomytree'] = $this->taxonomyTree;
    }
    
    public function onTwigTemplatePaths()
    {
        $this->grav['twig']->twig_paths[] = __DIR__ . '/templates';
    }
    
  • At line 13 add:
    private $taxonomyTree = [];
    
  • At line 4 add:
    use Grav\Common\Grav;
    
  • For the translation of the header displayed above the list, replace the content of file /user/plugins/taxonomytree/language.yaml with:
    en:
      SIDEBAR:
        TAXONOMYTREE:
            HEADLINE: Taxonomy Tree
    
  • Create file /user/plugins/taxonomytree/templates/partials/taxonomytree.html.twig and add the following content: (Adapt to your likings)
    <ul>
        {% for category in taxonomytree|keys %}
            <li><a href="{{ page.url }}/category:{{ category }}">{{ category }}</a>
                <ul>
                {% for tag in taxonomytree[category]|keys %}
                    <li><a href="{{page.url}}/category:{{ category }}/tag:{{ tag }}">{{ tag }}</a></li>
                {% endfor %}
                </ul>
            </li>
        {% endfor %}
    </ul>
    
  • The plugin should now be working.

The taxonomy tree will now be created and passed on to Twig as a variable called ‘taxonomytree’.

I have no experience nor any understanding of Gantry so I cannot help you there…
I hope that you, as a designer, know way better than me where to display the taxonomy tree.

  • In one of the templates you could add the following code:
    Some themes have a partials/sidebar.html.twig which would be a good choice. Again,adapt to your likings and context.
    {% if config.plugins.taxonomytree.enabled %}
    <div class="sidebar-content">
        <h4>{{ 'SIDEBAR.TAXONOMYTREE.HEADLINE'|t }}</h4>
        {% include 'partials/taxonomytree.html.twig' %}
    </div>
    {% endif %}
    
  • CSS styling of the nested list should not present you any issues I guess.

#9

You need to do some coding. The docs give a clue..

The fundamental problem is that there is no necessary relationship between tags and categories. Tags don’t “belong” to categories in any inherent way. So the only way I know of to accomplish what you want (but I’m no expert) is to actually iterate over all the posts in each category to find out which tags are used in that category. (The following code is untested.)

{% set catlist = taxonomy.taxonomy["category"]|keys|sort %}
{% for cat in catlist %}
  {% set taglist = [] %}
  {% for post in taxonomy.findTaxonomy({'category': cat}) %}
    {% set taglist = taglist|merge(post.taxonomy["tag"]) %}
  {% endfor %} 
  {# output HTML in whatever format you want for this category and nested tags #}
{% endfor %}

This seems like a very inefficient approach, but I don’t know of a better one off the top of my head.


#10

ERROR:

Argument 1 passed to Grav\Plugin\DevToolsPlugin::onPagesInitialized() must be an instance of Grav\Plugin\Event, instance of RocketTheme\Toolbox\Event\Event given, called in /home/dudblog/public_html/vendor/symfony/event-dispatcher/EventDispatcher.php on line 212


#12

Very grateful for your reply. But it also gives an error:
Twig_Error_Runtime

The merge filter only works with arrays or “Traversable”, got “NULL” as second argument in “@Page:/home/dudblog/public_html/user/pages/03.blog/grav-gantry-5” at line 6.


#13

I’ve understood everything correctly, I need to add the php code here. Right?
*/user/plugins/devtools/devtools.php

And a separate and many thanks for your reply and time spent on me.
:+1:

I do not know what to do, not what’s wrong. I am very grateful to you, but I can not deduce this sheet stubbornly.
:anguished:


#14

I understand your frustration… Somehow I assumed you are a developer instead of a novice user…

The functionality you requested does not come build-in with Grav. However, Grav is very flexible for creating added functionality. Some developers have already created ready to use plugins (like TaxonomyList), but if no plugin is available that fullfills our needs we have to code ourselves.

If you have no PHP of Twig experience the solution I offered might be over your head and might cause more grief than pleasure… In that case a finished ‘prêt-à-porter’ plugin might be a better choice (if available).

If you have not found a suitable plugin and want to try my suggested solution, I will need to know a bit more about your skill levels. What does ‘novice’ mean to you? Novice with respect to Grav, or novice wrt. PHP and Twig? What experience may I presume?

I will update my post accordingly.


#15

Many thanks for your understanding. I dealt with Wordpress, mostly I’m engaged in layout and design. With regards to programming, I’m not bad at jQuery. I know CSS well and I understand php. But all that I did and knew before it just became the ashes of a half of a clash with Grav CMS.
For me Grav is a beautiful and very powerful system that breaks all the templates. But it seemed to me that to create a blog, such functions as a simple list of cathegories and sub categories are simply modules that should be by default. I did not think that such seemingly trivial things could spend so much of my strength. Honestly, I already doubt my skills.
Unfortunately I did not find the “prêt-a-porter” plug-in. Could you give a link to it?
With regards to the plugin “TaxonomyList” I persistently can not understand why it does not work.
For the design of the site, I use the theme “Helium v5.4.24” and the plugin Gantry 5. In general, my blog is ready for 85%, but it seems like such trivial things as this topic is simply knocked out.
Thanks again for your answers, and your time.


#16

I have updated post #8

Coming from Wordpress myself, I can understand that Grav shakes the ground a bit. But in a very fresh and welcoming way… Wordpress is big and got stuck in old code because of backwards compatibility, Grav is innovative and wants to be slim and fast. It provides the core and does that very well. That also means that for functionality that is not part of the core, plugins need to be build, or installed if already made available by others.

And building these plugins are a breeze compared to Wordpress… And I just love that.

Andy Miller has written a nice Grav Origins (scroll down halfway), in which he describes why Grav was created. Some keywords: speed, simplicity, powerful & flexible and flat-file.


#17

Everything turned out, you just can not imagine how much I’m grateful to you.
:smiley::+1::ok_hand::sparkler:


#18

Friends I ran into a new problem.
Suppose my post has two categories and tags for them:

  • Google
    • Analytics
  • Wordpress
    • Plugins

When using the current solution, I get tags in both categories.
That is, the output is such a display on the site:

  • Google
    • Analytics
    • Plugins
  • Wordpress
    • Analytics
    • Plugins

Please help change the current solution so that the tags would be listed only to the categories I need.

I am also interested in such a question. How can I specify nested categories, let’s say:

  • Google
    • Analytics
      • Tags

#19

@dydaevskiy First, thanks for re-editing and properly formatting your question… :slight_smile:
By the way, I’m curious how you get multiple bullets on a single line…

Categories and tags have no relationship with each other. This means that a category has no tag belonging to it.
The “relationship” is more or less defined by the page on which they appear together.

Could it be possible that you have a page with “Google” and “Analytics” and another page with “Google” and “Plugins”, or a page with “Google” and “[Analytics, Plugins]”

What “current solution” are you referring too? Are you perhaps referring to the “taxonomyTree” plugin I once created for you?


#20

Thank you for such a prompt reply, very happy to you :slight_smile:

Categories and tags have no relationship with each other. This means that a category has no tag belonging to it.
The “relationship” is more or less defined by the page on which they appear together.

At the moment I specify the categories of tags at the top of the page (.md file) as follows:

taxonomy:
    category:
        - Google
        - Wordpress
    tag:
        - Analytics
        - Plugins

What “current solution” are you referring too? Are you perhaps referring to the “taxonomyTree” plugin I once created for you?

That’s right, I meant it was you who wrote the plugin (for which I am immensely grateful to you).

It would be great if I could specify categories in this way (even without tags):

taxonomy:
category:
    - Google
           - Analytics
    - Wordpress
           - Plugins
                   - Google Analytics Dashboard for WP by ExactMetrics (formerly GADWP)

Unfortunately, my English skills are not great, you could more accurately describe the question. Just using the translator (from English to Russian) I did not understand your question. thank

A dream it seems you meant how I managed to get some circles out. Here is how I did it :slight_smile:

- Google
- - Analytics
- Wordpress
- - Plugins

#23

@dydaevskiy A lot of questions… Let me try to answer them collectively in one post.

Your current solution:
The logic of plugin ‘categoryTree’ I created for you, is currently as follows: For each page in the blog, and for each category found on each page, get me all tags on that same page. And finally display a nice sorted tree.

When a page contains the frontmatter as you showed in post #18, the plugin will yield a tree like:

  • Google
    • Analytics
    • Plugins
  • Wordpress
    • Analytics
    • Plugins

Since that is the result you are seeing, the plugin seems to be working as designed… Phew

Your wish for hierarchical taxonomies:
I think it would be a nice feature if taxonomies could be expressed in a parent/child relationship. However, currently that is not possible.

Unfortunately, (at the moment) I see no way how I could implement the parent/child relationship and build/filter collections based on free-format parent/child ‘labels’. Without collections and a filtering mechanism such ‘labels’ are quite useless I think.