Jump to content

Find all images with a certain tag including ones in repeaters


abdus
 Share

Recommended Posts

A simple recursive function that walks over all image fields and those inside repeaters(including FieldtypeFieldsetPage) to find images tagged with a certain tag(s). It can easily be extended to file fields by changing instanceof FieldtypeImage to FieldtypeFile, or be restricted to file fields by adding a !$type instanceof FieldtypeFile, too. Adapted from ProcessPageEditLink::getFilesPage() method.

/**
 * Find all images tagged with a certain tag in a page including repeater items.
 * 
 * @param $page Page to search tagged images
 * @param $tag string|array Image tag(s). Can be 'foo' for single, 'foo|bar' for multiple OR tags, 'foo,bar' or ['foo', 'bar'] for multiple AND tags
 * @return array Tagged images in [basename => Pageimage] associated array form or empty an array
 */
function findTaggedImages(Page $page, $tag)
{
    $tagged = [];
    foreach ($page->template->fieldgroup as $f) {
        $type = $f->type;
        if ($type instanceof FieldtypeImage) {
            /** @var Pageimages $images */
            $images = $page->{$f->name};
            if (!$images) continue;
            $tagged = array_merge($tagged, $images->findTag($tag)->getArray());
        } else if ($type instanceof FieldtypeRepeater) {
            $items = $page->{$f->name};
            if (!$items) continue;
            if ($items instanceof PageArray) {
                foreach ($page->$f as $item) $tagged = array_merge($tagged, findTaggedImages($item, $tag));
            }
            // FieldtypeFieldsetPage returns a single page instead of a PageArray
            elseif ($items instanceof Page) {
                $tagged = array_merge($tagged, findTaggedImages($items, $tag));
            }
        }
    }
    return $tagged;
}

And can be used as 

$featuredImages = findTaggedImages($page, 'featured');
// get first featured image
$featured = reset($featuredImages); // or array_shift($featuredImages)

 

  • Like 2
Link to comment
Share on other sites

54 minutes ago, abdus said:

} else if ($type instanceof FieldtypeRepeater) {

Shouldn't that be:

} else if ($type instanceof FieldtypeRepeater || $type instanceof FieldtypeFieldsetPage) {

or perhaps:

} else if(wireInstanceOf($type, 'FieldtypeRepeater')) { 

to support FieldtypeFieldsetPage? 

  • Like 1
Link to comment
Share on other sites

3 minutes ago, matjazp said:

support FieldtypeFieldsetPage? 

FieldtypeFieldsetPage extends FieldtypeRepeater, so you dont need to explicity specify FieldtypeFieldsetPage.

class FieldtypeFieldsetPage extends FieldtypeRepeater implements ConfigurableModule { ... }

image.png.e4faf6f2374c7968aecf5ea588271f74.png

  • Like 1
Link to comment
Share on other sites

Hmm, it still works without wireInstanceOf() (which I believe is used for PW2 compatibility), but one bug I've found is that since FieldtypeFieldsetPage is a single repeater item, it doesnt return a RepeaterPageArray, instead returns the only item. Adding a check fixes it

else if ($type instanceof FieldtypeRepeater) {
    $items = $page->{$f->name};
    if (!$items) continue;
    if ($items instanceof PageArray) {
        foreach ($page->$f as $item) $tagged = array_merge($tagged, findTaggedImages($item, $tag));
    }
    // FieldtypeFieldsetPage returns a single page instead of a PageArray
    elseif ($items instanceof Page) {
        $tagged = array_merge($tagged, findTaggedImages($items, $tag));
    }
}

Updated the code in OP

  • Like 1
Link to comment
Share on other sites

 Could this:

else if ($type instanceof FieldtypeRepeater) {
    $items = $page->{$f->name};
    if (!$items) continue;
    if ($items instanceof PageArray) {
        foreach ($page->$f as $item) $tagged = array_merge($tagged, findTaggedImages($item, $tag));
    }
    // FieldtypeFieldsetPage returns a single page instead of a PageArray
    elseif ($items instanceof Page) {
        $tagged = array_merge($tagged, findTaggedImages($items, $tag));
    }
}

be like this?

else if ($type instanceof FieldtypeRepeater) {
    $items = $page->{$f->name};
    if ($items instanceof Page) $items = array($items);
    if ($items) foreach ($page->$f as $item) $tagged = array_merge($tagged, findTaggedImages($item, $tag));
}

I'm not a programmer at all and haven't tested this so I might be completely wrong :-) 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...