Jump to content

Sub-pages not visible in page tree


daniel-not-dan
 Share

Recommended Posts

I have a client who has a veeeeeery limited knowledge of computers. I built a site for her (annachobor.com) and a cms (with Processwire, obviously) and gave her detailed directions on how to update her content. 

There are several sub-pages under her /services/ page (and then some sub-sub-pages beneath those). She has brought it to my attention that she cannot see those sub-pages at all in the page tree on the dashboard. She clicks on "Services" and nothing shows up underneath it. However, due to her knowing very little about computers, she can't take a screenshot for me (and she's across the country, so I can't visit). 

So far I have had her try a different browser, but she has the same result in Chrome and Internet Explorer. She is on windows 8, I believe. I also had her check both her browsers at this site: https://www.whatismybrowser.com/is-javascript-enabled to make sure her Javascript was enabled. She gets "yes" for both browsers. 

Has anyone come across this issue before? I very much doubt it's a processwire issue, but I find you all so helpful that I was hoping someone might have some insight into it. If I can at least figure out what's causing it, I can send her off to someone locally who she can explain the issue to, and hopefully they can fix it for her.

Thank you!

Link to comment
Share on other sites

Hey there,

I don't know which Admin theme you are using, but I think both Default and AdminThemeReno use the "ProcessPageList" module (in /wire/modules/Process/) to render the page tree on the "/admin/page" link. I checked the module settings and it doesn't have an option to select "show all subpages" (for good reason - there can be a lot of nesting or just a lot of children, which could slow down the render considerably or fail altogether), so some customization might be required in your case.

I really like to root around in the module files, and found that in this module's "ProcessPageList.module" file an AJAX request is constructed to render the list, and the request includes which rootID to build the tree on (in this case it would be the homepage, so ID=1) and also includes whether/which IDs should be "open" - same as if you navigated to "/admin/page/?open=282" and it would show the whole page tree with all the parents of page ID 282 open and all its children visible.

In the ProcessPageList.module file, this render function (in dev version) starts on #L117. You can see that the $openPageIDs array is defined from L122 to #L128:

        $openPageIDs = array();
        if($this->openPage->id > 1) {
                $openPageIDs[] = $this->openPage->id; 
                foreach($this->openPage->parents() as $parent) {
                        if($parent->id > 1) $openPageIDs[] = $parent->id; 
                }
        }
(I'll assume a little familiarity with OO PHP, but if not there is no better place (IMHO) to learn that the module files.)

As you can see above (and in the lines just following the above snippet), the openPagesID parameter in the initial request constructed in the .module file is an array, so we can actually just put in it all the children of the root page which have children, and it will execute the "open" request on each of those pages one-by-one. I tested the following solutions in AdminThemeReno (with PW 2.5.21 dev version) and it worked to open all the sub-page views one after another, so that in a couple of seconds you have the whole tree (subpages included) rendered. You can try out the one which works for your situation (and revert right back to the original in case of errors):

Option 1: If you know that the nesting on your tree is only one level deep, it's pretty easy:

        $openPageIDs = array();

        /**snippet to add:**/

        // $this->openPage->id is a variable of the class instance indicated in the URL as ?open=IDnumber ($input->get->open's value), if it doesn't exist we use the root :
        foreach($this->pages->get($this->openPage->id ? $this->openPage->id : 1)->children as $child){ 
                if($child->numChildren()) 
                        //if it has children, add it to the array of IDs to open:
                        $openPageIDs[] = $child->id; 
        }

        /**end snippet**/

        if($this->openPage->id > 1) {
                $openPageIDs[] = $this->openPage->id; 
                foreach($this->openPage->parents() as $parent) {
                        if($parent->id > 1) $openPageIDs[] = $parent->id; 
                }
        }
The above might be enough for your case, especially if you have only one level deep nesting (only children of homepage have subchildren).

Option 2: If you have a bit more nesting, here's a solution that works. Please beware that I'm not very good at OO PHP myself, and with a lot of children this might be pretty slow. Also, it uses a recursive function, and your PHP extensions might have a limit on how many nested calls are allowed (e.g xdebug allows 100 levels).

Step 1. declare a protected variable for the whole class called $openAll (you can add it just after L26).

Step 2. create a protected method for the class called getChildParents (or something less confusing):

        protected function getChildParents($id){   // pass the function ID of root/parent on which to check

                $p = $this->pages->get($id);

                foreach($p->children as $child){

                        if($child->numChildren()){ 

                                // if child has children, add it to the global variable $openAll:
                                $this->openAll[] = $child->id; 

                                // call this function with child ID as parent ID:
                                $this->getChildParents($child->id); 
                        }
                }
        }	
Step 3. Change the snippet I added in the first solution to the following:
        $openPageIDs = array();

        /**snippet to add:**/

        // instantiate the global variable as an empty array:
        $this->openAll = array();
       
        // call the recursive function starting with the $input->get->open ID which will populate the array we just instantiated:
        $this->getChildParents($this->openPage->id ? $this->openPage->id : 1);

        // since openPageIDs array was empty to begin with, we can just copy our new array into it:
        if(count($this->openAll))
                $openPageIDs = $this->openAll; 

        /**end snippet **/

        if($this->openPage->id > 1) {
                $openPageIDs[] = $this->openPage->id; 
                foreach($this->openPage->parents() as $parent) {
                        if($parent->id > 1) $openPageIDs[] = $parent->id; 
                }
        }
If any particular ID has a LOT of children but no subchildren, you can include a condition in the function to skip its checking.

Option 3: Easiest option of all - if your client won't be creating new subnesting herself (adding children where none existed before), and if you already know which pages you want to open, you can skip all of the above and just instantiate $openPageIDs array to have a list of IDs you always want to open along with the homepage.

In any case, it might take a second or two to have all of them render, so tell her to be patient. :)

(PS: It's very possible there's an easier / less recursive way to do this in PW, in which case hopefully one of the experienced people will chime in and correct my method.)

ETA: I changed the count selector to the built-in numChildren to check for children, which includes hidden children. You can also add the "include=all" condition on any of the ->children() or ->child() calls, especially if you are not seeing hidden/unpublished children where you want to see them. I do want to re-emphasize that this can become a memory intensive operation if applied to a site with many thousands of pages or many sublevels, but hope it helps in your case.

Edited by nickie
  • Like 2
Link to comment
Share on other sites

Can you share a screen via Skype or get her to use TeamViewer?

I am going to have to try to explain how to do one of those things (prob Skype), seeing as whatever the issue is, it doesn't seem to be anything simple/self-explanatory.

nickie, thanks for your ideas. That is an extremely generous answer and I shall have to pick it apart a little later on after I've had my morning coffee. I have not yet had cause to open up any /wire/ files (after probably 10 processwire projects), so this will be a new frontier for me. I'll try it locally first and then if everything still works I'll make the changes to the live site.

I'll report back with more info, hopefully.

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...