Jump to content

access profields table from sibling


fruid
 Share

Recommended Posts

so I have a Profields Table on a sibling's page, trying to access it from its sibling's page (DUH!) which is $page now, cause that's where I am right now.

I do

    $toc = $page->siblings("template=tableofcontents")->tableofcontents_table;
    $toc->render();

or

    $toc = $page->siblings("template=tableofcontents");
    $toc = $toc->tableofcontents_table;
    $toc->render();

but it just won't work because Call to a member function render() on null

The table clearly is there and clearly is a sibling and its template is as stated and the table also.

Please help me quick, about to throw the computer out the window, thank you.

Link to comment
Share on other sites

1 hour ago, fruid said:

Please help me quick, about to throw the computer out the window, thank you.

Maybe a sign that it's times for a break 😄.

1 hour ago, fruid said:

$toc = $page->siblings("template=tableofcontents")->tableofcontents_table;

Sometimes it helps to 'speak out your code' to determine if it makes sense. Have a look at that line. tableofcontents_table, I assume, is your Profields Table. Reading that out loud, your code is saying, find me siblings (PLURAL) of this page and get me the value of its (SINGLE) tableofcontents_table field. Doesn't sound right, does it? It's like saying 'find me 10 oranges (PLURAL) and show me its (SINGLE) price. That's wrong. The question would be, which orange's price? We have 10 oranges here! It should read, 'find me 10 oranges (PLURAL) and show me their (PLURAL) prices.  Aha, so, we are dealing with a collection. Any collection has to be iterated (foreach) to get each members individual value. Alternatively, you could ask for the first(), last() or nth() orange to deal with one member only.

OK, so I need to get some sleep too. The docs say this about $page->siblings():

Quote

Return this Page’s sibling pages, optionally filtered by a selector.

 

Quote

 Return value

 $toc is a PageArray. 

If you run this in Tracy console: 

<?php

d($page->siblings("template=tableofcontents")->tableofcontents_table);// null

You will get the value null, hence your error message since you are doing this null->render().

Now for some unsolicited advice 😁.

  1. TracyDebugger is your best friend.
  2. The table clearly is there and clearly is a sibling and its template is as stated and the table also. Whilst this might be the case, it is best to always check if your selector/query returned something (and its type) before you start working with it.

Hope this helps.

ps: Profields Table has its own VIP support forum, accessible to you if you have a current subscription

  • Like 3
Link to comment
Share on other sites

  • 3 months later...

need to continue this thread, trying to improve my script but I'm out of ideas.

What I want is a hook that adds a row to the table-of-contents-table with certain details when a page (sibling to the table-of-content) is saved and removed when it's changing status, i.e. trashed, hidden or unpublished.

I tried in many ways already, I never get it to do what I need upon trashing a page plus the code was getting too complicated anyway so I tried something else. I just want the rows to be created or deleted when the table-of-contents-page itself is saved. Then, when I save any other siblingspage, just run a hook that saves the table-of-contents-page. Sounds like a plan? The code is quite short…

But again, I just can't seem to hook the trash event. My guess is that when I'm trashing the page, the parent and siblings change and so I cannot refer to them this way? 

$wire->addHookafter('Pages::saved', function($event) {        
    $page = $event->arguments[0];
    if ($page->parent->template == 'magazine' && $page->template != 'tableofcontents') :        
        $page->siblings("template=tableofcontents")->save("tableofcontents_table");
    endif;

    if ($page->template == 'tableofcontents') :    
        $parent = $page->parent;
        $page->of(false); 
        $toc = $page->tableofcontents_table;
        $contents = $page->siblings(true);

        foreach ($contents as $content) :

            $content_id = (int)$content->id;        
            $content_url = $content->url;
            $content_page = $content->page_number;
            $content_title = $content->title;

            if ($parent->child("id=$content_id") == false) {
                $item = $toc->get("content_id=$content_id"); 
                $toc->remove($item);
                $event->message("deleted row");
            } else {
                if ($toc->has("content_id=$content_id") == false) {
                    $item = $toc->makeBlankItem(); 
                    $item->content_url = $content_url;
                    $item->content_page = $content_page;
                    $item->content_title = $content_title;
                    $item->content_id = $content_id;
                    $toc->add($item); 
                    $event->message("create row");
                } else {
                    $item = $toc->get("content_id=$content_id"); 
                    $item->content_url = $content_url;
                    $item->content_title = $content_title;
                    $item->content_page = $content_page;
                    $event->message("update row");
                }                    
            }

        endforeach;
        
        $page->save("tableofcontents_table");
        $page->of(true);
    
    endif;
    
});

 

Link to comment
Share on other sites

OK so I made some adjustments because I figured the best way to remove a row in the table of contents when that page is deleted is to make use of a addHookBefore, because at this point the page "still knows" its parents and siblings. However, if I go that way, updating the table only when saving the table of contents page gets in the way because the script would check the pages (siblings) and since it's a addHookBefore (hooked before it's deleted) it would still exist at this point so basically would be deleted with the hook but also re-added with the hook that runs when the table of contents page is saved. Pretty confusing for newcomers I guess but not for this community, I'm sure you had dilemmas like that yourself before.

So I did the following instead:

