Go to main content

Textpattern CMS support forum

You are not logged in. Register | Login | Help

#1 2016-06-30 08:13:10

NicolasGraph
Plugin Author
From: France
Registered: 2008-07-24
Posts: 860
Website

safe_update on plugin deletion does not work

Hi,
I call safe_delete and safe_update on plugin deletion but safe_update has no effect (while safe_delete works well)…
The following code should change any invalid form type to misc.

safe_update('txp_form', "type = 'misc'", "type not in ('article', 'category', 'comment', 'file', 'link', 'misc', 'section')");

Any clue?

Edit: when called on disabled instead of deteted, it works. …I mean when I disable the plugin but not when I delete it before to disable. Weird; as the disabled event should fires before deteted, no?

Last edited by NicolasGraph (2016-06-30 08:48:58)


Nicolas
Follow me on Twitter and GitHub!
Multiple edits are usually to correct my frenglish…

Offline

#2 2016-07-01 12:01:11

NicolasGraph
Plugin Author
From: France
Registered: 2008-07-24
Posts: 860
Website

Re: safe_update on plugin deletion does not work

Is there any reason why safe_update() would work on disable but not on delete?


Nicolas
Follow me on Twitter and GitHub!
Multiple edits are usually to correct my frenglish…

Offline

#3 2016-07-01 14:53:47

Bloke
Developer
From: Leeds, UK
Registered: 2006-01-29
Posts: 11,271
Website GitHub

Re: safe_update on plugin deletion does not work

NicolasGraph wrote #300048:

I call safe_delete and safe_update on plugin deletion but safe_update has no effect (while safe_delete works well)… Any clue?

None whatsoever! My test plugin abc_callback_test worked fine for me. On 4.6-dev at least. It fired both disabled (even if the plugin was already disabled… erm?) and deleted lifecycle events, which I intercepted:

register_callback(
   'abc_callback_welcome',
   'plugin_lifecycle.abc_callback_test'
);

function abc_callback_welcome($evt, $stp)
{
    $msg = '';

    switch ($stp) {
        case 'disabled':
            $msg = 'disabled :-)';
            dmp($msg);
            break;
        case 'deleted':
            safe_update('txp_form', "type = 'misc'",
               "type not in ('article', 'category', 'comment', 'file', 'link', 'misc', 'section')");
            $msg = 'deleted :-)';
            dmp($msg);
            break;
    }

    return $msg;
}

That worked. I saw both disabled and deleted messages on-screen when I deleted the plugin from the Admin->Plugins panel. In addition, the Form I had intentionally mangled (via SQL) to be of type squid was reverted to misc.

Baffling.


The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.

Txp Builders – finely-crafted code, design and Txp

Offline

#4 2016-07-01 15:49:41

NicolasGraph
Plugin Author
From: France
Registered: 2008-07-24
Posts: 860
Website

Re: safe_update on plugin deletion does not work

Bloke wrote #300107:

Baffling.

Yes. Anyway, thanks for your test, I’m also able to display both messages on delete in my plugin but no update on db side; I need to investigate a bit more…

Edit: I’m also on Txp 4.6, on Mamp.

Last edited by NicolasGraph (2016-07-01 15:59:02)


Nicolas
Follow me on Twitter and GitHub!
Multiple edits are usually to correct my frenglish…

Offline

#5 2016-07-01 17:39:54

NicolasGraph
Plugin Author
From: France
Registered: 2008-07-24
Posts: 860
Website

Re: safe_update on plugin deletion does not work

Ok, I get it; a callback fires after the plugin deleted step and reset the db data…
Is there a way to not fire callbacks following a plugin delete or should I change events and steps?

Last edited by NicolasGraph (2016-07-01 17:40:15)


Nicolas
Follow me on Twitter and GitHub!
Multiple edits are usually to correct my frenglish…

Offline

#6 2016-07-01 21:33:09

Bloke
Developer
From: Leeds, UK
Registered: 2006-01-29
Posts: 11,271
Website GitHub

Re: safe_update on plugin deletion does not work

NicolasGraph wrote #300114:

Ok, I get it; a callback fires after the plugin deleted step and reset the db data…

Really? I thought the delete step fired just before the plugin was actually deleted. Otherwise it wouldn’t be able to run its own code to tidy itself up, as it would already be deleted before the callback fired!

Is there a way to not fire callbacks following a plugin delete or should I change events and steps?

Not sure I understand. You have two broad options:

  1. If you don’t want to use lifecycle events, don’t set the lifecycle flag in the plugin template.
  2. If you do want to use them, set the flag and then either:
    1. Raise one callback per event and step that you want to process; or
    2. Raise a single callback on the event and then use the passed $stp (2nd parameter) in your callback function to differentiate between the steps: installed, enabled, disabled, or deleted — like I did in the code above.

In all cases, if you don’t elect to handle a particular step, the callback is not executed for your plugin.


The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.

Txp Builders – finely-crafted code, design and Txp

Offline

#7 2016-07-02 13:31:17

NicolasGraph
Plugin Author
From: France
Registered: 2008-07-24
Posts: 860
Website

Re: safe_update on plugin deletion does not work

Bloke wrote #300120:

Really? I thought the delete step fired just before the plugin was actually deleted. Otherwise it wouldn’t be able to run its own code to tidy itself up, as it would already be deleted before the callback fired! […]

Thanks Stef; I think that I need to clarify; the callback on the plugin delete fires and update form types, however the plugin continue to fires the following callbacks in the plugin (there is one on admin_side, body_end) and reload my custom forms… I expected that no callback fires anymore if the plugin is deleting but it is not as simple…


Nicolas
Follow me on Twitter and GitHub!
Multiple edits are usually to correct my frenglish…

Offline

