[wp-hackers] register_uninstall_hook VS uninstall.php

Davit Barbakadze jayarjo at gmail.com
Sat May 8 06:42:04 UTC 2010


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 <wordpress at santosj.name> 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<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
>>>
>>>
>>>
>>
>>
>>
>>
>
> _______________________________________________
> wp-hackers mailing list
> wp-hackers at lists.automattic.com
> http://lists.automattic.com/mailman/listinfo/wp-hackers
>



-- 
Davit Barbakadze


More information about the wp-hackers mailing list