$wire->addHookAfter('Pages::saved', function($event) {

	if ($page->parent->template == 'magazine' && $page->template != 'tableofcontents') :
            
        $parent = $page->parent;
        $toc = $parent->child("template=tableofcontents");
        $rows = $toc->tableofcontents_table;
        $contents = $page->siblings(true);

        $page_id = $page->id;        
        $page_url = $page->url;
        $page_number = $page->page_number;
        $page_title = $page->title;

        $toc->of(false); 

		// creating a new row for this page
        if ($rows->has("content_id=$page_id") == false) {
            $item = $rows->makeBlankItem(); 
            $item->content_id = $page_id;
            $item->content_url = $page_url;
            $item->content_title = $page_title;
            $item->content_page = $page_number;
            $rows->add($item); 
            $event->message("row created");
		// updating an existing row for this page
        } else {
            $item = $rows->get("content_id=$page_id"); 
            $item->content_url = $page_url;
            $item->content_title = $page_title;
            $item->content_page = $page_number;
            $event->message("row updated");
        }              
    
		// this is new: also loop through the rows and delete any which don't have a corresponding page
        foreach ($rows as $row) :
            $row_id = $row->content_id;
            if ($contents->has("id=$row_id") == false) {
                $rows->remove($row);
                $event->message("row deleted");
            }
        endforeach;
    
        $toc->save("tableofcontents_table"); 
        $toc->of(true); 
     
    endif;

});

and the other hook:

$wire->addHookBefore('Pages::trashed', function($event) {

    $page = $event->arguments[0];
    $parent = $page->parent;
    if ($parent->template == 'magazine') :
        $toc = $parent->child("template=tableofcontents");
        $rows = $toc->tableofcontents_table;
        $page_id = $page->id;        
        $toc->of(false); 
        $item = $rows->get("content_id=$page_id");
        $rows->remove($item);
        $event->message("row deleted");
        $toc->save("tableofcontents_table");
        $toc->of(true);
    endif;

});

creating, unpublishing, hiding and editing pages do change the rows of the table of contents as intended but I can't get it to delete a row when trashed.

Any ideas why? 

Link to comment
Share on other sites

  • 2 weeks later...

OK so I had some progress, the hooks, I guess were conflicting each other. One hook's intention is to delete the page from the other page's table but it was triggered before the page is saved and also triggered the other page's save-event. See here:

so basically…
page A is the page that is saved
page B is the table of content (sibling)

page A -> addHookbefore: trash: remove from page B, save page B -> addHook: check siblings -> finds and adds page A -> page A is saved i.e. trashed but stil in the page B list.

Here's the code – if you're still interested 😅

 

// update TABLE OF CONTENTS when saving individual page :D 
// works for editing, hiding/unhiding, publishing/unpublishing and trashing :D 
// does NOT work for moving pages (to different parent) :D 
// when moving a page, save the former parent page (table of contents) :D 

$wire->addHook('Pages::saveReady', function($event) {

    $item = $event->arguments[0];
    
    if ($item->parent->template != 'magazine') return;
    if ($item->template != 'tableofcontents') return;
    
    $parent = $item->parent;

    $contents = $item->siblings(true);
    $rows = $item->tableofcontents_table;
    foreach ($contents as $content) :
        updateRows($rows, $content, $event);
    endforeach;
    cleanRows($rows, $item, $event);
            
});


// update TABLE OF CONTENTS when saving TABLE OF CONTENTS page :D 

$wire->addHookAfter('Pages::saved', function($event) {

    $item = $event->arguments[0];
    
    if ($item->parent->template != 'magazine') return;
    if ($item->template == 'tableofcontents') return;
    
    $parent = $item->parent;
    $toc = $parent->child("template=tableofcontents");

    $rows = $toc->tableofcontents_table;
    
    $toc->of(false); 

    updateRows($rows, $item, $event);
    cleanRows($rows, $item, $event);
    
    $toc->save("tableofcontents_table"); 
    $toc->of(true); 
            
});


// *update TABLE OF CONTENTS when trashing a page :D 

$wire->addHookBefore('Pages::trash', function($event) {
    
    $page = $event->arguments[0];
    $parent = $page->parent;
    if ($parent->template != 'magazine') return;
    $toc = $parent->child("template=tableofcontents");
    $rows = $toc->tableofcontents_table;
    $page_id = $page->id;        
    $toc->of(false); 
    $item = $rows->get("content_id=$page_id");
    $rows->remove($item);
    $event->message("row deleted");
    $toc->save("tableofcontents_table");
    $toc->of(true);
});

// this just won't work, thought it would work just as well as trashed but nope

//$wire->addHookBefore('Pages::moved', function(HookEvent $event) {
//    $page = $event->arguments[0];
//    $parent = $page->parent;
//    if ($parent->template != 'magazine') return;
//    $toc = $parent->child("template=tableofcontents");
//    $rows = $toc->tableofcontents_table;
//    $page_id = $page->id;        
//    $toc->of(false); 
//    $item = $rows->get("content_id=$page_id");
//    $rows->remove($item);
//    $event->message("row deleted");
//    $toc->save("tableofcontents_table");
//    $toc->of(true);
//});


// add/update details to pages that are missing from the TABLE OF CONTENTS :D

function updateRows($rows, $item, $event) {
        
    $item_id = $item->id;        
    $item_url = $item->url;
    $item_title = $item->title;
    $item_number = $item->page_number;
    if ($rows->has("content_id=$item_id") == false) {
        $row = $rows->makeBlankItem(); 
        $row->content_id = $item_id;
        $row->content_url = $item_url;
        $row->content_title = $item_title;
        $row->content_page = $item_number;
        $rows->add($row); 
        $event->message("row created");
    } else {
        $row = $rows->get("content_id=$item_id"); 
        $row->content_url = $item_url;
//        $row->content_title = $item_title;
        $row->content_page = $item_number;
        $event->message("row updated");
    }              
}


// remove obsolete pages from the TABLE OF CONTENTS :D

function cleanRows($rows, $item, $event) {

    $contents = $item->siblings(true);
    foreach ($rows as $row) :
        $row_id = $row->content_id;
        if ($row_id == '') continue;
        if ($contents->has("id=$row_id") == false) {
            $rows->remove($row);
            $event->message("row deleted");
        }
    endforeach;
    
}

 

 

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...