2

I have articles with a multi-select named theme.

This works fine in a template:

{% set entries = craft.entries.section('article').search('theme:themeFoobar') %}
<p>{{ entries | length }}</p>

I'm working on a plugin to create a custom source containing only those articles that have themeFoobar selected in their multi-select, this is what I have:

public function modifyEntrySources(&$sources, $context)
{
  $sources[] = array('heading' => 'Themes');

  $sources['theme:foobar'] = array(
    'label' => 'Theme: Foobar',
    'criteria' => array(
      'section' => 'article',
      'search' => 'theme:themeFoobar'
    )
  );
}

The result of this is that the source contains all articles, it looks like the search criteria is completely ignored.

Is search not the correct criteria to use here? Is there another criteria I can use to find only the articles with themeFoobar selected in the multi-select?

Further information

The multi-select used to be just a dropdown. When it was a dropdown, this plugin worked fine:

public function modifyEntrySources(&$sources, $context)
{
  $sources[] = array('heading' => 'Themes');

  $sources['theme:foobar'] = array(
    'label' => 'Theme: Foobar',
    'criteria' => array(
      'section' => 'article',
      'theme' => 'themeFoobar'
    )
  );
}
4
  • Does it work if you change it to 'search' => 'theme:*themeFoobar*'? The multi select stores the array of values as a JSON string to the database.
    – carlcs
    Mar 3 '16 at 13:00
  • @carlcs nope, same result. All articles are returned, the search criteria appears to have no effect.
    – Esseb
    Mar 3 '16 at 13:10
  • Hey @esseb, the solutions I posted to this question should also work from PHP. Search against a checkboxes field's options
    – carlcs
    Mar 3 '16 at 14:13
  • @carlcs If you'd like, go ahead and write that as an answer and I'll accept it. I'll post my own final code later once I clean it up a bit.
    – Esseb
    Mar 3 '16 at 14:45
3

My solution, thanks to @carlcs:

public function modifyEntrySources(&$sources, $context)
{
    $sources[] = array('heading' => Craft::t('Themes'));

    $themes = array(
        'THEME_FOO' => 'themeFoo',
        'THEME_BAR' => 'themeBar'
    );

    $criteria = craft()->elements->getCriteria(ElementType::Entry);
    $criteria->section = 'article';
    $articles = $criteria->find();

    foreach ($themes as $theme => $label)
    {
        // Loop through all articles and check if they contain the current theme.
        // If they do, add it to the ids array which we will later use to filter
        // just the articles with this theme.
        $ids = [];
        foreach ($articles as $article)
        {
            foreach ($article->theme as $articleTheme)
            {
                if ($articleTheme == $themes[$theme])
                {
                    array_push($ids, $article->id);
                    break;
                }
            }
        }

        $sources['theme:' . $label] = array(
            'label' => Craft::t('Theme') . ': ' . Craft::t($theme),
            'criteria' => array(
                'section' => 'article',
                'id' => $ids
            )
        );
    }
}

The PHP itself could be cleaned up, but this works for now.

Categories would probably have been a simpler solution had I gone for that originally.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.