MoritzLost Posted September 6, 2019 Share Posted September 6, 2019 This doesn't warrant a full tutorial, but I wrote a little function that will recursively search through a repeater field to find the first non-empty field matching a list of fields to look for. I needed something like this to generate a fallback for SEO fields (og:image, og:description et c.). Here it is: <?php namespace ProcessWire; /** * Find the first non-empty field out of a list of fields in a repeater or repeater matrix field. * Will recursively search through nested repeaters until it finds a non-empty * field. * * @param RepeaterPageArray $repeater The field to search through. * @param array $fields A list of fields the function should look for. * @param array|null $allowed_repeater_types All the Repeater Matrix types the function will check. Leave empty to allow all. * @param array|null $allowed_repeater_fields All the repeater fields the function will check recursively. Leave empty to allow all. * @return void */ function firstRecursiveRepeaterMatch( RepeaterPageArray $repeater, array $fields, ?array $allowed_repeater_types = null, ?array $allowed_repeater_fields = null ) { // iterate over the items of the repeater foreach ($repeater as $current) { // if the function is currently inside a repeater matrix field, // skip this item if it isn't one of the allowed types, unless // allowed_repeater_types is empty (all types allowed) if ( $current instanceof RepeaterMatrixPage && is_array($allowed_repeater_types) && !in_array($current->type, $allowed_repeater_types) ) { continue; } // get all fields of the current item foreach ($current->getFields() as $field) { $name = $field->name; // if the current field is another repeater, check it recursively $fieldtype_class = $field->getFieldType()->className(); if ($fieldtype_class === 'FieldtypeRepeater' || $fieldtype_class === 'FieldtypeRepeaterMatrix') { // continue with the next item if the field name isn't one of the // allowed repeater fields, unless allowed_repeater_fields empty (null) if ( is_array($allowed_repeater_fields) && !in_array($name, $allowed_repeater_fields) ) { continue; } $deep_search = firstRecursiveRepeaterMatch( $current->get($name), $fields, $allowed_repeater_types, $allowed_repeater_fields ); // if the deep search inside the repeater // finds something, the function ends here if ($deep_search !== null) { return $deep_search; } } // if the current field name is one of the requested // fields, return it's value if it isn't empty if (in_array($name, $fields)) { $value = $current->get($name); if ( // check for empty values !empty($value) // if the value is any wirearray, check // if it has at least one item && (!$value instanceof WireArray || $value->count() > 0) ) { return $value; } } } } // if the function reaches this point, there is no match in the entire tree return null; } Can be used like this: $seo_description = firstRecursiveRepeaterMatch( // content sections fields, a repeater matrix with multiple types $page->sections, // look for the first non-empty instance of any of those fields ['body', 'html_basic', 'html_full'], // only check sections of the following types ['section_text', 'section_columns', 'section_accordion'], // only check the following nested repeaters recursively ['columns', 'accordion'] ); Wanted to share because I thought it could be useful to others. It should be easy to adjust the matching condition from non-emtpy fields to some other condition, depending on the use case ... 8 1 Link to comment Share on other sites More sharing options...
3fingers Posted September 6, 2019 Share Posted September 6, 2019 Thanks a lot for this, it might be useful in the future ? Could you please point me where I can learn about the question mark on this line? ?array $allowed_repeater_types = null, I know it should be something about php 7.*, but I cannot find anything due to the fact that the search string "? php" leads, obviously, to wrong results on google ? Thanks! 3 Link to comment Share on other sites More sharing options...
flydev Posted September 6, 2019 Share Posted September 6, 2019 11 minutes ago, 3fingers said: Could you please point me where I can learn about the question mark on this line? https://wiki.php.net/rfc/nullable_types https://www.php.net/manual/en/migration71.new-features.php 3 1 Link to comment Share on other sites More sharing options...
alxndre Posted September 6, 2019 Share Posted September 6, 2019 14 minutes ago, 3fingers said: Could you please point me where I can learn about the question mark on this line? ?array $allowed_repeater_types = null, This is a nullable type variable declaration. It simply means $allowed_repeater_types could either be an array or null. https://www.php.net/manual/en/migration71.new-features.php 3 Link to comment Share on other sites More sharing options...
Recommended Posts