arturogsz Posted January 12, 2022 Share Posted January 12, 2022 Hi everyone. I have a field buried inside other fields on several pages. It is a page reference field I use for setting navigation links (navbar, footer, banners, etc.). I need to get the pages that ultimately "contain" this field. This is, the pages the user edit in the admin and from where they set its value. These pages can be anywhere in the pages tree. These are two examples of pages and their fields structures: footer (Page) -> footer_columns (Repeater) -> nav_items (Repeater) -> nav_item (FieldSetPage) -> page_selector (Page Reference) home (Page) -> home_covers (Repeater) -> nav_item (FieldSetPage) -> page_selector (Page Reference) I need to get the ids of all pages that "contain" the page_selector field buried in their fields "trees". Since the pages that can contain it are not of the same template and will be changing (any page can start using it), I am not sure it can be solved using the pages API find function. I have tried examining the DB directly (I have no problem with MySQL) but haven't been able to decipher the relations between fields, repeaters and pages. Any help will be appreciated Link to comment Share on other sites More sharing options...
Jan Romero Posted January 12, 2022 Share Posted January 12, 2022 Hi, welcome to the ProcessWire forums! I’m not sure I fully grokked you requirements, but I made you this monstrosity: function getTemplatesFromField(Field $field, array &$templates) { foreach ($field->getTemplates() as $tpl) { $fieldUsingThis = fields()->get('type=FieldtypeFieldsetPage|FieldtypeRepeater, template_id=' . $tpl->id); if ($fieldUsingThis->id) { getTemplatesFromField($fieldUsingThis, $templates); } else { $templates[] = $tpl; } } } $templates = []; getTemplatesFromField(fields()->get('nav_item'), $templates); var_dump($templates); That should print out all templates that contain the field “nav_item” inside their own fieldgroups or nested anywhere inside their FieldsetPage and Repeater fields. You could probably make something similar in SQL with an iterative CTE, but it’s going to be a bit of a pain because some of the data is stored in JSON columns and it’s hard to get from a repeater/fieldsetpage template to its field… Doing it in PHP should be fast enough, because all this info is loaded by ProcessWire anyway. 1 Link to comment Share on other sites More sharing options...
Robin S Posted January 13, 2022 Share Posted January 13, 2022 Another possible way to approach it is to find both normal and repeater pages and then convert the repeater pages into the non-repeater pages that contain them. FieldsetPage is a kind of Repeater. // Function to get the root container page when the supplied page might be a RepeaterPage function getRootContainer($page) { if($page instanceof RepeaterPage) { return getRootContainer($page->getForPage()); } else { return $page; } } // Get your Page Reference field $f = $fields->get('page_selector'); // Get the templates that contain the field (including Repeater templates) $tpls = $f->getTemplates(); // Implode to a string for use in a selector $tpls_string = $tpls->implode('|', 'name'); // Find pages (including Repeater pages) where the field is populated // The check_access=0 is so that Repeater pages are found when $user is a non-superuser $items = $pages->find("template=$tpls_string, check_access=0, $f.count>0"); // An empty PageArray that will hold the results $results = new PageArray(); foreach($items as $item) { // Convert any Repeater pages to their root container page and add to the results $results->add(getRootContainer($item)); } // Now use $results as needed 3 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now