Skip to content
Grav 2.0 is officially stable. Read the announcement →

Community guidelines

Please keep discussions civil and on-topic. Repeated violations may lead to a temporary ban.

Themes & Styling

Replace long if/elseif/else with array search

Solved by pamtbaau View solution

Started by Robert 8 years ago · 12 replies · 1127 views
8 years ago

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

TWIG
        {% 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!):

TWIG
        {% 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?

8 years ago

Perhaps a nice challenge for @pamtbaau?

8 years ago Solution

You could try:

TWIG
{% 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:

TXT
twitter: twitter.com
instagram : instagram.com

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

👍 1
8 years ago

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

8 years ago

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 :-)

Found an even shorter way...

Frontmattter:

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

default.html.twig

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|263x171

👍 1
8 years ago

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

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

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 %}
8 years ago

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

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

8 years ago

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.

8 years ago

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 :-)

8 years ago

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

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. 😉

Update: something like (not working)

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

last edited 08/24/18 by Robert
8 years ago

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

YAML
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:

TWIG
{% set icon = theme.syndication_icons[s_url] ?: default_icon %}
👍 1
last edited 08/24/18 by pamtbaau
8 years ago

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).

8 years ago

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

Suggested topics

Topic Participants Replies Views Activity
Themes & Styling · by Pedro M, 2 months ago
4 222 2 months ago
Themes & Styling · by Ian, 2 months ago
3 118 2 months ago
Themes & Styling · by Norbert, 2 years ago
11 481 3 months ago
Themes & Styling · by Lukáš Findeis, 3 months ago
0 72 3 months ago
Themes & Styling · by Sebadamus, 4 months ago
5 132 3 months ago