#8 2016-07-02 14:40:06

Bloke
Developer
From: Leeds, UK
Registered: 2006-01-29
Posts: 11,271
Website GitHub

Re: safe_update on plugin deletion does not work

NicolasGraph wrote #300128:

I expected that no callback fires anymore if the plugin is deleting but it is not as simple…

Interesting, thanks for the clarification. So the deletion lifecycle event fires, but the plugin isn’t actually deleted until the page loads, which means that any page-based callbacks that are in use by the plugin probably still fire. As you say, an unexpected outcome.

Without actually testing it, here’s what I think is happening:

  • In order to fire a deletion callback — indeed, in order for Txp to even know about the fact that the plugin intends to raise such a callback — each plugin needs to be loaded first. Yes, even on the Admin->Plugins page, which doesn’t actually run plugins. They still need to be invoked to check if they need to do any tidy up. So all plugins with the lifecycle flag raised are called.
  • As the plugin loads, it registers its intent with the callback system via a series of register_callback() functions. These are loaded into Txp’s internals ready to be called when the appropriate callback point is reached during the rendering of the page.
  • Txp raises its digital paw “anyone got anything to disable/delete?”
  • Your plugin says “yes please” and runs the disable/delete events.
  • It is deleted from the database but, crucially, because it is eval()’d code, it is still in memory. Thus, still active. Thus all callbacks are still registered and active.
  • The page is rendered. Txp says “anyone got any interest in admin_side/head_end?” (for example). Your plugin in memory says “yes please” and runs its callback function.
  • Page continues to load. When it gets to the bit that lists the plugins, it queries the database for the list of plugins. Yours is not there, thus is missing from the list, but for that one page refresh only it is effectively still there and “alive”.

That’s my best guess. And it is a guess. But if that is accurate, the way to bypass that might be to ensure that only lifecycle callbacks are raised outside the plugin’s scope — i.e. globally inside the if (txpinterface === 'admin') segment. Then, inside your plugin’s kickstart routine, raise the rest of the callbacks that are necessary to run on that page. Like this (untested):

if (txpinterface === 'admin') {
    new abc_cool();
} elseif (txpinterface === 'public') {
    // Register and define any public tags here.
}

/**
 * Admin interface.
 */
class abc_cool
{
    /**
     * The plugin's event as registered in Txp.
     *
     * @var string
     */
    protected $abc_cool_event = 'abc_cool';

    /**
     * Constructor to set up callbacks and environment.
     */
    public function __construct()
    {
        global $event, $step;

        // Always register lifecycle callbacks.
        register_callback(array($this, 'welcome'), 'plugin_lifecycle.' . $this->abc_cool_event);

        if ($event === $this->abc_cool_event) {
            // Only register plugin-specific callbacks if on its own admin panel.
            add_privs($this->abc_cool_event, '1, 2, 3');
            register_tab('extensions', $this->abc_cool_event, gTxt('abc_cool_tab_name'));
            register_callback(array($this, 'dispatcher'), $this->abc_cool_event);
            register_callback(array($this, 'inject_css'), 'admin_side', 'head_end');
            ...
        }
    }

    /**
     * Handle lifecycle events.
     *
     * @param  string $evt Textpattern event (lifecycle event)
     * @param  string $stp Textpattern step (action)
     */
    public function welcome($evt, $stp)
    {
        switch ($stp) {
            case 'disabled':
               // ...
            break;
        case 'deleted':
               // ...
            break;
        }
    }

    /**
     * Plugin jump-off point.
     *
     * Switch on $stp here and run appropriate function if it matches
     * and bouncer() permits it to run.
     *
     * @param  string $evt Textpattern event (panel)
     * @param  string $stp Textpattern step (action)
     */
    protected function dispatcher($evt, $stp)
    {
        // ...
    }

    /**
     * Add CSS to page.
     *
     * @param  string $evt Textpattern event (panel)
     * @param  string $stp Textpattern step (action)
     */
    protected function inject_css($evt, $stp)
    {
        // ...
    }
}

Not sure if that’ll work, and there will be nuances and variations if you want the plugin to do stuff on panels other than its own, but it seems logical to me. You may have to register tabs and privs in the global scope, I’m not sure. But the general sentiment of “only register callbacks when they’re needed” might save you from this unintended behaviour you’re seeing.

See how you get on, and by all means ask questions if things aren’t clear or if I’ve screwed up the example.

Last edited by Bloke (2016-07-02 14:44:47)


The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.

Txp Builders – finely-crafted code, design and Txp

Offline

#9 2016-07-02 18:36:44

NicolasGraph
Plugin Author
From: France
Registered: 2008-07-24
Posts: 860
Website

Re: safe_update on plugin deletion does not work

Bloke wrote #300130:

[…] See how you get on, and by all means ask questions if things aren’t clear or if I’ve screwed up the example.

Ok, thanks, I’ll test it and come back to you, but I already think that I now have a solution.


Nicolas
Follow me on Twitter and GitHub!
Multiple edits are usually to correct my frenglish…

Offline

#10 2016-07-04 08:13:31

NicolasGraph
Plugin Author
From: France
Registered: 2008-07-24
Posts: 860
Website

Re: safe_update on plugin deletion does not work

Ok, If fixed this issue by setting a variable in the uninstall function and and by checking it in the function used in the admin_side/body_end callback.

So the second function is still called after the plugin/deleted callback but it does nothing if the the plugin is deleting. I think that was the more efficient thing to do as the plugin is special and use its admin_side callback everywhere.

Thanks Stef, you contributed to keep rah_flat alive! (look for deleting in this file to see more…)


Nicolas
Follow me on Twitter and GitHub!
Multiple edits are usually to correct my frenglish…

Offline

Board footer

Powered by FluxBB