Replace long if/elseif/else with array search

I currently have a very long if/elseif/else that can only keep growing:

        {% set default_icon = "globe" %}
        {% for s_url in page.header.syndication %}
            {% if "twitter.com" in s_url %}
                {% set icon = "twitter" %}
            {% elseif "blogger.com" in s_url %}
                {% set icon = "blogger" %}
            {% elseif "github.com" in s_url %}
                {% set icon = "github" %}
            {% elseif "instagram.com" in s_url %}
                {% set icon = "instagram" %}
            {% elseif "linkedin.com" in s_url %}
                {% set icon = "linkedin" %}
            {% elseif "reddit.com" in s_url %}
                {% set icon = "reddit" %}
            {% elseif "wordpress.com" in s_url %}
                {% set icon = "wordpress" %}
            {% elseif "wordpress.org" in s_url %}
                {% set icon = "wordpress" %}
            {% else %}
                {% set icon = default_icon %}
            {% endif %}
            <a class="u-syndication" href="{{ s_url }}"><i class="{{ icon == default_icon ? 'fa' : 'fab' }} fa-{{ icon }}"></i></a>
        {% endfor %}

I would like to replace with setting an array and search the right value from the array.

Something like (not yet working!):

        {% set default_icon = "globe" %}

        {% set icons = {
            "twitter.com" : "twitter",
            "instagram.com" : "instagram",
            } %}

        {% for s_url in page.header.syndication %}
            {% set icon = default_icon %}
            {% for i in icons %}
                {% if i in s_url %}
                    {% set icon = icons[i] %}
                {% endif %}
            {% endfor %}
            <a class="u-syndication" href="{{ s_url }}"><i class="{{ icon == default_icon ? 'fa' : 'fab' }} fa-{{ icon }}"></i></a>
        {% endfor %}

Does anyone have suggestions / a working example?

Perhaps a nice challenge for @pamtbaau?

You could try:

{% set default_icon = "globe" %}

{% set icons = {
    "twitter": "twitter.com",
    "instagram" : "instagram.com",
    }
%}

{% for s_url in page.header.syndication %}
    {% set icon = array_search(s_url, icons) ?: default_icon %}
    <a class="u-syndication" href="{{ s_url }}"><i class="{{ icon == default_icon ? 'fa' : 'fa' }} fa-{{ icon }}"></i></a>
{% endfor %}

And if you don’t want to edit your code all the time, you could save the icons definition into /user/config/icons.yaml:

twitter: twitter.com
instagram : instagram.com

and use array_search(s_url, config.icons) in Twig.

1 Like

It looks like the PHP array_search() function is unavailable in Twig.

Although my example is working fine in my project, I couldn’t find any mentioning of ‘array_search()’ in the Grav docs. But it does work (in my project)… So I guessed the docs were outdated :slight_smile:

Found an even shorter way…

Frontmattter:

syndication:
    - twitter.com
    - blogger.com
    - github.com
    - instagram.com
    - linkedin.com
    - reddit.com
    - wordpress.com

default.html.twig

{% set default_icon = "globe" %}

{% set icons = {
    "twitter.com": "twitter",       <- key/value have been reversed
    "instagram.com" : "instagram",
    "github.com" : "github",
    }
%}

<p>
{% for s_url in page.header.syndication %}
    {% set icon = icons[s_url] ?: default_icon %}
    {{ s_url }} => {{ icon }} <a class="u-syndication" href="{{ s_url }}"><i class="{{ icon == default_icon ? 'fa' : 'fa' }} fa-{{ icon }}"></i></a>
    </br>
{% endfor %}
</p>

Result:
image

1 Like

My bad. It is working now… The s_url isn’t a domain name, but a canonical url to a page. I first had to retrieve the domain name from the url. This is my current working code:

item.md

---
title: 'Lorem Syndication'
syndication:
    - 'https://twitter.com/metbril/status/12345678'
    - 'https://www.twitter.com/metbril/status/12345678'
    - 'https://mobile.twitter.com/metbril/status/12345678'
    - 'https://instagram.com/metbril/p/1234567'
    - 'https://linkedin.com/12345'
    - 'https://discuss.com/test'
    - 'https://reddit.com/reddit'
    - 'https://wordpress.com/test'
    - 'https://wordpress.org/test'
    - 'https://github.com/metbril'
