Jump to content

ProcessWire: ProcessModule: Can't delete Page because it has one or more children.


Inxentas
 Share

Recommended Posts

I'm developing a module that installs a couple of nested pages beneat the Admin page (and assigns the module as a Process to them).

In the install method, I create these pages from top to bottom. In the uninstall method, I do the reverse and delete all children before deleting their parent page. However, I get the following error message:

ProcessWire: ProcessModule: Can't delete Page 1563 because it has one or more children.

This is strange as the script makes sure that isn't the case, as these are all deleted. Afterwards, their children are indeed nicely deleted.

I've done a couple of checks. When I first delete all children, and use $message to print out $p->children()->count that returns zero, as expected.

Yet $p cannot be deleted after confirming it's zero, because "it has children". Does anyone have any idea why?

 

Extra information: Beneath the Admin page I create a new page called "Webshop" and assign my module as a Process to this page. This creates a button in the menu that leads to the primary admin interface of the webshop, for which I use a view. This all works nicely. The module installs a template named "orders" beneath this page, as I was planning to collect webshop orders beneath that one. In the uninstall method, I make sure to first delete all pages of the template "order" and "orders" before I attempt to delete the Webshop Process page. On an unintall attempt, I get above error message, but when I check whether the page it references (1563) indeed has children, these are indeed deleted in accordance with my code. Only the Webshop page remains, and it's Process is (logically) empty.

Link to comment
Share on other sites

Hi @Inxentas You can set before hook to Process::installPage and Process::uninstallPage from within your install and uninstall methods and from these hooks manually firstly remove nested pages the main process page of your module. 

Link to comment
Share on other sites

1 hour ago, Zeka said:

Hi @Inxentas You can set before hook to Process::installPage and Process::uninstallPage from within your install and uninstall methods and from these hooks manually firstly remove nested pages the main process page of your module. 

I've tried this, and put a $this->message() call in the hooked methods for now. They are not called at all. The pages are also not "installed" but created in the API like this:

$admin = $this->wire()->pages->get("title=Admin");
 
        $webshop = new ProcessWire\Page();
        $webshop->template = "admin";
        $webshop->title = "Webshop";
        $webshop->icon = "cogs";
        $webshop->parent = $admin;
        $webshop->process = $this;
        $webshop->save();
 
        $orders = new ProcessWire\Page();
        $orders->template = "page-orders";
        $orders->name = "orders";
        $orders->title = "Orders";
        $orders->parent = $webshop;
        $orders->save();
Link to comment
Share on other sites

I've tried adding the hooks to the init method. I also used my own module name. This works.

public function init()
    {
        $this->addHookBefore('Webshop::uninstall', function($event){
            $this->deleteProcessChildren();
        });
       
        $this->addHookAfter('Webshop::uninstall', function($event){
            $this->deleteProcesses();
        });
    }

But alas, even when I explicitly set a BEFORE hook to delete all children... and an AFTER hook to delete the process itself...

I still get the same message.

Because I get that error, the module isn't truly uninstalled, but it DOES delete the children of the Process page.

If I then attempt to uninstall it again, it suddenly works because the previous attempt deleted all children already.

But whenever I try to do this in the same request, I get the message that the Process Page still has children, so somehow it's being called too early or something. I've added a $message to the loop that runs through the Process Pages children. As you can see it deletes the "orders" page (second line) before it tries to delete the Process page (last line).

  • Webshop: deleteProcessChildren
  • Webshop: process child deleted: orders
  • Webshop: Deleted 0 Pages.
  • Webshop: Deleted 3 Templates.
  • Webshop: Deleted 5 Fields.
  • Webshop: Permission 'shop-owner' deleted.
  • Webshop: deleteProcesses
Link to comment
Share on other sites

On 3/27/2023 at 4:23 PM, BitPoet said:

Does calling $pages->uncacheAll() before deleting your process page fix it?

Since $page->delete takes an option argument for recursion. So you could just call $webshop->delete(true) and forgo deleting orders and their parent page individually.

Yes! Well, not immediately. When I do this to the Process it still gave me an error, but when I used the argument in the lines that delete pages by their template (orders and order pages are deleted first) then it works. I still explicitly delete the individual orders by template before I delete their parent, but I'll experiment a bit with this technique. Again PW surprises me with it's simplicity. One last question: notifications are going to ask me to mark your post as the best solution. But I don't see any options for that. How can I do this?

Link to comment
Share on other sites

On 3/30/2023 at 11:15 AM, Inxentas said:

One last question: notifications are going to ask me to mark your post as the best solution. But I don't see any options for that. How can I do this?

Glad to hear my suggestion works. Don't bother about that text in notifications. It's part of a default mail template, but the option to mark solutions isn't enabled in the forum.

  • Like 1
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...