Quantcast

register_uninstall_hook VS uninstall.php

classic Classic list List threaded Threaded
25 messages Options
12
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

register_uninstall_hook VS uninstall.php

jayarjo
Can anyone explain a bit more deeply, what is meant in the paragraph below?
Especially in the part about "The plugin should not run arbitrary code
outside of functions"?

"The plugin should not run arbitrary code outside of functions, when
registering the uninstall hook. In order to run using the hook, the plugin
will have to be included, which means that any code laying outside of a
function will be run during the uninstall process. The plugin should not
hinder the uninstall process. "

http://codex.wordpress.org/Function_Reference/register_uninstall_hook

There is always some code inside the plugin right? register_uninstall_hook
looks more convenient, 'cause for example I use variable in option and table
names, which depend on the classname of the plugin, or for example I want to
use variables form within my plugin to check some conditions before
uninstalling. And by the way can I use array($this, 'callback') type of
callback in register_uninstall_hook?

--
Davit Barbakadze
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

Dion Hulse (dd32)
Basically, Your plugin shouldnt run any PHP upon inclusion OTHER THAN
add_action/add_Filter()

<?php
/* header..*/

add_action('....
register_uninstall_hook...
?>

Is Good.

This is bad:
 <?php
/* header..*/

if ( strpos(.....) )
  wp_redirect(....
if ( something )
  include somethingelse.php

add_action('....
register_uninstall_hook...
?>

And no, You cannot use array(&$this in uninstall hooks, the uninstall hook
is stored within the database, its not determined at run time. Your plugin
will not recieve init/plugins_loaded/admin_init, etc hook firings when the
uninstall hook is called, Its a pure "Heres some SELF CONTAINED code to run
to clean up"

On 7 May 2010 09:52, Davit Barbakadze <[hidden email]> wrote:

> Can anyone explain a bit more deeply, what is meant in the paragraph below?
> Especially in the part about "The plugin should not run arbitrary code
> outside of functions"?
>
> "The plugin should not run arbitrary code outside of functions, when
> registering the uninstall hook. In order to run using the hook, the plugin
> will have to be included, which means that any code laying outside of a
> function will be run during the uninstall process. The plugin should not
> hinder the uninstall process. "
>
> http://codex.wordpress.org/Function_Reference/register_uninstall_hook
>
> There is always some code inside the plugin right? register_uninstall_hook
> looks more convenient, 'cause for example I use variable in option and
> table
> names, which depend on the classname of the plugin, or for example I want
> to
> use variables form within my plugin to check some conditions before
> uninstalling. And by the way can I use array($this, 'callback') type of
> callback in register_uninstall_hook?
>
> --
> Davit Barbakadze
> _______________________________________________
> wp-hackers mailing list
> [hidden email]
> http://lists.automattic.com/mailman/listinfo/wp-hackers
>
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

Andrew Nacin-2
Arbitrary code is referring to code that is not wrapped inside a function,
with the exception of course of add_action and add_filter calls (and
_ref_array) tying those functions to hooks. (And hook registrations for
activation, deactivation, uninstall, etc.)

Generally speaking, a plugin should never do anything before the init hook.
That includes the enqueue of scripts and styles, the registration of custom
post types and taxonomies, and so much else.

Since the plugin file needs to be included to execute the uninstall
function, that code would run here. You don't want that.

As Dion said, you cannot use a class method for a callback for an uninstall
hook. You also cannot use multiple uninstall callbacks. If you need a more
complex uninstall process, use uninstall.php. Make sure you check for
defined( 'WP_UNINSTALL_PLUGIN' ) before continuing (die if it is not
defined) when using the uninstall.php file.
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

scribu
In reply to this post by Dion Hulse (dd32)
On Fri, May 7, 2010 at 7:56 PM, Dion Hulse (dd32) <[hidden email]>wrote:

> And no, You cannot use array(&$this in uninstall hooks, the uninstall hook
> is stored within the database, its not determined at run time.
>

Actually, you can, but it causes an extra SQL query on each page load.

Also, you can only use _one_ hook with register_uninstall_hook.

Related discussion:

http://core.trac.wordpress.org/ticket/12754


--
http://scribu.net
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

jayarjo
In reply to this post by Dion Hulse (dd32)
Hmmm... dont' you think that there is something wrong with this (current?)
solution?

On Fri, May 7, 2010 at 8:56 PM, Dion Hulse (dd32) <[hidden email]>wrote:

> Basically, Your plugin shouldnt run any PHP upon inclusion OTHER THAN
> add_action/add_Filter()
>
> <?php
> /* header..*/
>
> add_action('....
> register_uninstall_hook...
> ?>
>
> Is Good.
>
> This is bad:
>  <?php
> /* header..*/
>
> if ( strpos(.....) )
>  wp_redirect(....
> if ( something )
>  include somethingelse.php
>
> add_action('....
> register_uninstall_hook...
> ?>
>
> And no, You cannot use array(&$this in uninstall hooks, the uninstall hook
> is stored within the database, its not determined at run time. Your plugin
> will not recieve init/plugins_loaded/admin_init, etc hook firings when the
> uninstall hook is called, Its a pure "Heres some SELF CONTAINED code to run
> to clean up"
>
> On 7 May 2010 09:52, Davit Barbakadze <[hidden email]> wrote:
>
> > Can anyone explain a bit more deeply, what is meant in the paragraph
> below?
> > Especially in the part about "The plugin should not run arbitrary code
> > outside of functions"?
> >
> > "The plugin should not run arbitrary code outside of functions, when
> > registering the uninstall hook. In order to run using the hook, the
> plugin
> > will have to be included, which means that any code laying outside of a
> > function will be run during the uninstall process. The plugin should not
> > hinder the uninstall process. "
> >
> > http://codex.wordpress.org/Function_Reference/register_uninstall_hook
> >
> > There is always some code inside the plugin right?
> register_uninstall_hook
> > looks more convenient, 'cause for example I use variable in option and
> > table
> > names, which depend on the classname of the plugin, or for example I want
> > to
> > use variables form within my plugin to check some conditions before
> > uninstalling. And by the way can I use array($this, 'callback') type of
> > callback in register_uninstall_hook?
> >
> > --
> > Davit Barbakadze
> > _______________________________________________
> > wp-hackers mailing list
> > [hidden email]
> > http://lists.automattic.com/mailman/listinfo/wp-hackers
> >
> _______________________________________________
> wp-hackers mailing list
> [hidden email]
> http://lists.automattic.com/mailman/listinfo/wp-hackers
>



--
Davit Barbakadze
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

Azizur Rahman
In reply to this post by Andrew Nacin-2
>
> As Dion said, you cannot use a class method for a callback for an uninstall
> hook. You also cannot use multiple uninstall callbacks. If you need a more
> complex uninstall process, use uninstall.php. Make sure you check for
> defined( 'WP_UNINSTALL_PLUGIN' ) before continuing (die if it is not
> defined) when using the uninstall.php file.
>


Like the uninstall.php to uninstall, can we use install.php or
activation.php for activation process?


Kind Regards,
Azizur Rahman


On Fri, May 7, 2010 at 6:01 PM, Andrew Nacin <[hidden email]> wrote:

> Arbitrary code is referring to code that is not wrapped inside a function,
> with the exception of course of add_action and add_filter calls (and
> _ref_array) tying those functions to hooks. (And hook registrations for
> activation, deactivation, uninstall, etc.)
>
> Generally speaking, a plugin should never do anything before the init hook.
> That includes the enqueue of scripts and styles, the registration of custom
> post types and taxonomies, and so much else.
>
> Since the plugin file needs to be included to execute the uninstall
> function, that code would run here. You don't want that.
>
> As Dion said, you cannot use a class method for a callback for an uninstall
> hook. You also cannot use multiple uninstall callbacks. If you need a more
> complex uninstall process, use uninstall.php. Make sure you check for
> defined( 'WP_UNINSTALL_PLUGIN' ) before continuing (die if it is not
> defined) when using the uninstall.php file.
> _______________________________________________
> wp-hackers mailing list
> [hidden email]
> http://lists.automattic.com/mailman/listinfo/wp-hackers
>
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

Andrew Nacin-2
On Fri, May 7, 2010 at 1:20 PM, Azizur Rahman <
[hidden email] <prodevstudio%[hidden email]>>
wrote:
>
> Like the uninstall.php to uninstall, can we use install.php or
> activation.php for activation process?

No. Those are much more flexible, as they are run either after activation or
just
before deactivation. They can be class methods, what have you. Uninstall is
simply
an exception, and so in 2.7 uninstall.php was introduced so uninstall
scripts can be
isolated and more robust.

On Fri, May 7, 2010 at 1:19 PM, Davit Barbakadze <[hidden email]> wrote:
>
> Hmmm... dont' you think that there is something wrong with this (current?)
> solution?

Not one bit. Use uninstall.php if you want flexibility, or
register_uninstall_hook if you
want simplicity. Bottom line is, we're executing code when a plugin is not
active, so we
need to be nimble about it.

On Fri, May 7, 2010 at 1:07 PM, scribu <[hidden email]> wrote:
> On Fri, May 7, 2010 at 7:56 PM, Dion Hulse (dd32) <[hidden email]
>wrote:
> >
> > And no, You cannot use array(&$this in uninstall hooks, the uninstall
hook
> > is stored within the database, its not determined at run time.
>
> Actually, you can, but it causes an extra SQL query on each page load.

From what I recall from #12754, it needs to be called statically. It's far
better to
use either a simple function, or even better, uninstall.php. And an extra
SQL query
on each page load is an obvious waste of resources.
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

jayarjo
Unfortunately I can't use uninstall.php for my purpose. Or better to say it
would be kinda last resort.

I read the code now and understand what you mean... But, I still find it
pretty weird. Isn't it? Why would you need to store callback in the
database? Or why would you need to call it directly? Why not just to do
do_action('uninstall_' . $file ... and let the user to hook on this and do
whatever he/she finds appropriate? This could eliminate neccessity of using
function_name callback only, and could have been much more cleaner, logical
and convenient in general.

Ok, whatever is the reason behind such solution I don't get, but even if
there's one, I've found very nice workaround, which could work if only
WP_UNINSTALL_PLUGIN would have been defined for register_uninstall_hook
version too. Is there any reason why it's not?


On Fri, May 7, 2010 at 9:26 PM, Andrew Nacin <[hidden email]> wrote:

> On Fri, May 7, 2010 at 1:20 PM, Azizur Rahman <
> [hidden email] <prodevstudio%[hidden email]> <
> prodevstudio%[hidden email] <prodevstudio%[hidden email]>
> >>
> wrote:
> >
> > Like the uninstall.php to uninstall, can we use install.php or
> > activation.php for activation process?
>
> No. Those are much more flexible, as they are run either after activation
> or
> just
> before deactivation. They can be class methods, what have you. Uninstall is
> simply
> an exception, and so in 2.7 uninstall.php was introduced so uninstall
> scripts can be
> isolated and more robust.
>
> On Fri, May 7, 2010 at 1:19 PM, Davit Barbakadze <[hidden email]>
> wrote:
> >
> > Hmmm... dont' you think that there is something wrong with this
> (current?)
> > solution?
>
> Not one bit. Use uninstall.php if you want flexibility, or
> register_uninstall_hook if you
> want simplicity. Bottom line is, we're executing code when a plugin is not
> active, so we
> need to be nimble about it.
>
> On Fri, May 7, 2010 at 1:07 PM, scribu <[hidden email]> wrote:
> > On Fri, May 7, 2010 at 7:56 PM, Dion Hulse (dd32) <[hidden email]
> >wrote:
> > >
> > > And no, You cannot use array(&$this in uninstall hooks, the uninstall
> hook
> > > is stored within the database, its not determined at run time.
> >
> > Actually, you can, but it causes an extra SQL query on each page load.
>
> From what I recall from #12754, it needs to be called statically. It's far
> better to
> use either a simple function, or even better, uninstall.php. And an extra
> SQL query
> on each page load is an obvious waste of resources.
> _______________________________________________
> wp-hackers mailing list
> [hidden email]
> http://lists.automattic.com/mailman/listinfo/wp-hackers
>



--
Davit Barbakadze
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

Andrew Nacin-2
On Fri, May 7, 2010 at 2:09 PM, Davit Barbakadze <[hidden email]> wrote:

> Unfortunately I can't use uninstall.php for my purpose. Or better to say it
> would be kinda last resort.
>
> I read the code now and understand what you mean... But, I still find it
> pretty weird. Isn't it? Why would you need to store callback in the
> database? Or why would you need to call it directly? Why not just to do
> do_action('uninstall_' . $file ... and let the user to hook on this and do
> whatever he/she finds appropriate? This could eliminate neccessity of using
> function_name callback only, and could have been much more cleaner, logical
> and convenient in general.
>
> Ok, whatever is the reason behind such solution I don't get, but even if
> there's one, I've found very nice workaround, which could work if only
> WP_UNINSTALL_PLUGIN would have been defined for register_uninstall_hook
> version too. Is there any reason why it's not?


When you plugin goes through the uninstall process, it isn't going to be
activated by that point. In most cases, it would have been deactivated well
before that page load, which means none of its code is included. Thus,
WordPress uses the option stored in the table to determine what file to
include and what code to execute. Hence why it must work this way, with a
function or a static class method. The rest of the plugin simply will not be
loaded.

WP_UNINSTALL_PLUGIN is only designed for uninstall.php, that way that file
is not unintentionally included or hit with an HTTP request and the
uninstall procedure is run. It's no different from dying at the top of
certain files (such as edit-form-advanced.php) if ABSPATH is not defined.

Hence, you can use uninstall.php, the same way you can use the uninstall
hook, in most cases. In both cases, the PHP code you are running may be
blissfully unaware of anything else your plugin normally does on
initialization.
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

jayarjo
Ok, I understand now what you are doing, but it doesn't answer question -
why.

> In both cases, the PHP code you are running may be
> blissfully unaware of anything else your plugin normally does on
> initialization.

I'd like it to be aware at some extent.

Ok, I will tell you what my workaround was. Since register_uninstall_hook
does include my plugin main file I can execute some code and obviously do
add_action('uninstall_' . plugin_basename(__FILE_), array($this,
'on_unistall'), 0); too, right? If I knew prior to that that it is uninstall
procedure going on I could break execution here (having initialized whatever
I would need later when action will be called) and wait for an action. Then
I could remove default action (my action has higher priority) and do
whatever I need. WP_UNINSTALL_PLUGIN could have helped here a lot.

Do you find any issue with my solution?

The only thing is that I need to know that uninstall is happening and not
just some regular load.

So far I've found only one way to do this - check for: $_POST['action'] ==
'delete-selected'  &&   $_POST['verify-delete'] == 1            &&
in_array(plugin_basename(__FILE__), (array)$_POST['check']).

On Fri, May 7, 2010 at 10:32 PM, Andrew Nacin <[hidden email]> wrote:

> On Fri, May 7, 2010 at 2:09 PM, Davit Barbakadze <[hidden email]>
> wrote:
>
> > Unfortunately I can't use uninstall.php for my purpose. Or better to say
> it
> > would be kinda last resort.
> >
> > I read the code now and understand what you mean... But, I still find it
> > pretty weird. Isn't it? Why would you need to store callback in the
> > database? Or why would you need to call it directly? Why not just to do
> > do_action('uninstall_' . $file ... and let the user to hook on this and
> do
> > whatever he/she finds appropriate? This could eliminate neccessity of
> using
> > function_name callback only, and could have been much more cleaner,
> logical
> > and convenient in general.
> >
> > Ok, whatever is the reason behind such solution I don't get, but even if
> > there's one, I've found very nice workaround, which could work if only
> > WP_UNINSTALL_PLUGIN would have been defined for register_uninstall_hook
> > version too. Is there any reason why it's not?
>
>
> When you plugin goes through the uninstall process, it isn't going to be
> activated by that point. In most cases, it would have been deactivated well
> before that page load, which means none of its code is included. Thus,
> WordPress uses the option stored in the table to determine what file to
> include and what code to execute. Hence why it must work this way, with a
> function or a static class method. The rest of the plugin simply will not
> be
> loaded.
>
> WP_UNINSTALL_PLUGIN is only designed for uninstall.php, that way that file
> is not unintentionally included or hit with an HTTP request and the
> uninstall procedure is run. It's no different from dying at the top of
> certain files (such as edit-form-advanced.php) if ABSPATH is not defined.
>
> Hence, you can use uninstall.php, the same way you can use the uninstall
> hook, in most cases. In both cases, the PHP code you are running may be
> blissfully unaware of anything else your plugin normally does on
> initialization.
> _______________________________________________
> wp-hackers mailing list
> [hidden email]
> http://lists.automattic.com/mailman/listinfo/wp-hackers
>



--
Davit Barbakadze
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

Otto-19
On Fri, May 7, 2010 at 2:08 PM, Davit Barbakadze <[hidden email]> wrote:
> Do you find any issue with my solution?

Only that it seems wholly unnecessary.

What exactly is the issue here? Your plugin shouldn't do anything of
consequence merely from being included. Quite honestly, NO plugin
should do anything of consequence from merely being included.

Take your "on load" stuff and move it inside a function that's hooked
to plugins_loaded instead, so it'll run that stuff after the normal
load process. plugins_loaded doesn't get triggered on the uninstall,
so you'll be safe there.

-Otto
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

Andrew Nacin-2
On Fri, May 7, 2010 at 4:14 PM, Otto <[hidden email]> wrote:

> On Fri, May 7, 2010 at 2:08 PM, Davit Barbakadze <[hidden email]>
> wrote:
> > Do you find any issue with my solution?
>
> Only that it seems wholly unnecessary.
>
> What exactly is the issue here? Your plugin shouldn't do anything of
> consequence merely from being included. Quite honestly, NO plugin
> should do anything of consequence from merely being included.
>
> Take your "on load" stuff and move it inside a function that's hooked
> to plugins_loaded instead, so it'll run that stuff after the normal
> load process. plugins_loaded doesn't get triggered on the uninstall,
> so you'll be safe there.


I completely agree with Otto. I'm not at all sure what you're trying to do,
but I'm sure you can do it without reinventing the wheel 10 times over.

This is honestly why plugins break on new versions of WP -- it's often not
that they do something that the API doesn't provide for, it's that they do
something the API *does *provide for, but *don't* use the API, and that's
what breaks.

You don't need WP_UNINSTALL_PLUGIN to check if you're being uninstalled.
When your uninstall hook is fired, you'll know you're being uninstalled.
Clean up your data so WP can delete you.
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

Jacob Santos-2
In reply to this post by jayarjo
I think the confusion really just stems from the lack of defined purpose
of the uninstall process.

The uninstall process is to clean up data that would otherwise be left
behind when the plugin is deleted. I'm not sure it could be said any
more clearly than that.

>  There is always some code inside the plugin right? register_uninstall_hook
>  looks more convenient, 'cause for example I use variable in option and table
>  names, which depend on the classname of the plugin, or for example I want to
>  use variables form within my plugin to check some conditions before
>  uninstalling. And by the way can I use array($this, 'callback') type of
>  callback in register_uninstall_hook?

I was confused the first time I read this. I think I understand a bit
more. I your case, you should probably have a method in your class that
runs some uninstall processing for each of the classes that has options.
However, I will suggest that a better idea is to just, well I mean the
class names are known, so why not just reference the class names from
within the uninstall process for the options instead of the first
suggestion?

As for the second problem, while array($this, 'callback') won't work,
array('Class_Name', 'callback') will. You will just have to reference
everything in that code statically or as a function. So technically, you
can use a class method, but it will have to be static.


>  Hmmm... dont' you think that there is something wrong with this (current?)
>  solution?


Not at all, it is a very simplified solution for something that can be
extremely difficult to implement otherwise.

 > "The plugin should not run arbitrary code outside of functions"

If you are wondering whether the statement is saying that you should not
use classes when using the uninstall process then the answer is no. Let
me be more clear since it was answered in what might be a double
negative. You may use either classes or functions in your code and the
statement was in no way suggesting that you MUST use functions over
classes. It was an example and if I had to write functions or classes
everywhere I would probably kill myself with the strain of having to
figure that into the correct context of each sentence it applies. It is
simply best practice to not use a class static method for the uninstall
hook, since I mean, it would be basically a function that is namespaced
in a class instead of a real namespace.

I already stated what the arbitrary code means in the last email and
won't restate what is in there. If you must, please read what Dion wrote
again a second or third time and it should be more clear what is really
meant for those two words. I believe Dion was instrumental in the
creation of the initial patch and additional fixes that came after, so I
trust Dion would fully know and understand the purpose and discussion
that went into the patch and additional improvements / fixes. I'm simply
trying to confirm and attempt to further the understanding of what the
uninstall hook and file mean and their purpose.

I believe Nacin and Otto explained some of your problems and will
suggest reading those responses again if further confused. You should be
using the WordPress API and any attempt to bypass will simply fail. The
uninstall process checks for the file or the hook existence before it
will even attempt the uninstall process. If those do not exist, then it
simply will not run.

>  The only thing is that I need to know that uninstall is happening and not
>  just some regular load.


The reason the WP_UNINSTALL_PLUGIN constant is only available for the
file is that it is not needed for the function. The constant is for
security so that the uninstall process is not run by accident. You could
get around it by checking ABSPATH as well, but it is better to check for
the constant to be sure that the plugin is meant to be uninstalled. For
the hook, it is assumed that the plugin is meant to be uninstalled.

>  So far I've found only one way to do this - check for: $_POST['action'] ==
>  'delete-selected'&&    $_POST['verify-delete'] == 1&&
>  in_array(plugin_basename(__FILE__), (array)$_POST['check']).

Please refrain from over thinking the process. You appear to think that
you have to make it harder than it needs to be. If uninstall.php is
included, it will be in function / local scope and after checking for
the WP_UNINSTALL_PLUGIN constant you can assume that it is meant to
uninstall the plugin. If the hook is called, then you can assume that
the plugin is meant to be uninstalled. You do not need to do any more
checks to be sure that the code was meant to be uninstalled.


I do not think more focus needs to be paid for this topic, but I believe
it could be improved by adding additional information based on what was
discussed here to the codex page and to the inline documentation in
WordPress to prevent future confusion as this one. I did not think that
people wouldn't be able to comprehend what was stated in the comment and
I wanted to be as brief as possible to be sure that people read the
comment. It appears I was wrong in this instance and I'm sorry that you
were confused. I do not plan on implementing my suggestion, so I hope it
was fully explained to you.

Jacob Santos


On 5/7/2010 2:08 PM, Davit Barbakadze wrote:

> Ok, I understand now what you are doing, but it doesn't answer question -
> why.
>
>    
>> In both cases, the PHP code you are running may be
>> blissfully unaware of anything else your plugin normally does on
>> initialization.
>>      
> I'd like it to be aware at some extent.
>
> Ok, I will tell you what my workaround was. Since register_uninstall_hook
> does include my plugin main file I can execute some code and obviously do
> add_action('uninstall_' . plugin_basename(__FILE_), array($this,
> 'on_unistall'), 0); too, right? If I knew prior to that that it is uninstall
> procedure going on I could break execution here (having initialized whatever
> I would need later when action will be called) and wait for an action. Then
> I could remove default action (my action has higher priority) and do
> whatever I need. WP_UNINSTALL_PLUGIN could have helped here a lot.
>
> Do you find any issue with my solution?
>
> The only thing is that I need to know that uninstall is happening and not
> just some regular load.
>
> So far I've found only one way to do this - check for: $_POST['action'] ==
> 'delete-selected'&&    $_POST['verify-delete'] == 1&&
> in_array(plugin_basename(__FILE__), (array)$_POST['check']).
>
> On Fri, May 7, 2010 at 10:32 PM, Andrew Nacin<[hidden email]>  wrote:
>
>    
>> On Fri, May 7, 2010 at 2:09 PM, Davit Barbakadze<[hidden email]>
>> wrote:
>>
>>      
>>> Unfortunately I can't use uninstall.php for my purpose. Or better to say
>>>        
>> it
>>      
>>> would be kinda last resort.
>>>
>>> I read the code now and understand what you mean... But, I still find it
>>> pretty weird. Isn't it? Why would you need to store callback in the
>>> database? Or why would you need to call it directly? Why not just to do
>>> do_action('uninstall_' . $file ... and let the user to hook on this and
>>>        
>> do
>>      
>>> whatever he/she finds appropriate? This could eliminate neccessity of
>>>        
>> using
>>      
>>> function_name callback only, and could have been much more cleaner,
>>>        
>> logical
>>      
>>> and convenient in general.
>>>
>>> Ok, whatever is the reason behind such solution I don't get, but even if
>>> there's one, I've found very nice workaround, which could work if only
>>> WP_UNINSTALL_PLUGIN would have been defined for register_uninstall_hook
>>> version too. Is there any reason why it's not?
>>>        
>>
>> When you plugin goes through the uninstall process, it isn't going to be
>> activated by that point. In most cases, it would have been deactivated well
>> before that page load, which means none of its code is included. Thus,
>> WordPress uses the option stored in the table to determine what file to
>> include and what code to execute. Hence why it must work this way, with a
>> function or a static class method. The rest of the plugin simply will not
>> be
>> loaded.
>>
>> WP_UNINSTALL_PLUGIN is only designed for uninstall.php, that way that file
>> is not unintentionally included or hit with an HTTP request and the
>> uninstall procedure is run. It's no different from dying at the top of
>> certain files (such as edit-form-advanced.php) if ABSPATH is not defined.
>>
>> Hence, you can use uninstall.php, the same way you can use the uninstall
>> hook, in most cases. In both cases, the PHP code you are running may be
>> blissfully unaware of anything else your plugin normally does on
>> initialization.
>> _______________________________________________
>> wp-hackers mailing list
>> [hidden email]
>> http://lists.automattic.com/mailman/listinfo/wp-hackers
>>
>>      
>
>
>    

_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

jayarjo
Thank you guys for your responses. I will consider how I can modify my code
with plugins_loaded, which Otto suggested.

>Please refrain from over thinking the process. You appear to think that you
have to make it harder than it needs to be. If
>uninstall.php is included, it will be in function / local scope and after
checking for the WP_UNINSTALL_PLUGIN constant you can
>assume that it is meant to uninstall the plugin. If the hook is called,
then you can assume that the plugin is meant to be
>uninstalled. You do not need to do any more checks to be sure that the code
was meant to be uninstalled.

My code does something in constructor apart from defining actions, I guess
that's what is understood under 'arbitrary code' in codex. So I really need
a conditional to break it at some point.

> I your case, you should probably have a method in your class that runs
some uninstall processing for each of the classes that
> has options. However, I will suggest that a better idea is to just, well I
mean the class names are known, so why not just
> reference  the class names from within the uninstall process for the
options instead of the first suggestion?

I've got options and tables defined that depend on the name of the class -
they use it as namespace, so doing it in API way could be problematic. I
won't know what the prefixes are if I not instantiate my plugin class and it
looks like I can't do that easily with an API.

Ok, what I do is I have my small framework, from which I inherit my all new
plugins. My friends are using it too, so I needed a simple, transparent way
to clean up after plugin, when it gets uninstalled. Of course I could tell
guys to do a particular things in uninstall.php, but big part of logic is
encapsulated in parent class, so they will need to look in there and check
what the names and namespaces are and come up with static names, which they
will need to use in uninstall.php. It's not that hard of course, but I
rather automate this somehow. Of course I probably could include my plugin
from uninstall.php and do some cleaning from there, but among other things
it adds complexity and clutters plugin directory too. At least I will have
to explain to everyone - guys you do not need to touch that uninstall.php in
root directory or something. Then if I could have just a regular class
method that does uninstall it just could have been so much more logical - I
think that's what people expect anyway.

Description in Codex is a bit not clear, the one for uninstall.php - is, but
for register_uninstall_hook - is not. It is as if it is not needed at all,
and is there just in case and at some point will become depricated. What it
actually does, becomes clear only after you read actual code in the core.
I'm sure everyone thinks - why it doesn't work like any other hooks? (I know
why it doesn't - no need to explain once again :)

But anyway, I think my solution is pretty clean by now, I still use an API
right? It won't harm anyone if I remove default action and run my own? If I
could get rid of ugly: $_POST['action'] == 'delete-selected'  &&
$_POST['verify-delete'] == 1            &&
in_array(plugin_basename(__FILE__), (array)$_POST['check']) it could become
even cleaner I think.

Thank you guys. I still think that register_uninstall_hook approach needs
some rethinking.




On Sat, May 8, 2010 at 6:41 AM, Jacob Santos <[hidden email]> wrote:

> I think the confusion really just stems from the lack of defined purpose of
> the uninstall process.
>
> The uninstall process is to clean up data that would otherwise be left
> behind when the plugin is deleted. I'm not sure it could be said any more
> clearly than that.
>
>
>   There is always some code inside the plugin right?
>> register_uninstall_hook
>>  looks more convenient, 'cause for example I use variable in option and
>> table
>>  names, which depend on the classname of the plugin, or for example I want
>> to
>>  use variables form within my plugin to check some conditions before
>>  uninstalling. And by the way can I use array($this, 'callback') type of
>>  callback in register_uninstall_hook?
>>
>
> I was confused the first time I read this. I think I understand a bit more.
> I your case, you should probably have a method in your class that runs some
> uninstall processing for each of the classes that has options. However, I
> will suggest that a better idea is to just, well I mean the class names are
> known, so why not just reference the class names from within the uninstall
> process for the options instead of the first suggestion?
>
> As for the second problem, while array($this, 'callback') won't work,
> array('Class_Name', 'callback') will. You will just have to reference
> everything in that code statically or as a function. So technically, you can
> use a class method, but it will have to be static.
>
>
>
>   Hmmm... dont' you think that there is something wrong with this
>> (current?)
>>  solution?
>>
>
>
> Not at all, it is a very simplified solution for something that can be
> extremely difficult to implement otherwise.
>
>
> > "The plugin should not run arbitrary code outside of functions"
>
> If you are wondering whether the statement is saying that you should not
> use classes when using the uninstall process then the answer is no. Let me
> be more clear since it was answered in what might be a double negative. You
> may use either classes or functions in your code and the statement was in no
> way suggesting that you MUST use functions over classes. It was an example
> and if I had to write functions or classes everywhere I would probably kill
> myself with the strain of having to figure that into the correct context of
> each sentence it applies. It is simply best practice to not use a class
> static method for the uninstall hook, since I mean, it would be basically a
> function that is namespaced in a class instead of a real namespace.
>
> I already stated what the arbitrary code means in the last email and won't
> restate what is in there. If you must, please read what Dion wrote again a
> second or third time and it should be more clear what is really meant for
> those two words. I believe Dion was instrumental in the creation of the
> initial patch and additional fixes that came after, so I trust Dion would
> fully know and understand the purpose and discussion that went into the
> patch and additional improvements / fixes. I'm simply trying to confirm and
> attempt to further the understanding of what the uninstall hook and file
> mean and their purpose.
>
> I believe Nacin and Otto explained some of your problems and will suggest
> reading those responses again if further confused. You should be using the
> WordPress API and any attempt to bypass will simply fail. The uninstall
> process checks for the file or the hook existence before it will even
> attempt the uninstall process. If those do not exist, then it simply will
> not run.
>
>
>   The only thing is that I need to know that uninstall is happening and not
>>  just some regular load.
>>
>
>
> The reason the WP_UNINSTALL_PLUGIN constant is only available for the file
> is that it is not needed for the function. The constant is for security so
> that the uninstall process is not run by accident. You could get around it
> by checking ABSPATH as well, but it is better to check for the constant to
> be sure that the plugin is meant to be uninstalled. For the hook, it is
> assumed that the plugin is meant to be uninstalled.
>
>
>   So far I've found only one way to do this - check for: $_POST['action']
>> ==
>>  'delete-selected'&&    $_POST['verify-delete'] == 1&&
>>  in_array(plugin_basename(__FILE__), (array)$_POST['check']).
>>
>
> Please refrain from over thinking the process. You appear to think that you
> have to make it harder than it needs to be. If uninstall.php is included, it
> will be in function / local scope and after checking for the
> WP_UNINSTALL_PLUGIN constant you can assume that it is meant to uninstall
> the plugin. If the hook is called, then you can assume that the plugin is
> meant to be uninstalled. You do not need to do any more checks to be sure
> that the code was meant to be uninstalled.
>
>
> I do not think more focus needs to be paid for this topic, but I believe it
> could be improved by adding additional information based on what was
> discussed here to the codex page and to the inline documentation in
> WordPress to prevent future confusion as this one. I did not think that
> people wouldn't be able to comprehend what was stated in the comment and I
> wanted to be as brief as possible to be sure that people read the comment.
> It appears I was wrong in this instance and I'm sorry that you were
> confused. I do not plan on implementing my suggestion, so I hope it was
> fully explained to you.
>
> Jacob Santos
>
>
>
> On 5/7/2010 2:08 PM, Davit Barbakadze wrote:
>
>> Ok, I understand now what you are doing, but it doesn't answer question -
>> why.
>>
>>
>>
>>> In both cases, the PHP code you are running may be
>>> blissfully unaware of anything else your plugin normally does on
>>> initialization.
>>>
>>>
>> I'd like it to be aware at some extent.
>>
>> Ok, I will tell you what my workaround was. Since register_uninstall_hook
>> does include my plugin main file I can execute some code and obviously do
>> add_action('uninstall_' . plugin_basename(__FILE_), array($this,
>> 'on_unistall'), 0); too, right? If I knew prior to that that it is
>> uninstall
>> procedure going on I could break execution here (having initialized
>> whatever
>> I would need later when action will be called) and wait for an action.
>> Then
>> I could remove default action (my action has higher priority) and do
>> whatever I need. WP_UNINSTALL_PLUGIN could have helped here a lot.
>>
>> Do you find any issue with my solution?
>>
>> The only thing is that I need to know that uninstall is happening and not
>> just some regular load.
>>
>> So far I've found only one way to do this - check for: $_POST['action'] ==
>> 'delete-selected'&&    $_POST['verify-delete'] == 1&&
>> in_array(plugin_basename(__FILE__), (array)$_POST['check']).
>>
>> On Fri, May 7, 2010 at 10:32 PM, Andrew Nacin<[hidden email]>  wrote:
>>
>>
>>
>>> On Fri, May 7, 2010 at 2:09 PM, Davit Barbakadze<[hidden email]>
>>> wrote:
>>>
>>>
>>>
>>>> Unfortunately I can't use uninstall.php for my purpose. Or better to say
>>>>
>>>>
>>> it
>>>
>>>
>>>> would be kinda last resort.
>>>>
>>>> I read the code now and understand what you mean... But, I still find it
>>>> pretty weird. Isn't it? Why would you need to store callback in the
>>>> database? Or why would you need to call it directly? Why not just to do
>>>> do_action('uninstall_' . $file ... and let the user to hook on this and
>>>>
>>>>
>>> do
>>>
>>>
>>>> whatever he/she finds appropriate? This could eliminate neccessity of
>>>>
>>>>
>>> using
>>>
>>>
>>>> function_name callback only, and could have been much more cleaner,
>>>>
>>>>
>>> logical
>>>
>>>
>>>> and convenient in general.
>>>>
>>>> Ok, whatever is the reason behind such solution I don't get, but even if
>>>> there's one, I've found very nice workaround, which could work if only
>>>> WP_UNINSTALL_PLUGIN would have been defined for register_uninstall_hook
>>>> version too. Is there any reason why it's not?
>>>>
>>>>
>>>
>>> When you plugin goes through the uninstall process, it isn't going to be
>>> activated by that point. In most cases, it would have been deactivated
>>> well
>>> before that page load, which means none of its code is included. Thus,
>>> WordPress uses the option stored in the table to determine what file to
>>> include and what code to execute. Hence why it must work this way, with a
>>> function or a static class method. The rest of the plugin simply will not
>>> be
>>> loaded.
>>>
>>> WP_UNINSTALL_PLUGIN is only designed for uninstall.php, that way that
>>> file
>>> is not unintentionally included or hit with an HTTP request and the
>>> uninstall procedure is run. It's no different from dying at the top of
>>> certain files (such as edit-form-advanced.php) if ABSPATH is not defined.
>>>
>>> Hence, you can use uninstall.php, the same way you can use the uninstall
>>> hook, in most cases. In both cases, the PHP code you are running may be
>>> blissfully unaware of anything else your plugin normally does on
>>> initialization.
>>> _______________________________________________
>>> wp-hackers mailing list
>>> [hidden email]
>>> http://lists.automattic.com/mailman/listinfo/wp-hackers
>>>
>>>
>>>
>>
>>
>>
>>
>
> _______________________________________________
> wp-hackers mailing list
> [hidden email]
> http://lists.automattic.com/mailman/listinfo/wp-hackers
>



--
Davit Barbakadze
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

scribu
On Sat, May 8, 2010 at 9:42 AM, Davit Barbakadze <[hidden email]> wrote:

> Ok, what I do is I have my small framework, from which I inherit my all new
> plugins. My friends are using it too, so I needed a simple, transparent way
> to clean up after plugin, when it gets uninstalled. Of course I could tell
> guys to do a particular things in uninstall.php, but big part of logic is
> encapsulated in parent class, so they will need to look in there and check
> what the names and namespaces are and come up with static names, which they
> will need to use in uninstall.php. It's not that hard of course, but I
> rather automate this somehow. Of course I probably could include my plugin
> from uninstall.php and do some cleaning from there, but among other things
> it adds complexity and clutters plugin directory too. At least I will have
> to explain to everyone - guys you do not need to touch that uninstall.php
> in
> root directory or something. Then if I could have just a regular class
> method that does uninstall it just could have been so much more logical - I
> think that's what people expect anyway.
>

That's my use-case exactly.


But anyway, I think my solution is pretty clean by now, I still use an API
> right? It won't harm anyone if I remove default action and run my own? If I
> could get rid of ugly: $_POST['action'] == 'delete-selected'  &&
> $_POST['verify-delete'] == 1            &&
> in_array(plugin_basename(__
> FILE__), (array)$_POST['check']) it could become
> even cleaner I think.
>


Try this:

// Have more than one callback attached to the uninstall hook
function add_uninstall_hook($plugin, $callback) {
        // trigger $is_uninstallable_plugin flag
        register_uninstall_hook($plugin, '__return_false');

        add_action('uninstall_' . plugin_basename($plugin), $callback);
}


You use it exactly like register_activation_hook().


--
http://scribu.net
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

jayarjo
> Try this:
>
> // Have more than one callback attached to the uninstall hook
> function add_uninstall_hook($plugin, $callback) {
>        // trigger $is_uninstallable_plugin flag
>        register_uninstall_hook($plugin, '__return_false');
>
>        add_action('uninstall_' . plugin_basename($plugin), $callback);
> }
>
>
> You use it exactly like register_activation_hook().
>


Looks very nice. But I don't quite understand how this may work... ? It
won't work with 2.9.2, right? Is it something from next version? What is
going to change?


--
Davit Barbakadze
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

The WordPress Web Warlock
In reply to this post by jayarjo
En/na Davit Barbakadze ha escrit:
> (...)
> Ok, what I do is I have my small framework, from which I inherit my all new
> plugins. My friends are using it too, so I needed a simple, transparent way
> to clean up after plugin, when it gets uninstalled. (...)

Why not hook into the uninstall hook?
I mean:

function my_plugin_main_uninstall(){
$args_init = array( 'foo' => 'bar' , 'bar' => 'foo' );
$args_init = apply_filter( 'my_plugin_args_init' , $args_init );
if( $args_init['include'] ) include
do_action( 'my_namespaced_uninstall_init' , $args_init );
if( $args_init['foo'] ) do_action( 'my_plugin_foo_uninstall' );
if( $args_init['bar'] ) do_action( 'my_plugin_bar_uninstall' );
};
register_uninstall_hook( $my_file , 'my_plugin_main_uninstall' );


Maybe I'm missing something, but by what I have understood, all you need
is to declare a gazillion things. By creating your uninstall hooks, you
can add the declaration functions both to plugins_loaded/admin/whatever
AND my_unique_namespaced_uninstall_init.
I've been working with a "framework plugin", too, and this approach of
uninstalling looks easier to me than all the uninstall.php & other
approaches. I've got some dependencies that may be, or may be not, used
by some of the "child plugins". There are options that may need removal,
and maybe not because they simply don't exist — so it's better to skip
that part of the uninstall process, instead of just checking every time
if there is anything that needs removal. Besides, some plugins using
shared optional components may have contradictory uninstall options —
some parsing is needed here. This way I can do anything I need, in the
right order, without having to duplicate selection code in each of the
child plugins (which could even break older child plugins).

_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

scribu
In reply to this post by jayarjo
On Sat, May 8, 2010 at 10:20 AM, Davit Barbakadze <[hidden email]> wrote:

> > Try this:
> >
> > // Have more than one callback attached to the uninstall hook
> > function add_uninstall_hook($plugin, $callback) {
> >        // trigger $is_uninstallable_plugin flag
> >        register_uninstall_hook($plugin, '__return_false');
> >
> >        add_action('uninstall_' . plugin_basename($plugin), $callback);
> > }
> >
> >
> > You use it exactly like register_activation_hook().
> >
>
>
> Looks very nice. But I don't quite understand how this may work... ? It
> won't work with 2.9.2, right? Is it something from next version? What is
> going to change?
>

It will work with 2.9.2 as long as you also add this:

// WP < 3.0
if ( ! function_exists('__return_false') ) :
function __return_false() {
    return false;
}
endif;



--
http://scribu.net
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

jayarjo
Ah, I see now :) Very clean indeed, I think it should go into the core.
Along with WP_UNINSTALL_PLUGIN both for uninstall.php and
register_uninstall_hook. It won't harm to have a solid way to check what's
happening.

On Sat, May 8, 2010 at 5:06 PM, scribu <[hidden email]> wrote:

> On Sat, May 8, 2010 at 10:20 AM, Davit Barbakadze <[hidden email]>
> wrote:
>
> > > Try this:
> > >
> > > // Have more than one callback attached to the uninstall hook
> > > function add_uninstall_hook($plugin, $callback) {
> > >        // trigger $is_uninstallable_plugin flag
> > >        register_uninstall_hook($plugin, '__return_false');
> > >
> > >        add_action('uninstall_' . plugin_basename($plugin), $callback);
> > > }
> > >
> > >
> > > You use it exactly like register_activation_hook().
> > >
> >
> >
> > Looks very nice. But I don't quite understand how this may work... ? It
> > won't work with 2.9.2, right? Is it something from next version? What is
> > going to change?
> >
>
> It will work with 2.9.2 as long as you also add this:
>
> // WP < 3.0
> if ( ! function_exists('__return_false') ) :
> function __return_false() {
>    return false;
> }
> endif;
>
>
>
> --
> http://scribu.net
> _______________________________________________
> wp-hackers mailing list
> [hidden email]
> http://lists.automattic.com/mailman/listinfo/wp-hackers
>



--
Davit Barbakadze
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: register_uninstall_hook VS uninstall.php

Andrew Nacin-2
>
> $_POST['action'] == 'delete-selected'  && $_POST['verify-delete'] == 1 && in_array(plugin_basename(__FILE__),
> (array)$_POST['check'])


That is exactly what I meant by plugins trying to avoid the existing API end
up breaking. When that stops working in a future version, don't say I didn't
tell you so:

 This is honestly why plugins break on new versions of WP -- it's often not
> that they do something that the API doesn't provide for, it's that they do
> something the API does provide for, but don't use the API, and that's what
> breaks.
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
12
Loading...