---
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In imperdiet nunc odio, interdum fermentum urna malesuada nec. Mauris dui lacus, auctor sit amet tortor eget, cursus iaculis erat. Fusce eu erat mauris. Sed efficitur non tellus quis finibus. Phasellus rhoncus vel lacus sed maximus. Quisque blandit enim vel porta commodo. Sed luctus purus elit, at vestibulum quam ultrices vel. Pellentesque sem purus, tincidunt ut bibendum eu, imperdiet auctor metus. Phasellus quis dictum nisl, id convallis nisi. Vestibulum dignissim quis mauris vitae rutrum. Aliquam erat volutpat. In ultricies fermentum laoreet. Mauris pretium tempus augue eget malesuada.

syndication.html.twig

{% if page.header.syndication %}
    {# TODO: config default icon via theme blueprint #}
    {% set default_icon = "globe" %} 
    {% set icons = {
        "blogger": "blogger.com",
        "delicious": "delicious.com",
        "facebook": "facebook.com",
        "flickr": "flickr.com",
        "foursquare": "foursquare.com",
        "get-pocket": "getpocket.com",
        "github": "github.com",
        "google-plus": "plus.google.com",
        "hacker-news": "hackernews.com",
        "imdb": "imdb.com",
        "instagram": "instagram.com",
        "lastfm": "lastfm.com",
        "linkedin": "linkedin.com",
        "medium": "medium.com",
        "meetup": "meetup.com",
        "pinterest": "pinterest.com",
        "reddit": "reddit.com",
        "soundcloud": "soundcloud.com",
        "spotify": "spotify.com",
        "strava": "strava.com",
        "tumblr": "tumblr.com",
        "twitter": "twitter.com",
        "twitter": "mobile.twitter.com",
        "vimeo": "vimeo.com",
        "wordpress": "wordpress.com",
        "wordpress": "wordpress.org",
        "youtube": "youtu.be",
        "youtube": "youtube.com",
        }
    %}
    <span class="syndication">
        {% for s_url in page.header.syndication %}
            {% set domain = s_url | parse_url(1) | regex_replace('/^www./', '') %}
            {% set icon = array_search(domain, icons) ?: default_icon %}
            <a class="u-syndication" href="{{ s_url }}">
                <i class="{{ icon == default_icon ? 'fa fa-' : 'fab fa-' }}{{ icon }}"></i>
            </a>
        {% endfor %}
    </span>
{% endif %}

Just curious…
What made you think array_search() was unavailable before, and what makes it available right now?

I blindly used array_search(s_url, icons) instead of array_search(domain, icons). This returned an empty string for icon, so I assumed the function was unsupported.

I asked because I was under the impression that Twig would throw an error on a non-existing function. But it doesn’t… Not even on xxxx()

Oh well… eventually your problem has been solved :slight_smile:

The twig is a partial of my template. Is there a simple way to have a default icons.yaml included in the template that can be overwritten by the user? So, the standard icon set is in theme://data/icons.yaml and the user can put his/her own in user/config/icons.yaml?

Probably an easy one for you, but a lot of trial and error for me. :wink:

Update: something like (not working)

{% set icons = ( config.icons ?? url('theme://data/icons.yaml') ) %}

You could add the ‘icons’ array inside ‘/user/themes/quark/quark.yaml’, like:

syndication_icons:
  twitter.com: twitter
  instagram.com : instagram
  github.com : github

Have the user copy the file ‘quark.yaml’ to folder ‘/user/config/themes/’ and edit/override the settings.

And use the following in Twig:

{% set icon = theme.syndication_icons[s_url] ?: default_icon %}
1 Like

Yeah, that would be the easiest. I read an example from the iplocate plugin and that was overly complex for this purpose (a mainly static list of icons).

Corrected a typo in the path where the user should copy quark.yaml to…