[wp-hackers] register_uninstall_hook VS uninstall.php

Jacob Santos wordpress at santosj.name
Sat May 8 02:41:22 UTC 2010

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 

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<wp at andrewnacin.com>  wrote:
>> On Fri, May 7, 2010 at 2:09 PM, Davit Barbakadze<jayarjo at gmail.com>
>> 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
>> wp-hackers at lists.automattic.com
>> http://lists.automattic.com/mailman/listinfo/wp-hackers

More information about the wp-hackers mailing list