【问题标题】:Is there a way to implement a popup when an user uninstalls your wordpress plugin?当用户卸载您的 wordpress 插件时,有没有办法实现弹出窗口?
【发布时间】:2018-08-29 08:10:23
【问题描述】:

我对 wordpress 插件开发相对较新,并且我已经阅读了 wordpress 代码,但在卸载功能的最佳实践和简单示例之外,当用户实际卸载时,我对插件可以做的事情并没有太多了解它。

我希望实现的是,当用户卸载我的插件时,会出现一个弹出窗口,询问他们是否只想删除插件文件或插件文件以及插件上传到他们网站的所有内容。对于更多上下文,我的插件的主要功能是将存储在单独服务器上的数据作为帖子迁移到用户的 wordpress 实例中,如果用户选择该选项,我希望删除这些帖子。

以下是我当前的卸载设置,当我在 wordpress 中单击卸载时,wordpress 会卸载我的插件(从其目录中删除插件文件夹和文件),但在此过程中未显示弹出窗口。我最初认为这是一个样式问题,但弹出文件中的 HTML 没有被加载。我还检查了文件路径变量,它是正确的路径。所以我不确定是什么阻止了弹出窗口的显示并允许用户选择是否应将内容与插件一起删除。

非常感谢您对此事的任何帮助或见解!

卸载.php

<?php
//checks to make sure Wordpress is the one requesting the uninstall
if (!defined('WP_UNINSTALL_PLUGIN')) {
    die;
}
$my_plugin_file_path = trailingslashit(plugin_dir_path(__FILE__));

include $my_plugin_file_path . 'templates/my-plugin-uninstall-popup.php';

my-plugin-uninstall-popup.php

<!-- styling for popup -->
<!-- end of styling for popup -->
<div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
            <h2 class="modal-title" id="myModalLabel">Uninstall popup</h2>
        </div>
        <div class="modal-body">
            <form action="<?php echo esc_url( $my_plugin_file_path . 'my-plugin-uninstall-executor.php' ); ?>" method="post">
                <label>Do you want to remove the content that this plugin has uploaded?</label>
                <input id="delete-content-yes" name="delete-content" value="YES" type="radio" />Yes
                <input id="delete-content-no" name="delete-content" value="NO" type="radio" />No
                <input type="submit" name="submit" value="Submit" />
            </form>
        </div>
    </div>
</div>

my-plugin-uninstall-executor.php

<?php
if (isset($_POST['delete-content']) && $_POST['delete-content'] === 'YES') 
    //delete content from user's wordpress db

【问题讨论】:

    标签: php html wordpress


    【解决方案1】:

    不幸的是,至少据我所知,没有可用于显示自定义卸载屏幕的官方挂钩。

    在旧版本的 WordPress 中曾经有一个卸载确认屏幕 - 尽管我很确定也没有办法进入它 - 但现在 WordPress 只是显示一个 JS 确认框(“你确定吗?您想在运行uninstall.php -if found- 并删除其文件之前删除 [Plugin Name] 及其数据?”)。

    我看到其他插件开发人员在这种情况下所做的是在插件的设置/配置页面中包含一个自定义卸载屏幕,它允许他们执行您在问题中描述的几乎所有操作。这不是一个理想的解决方案,因为如果某些用户不知道您的自定义卸载屏幕,他们可能会以“传统”方式卸载插件,因此您将无法显示确认屏幕/弹出窗口,但这是您可以做的最好的这次。

    如果您想更进一步this answer tells you how to uninstall a plugin programatically。它现在已经很老了(2011 年),但如果它仍然有效,那么也许你可以在运行自定义操作后删除自己的插件。

    【讨论】:

    • ...或者通过设置屏幕用户可以提前选择“卸载插件时我们是否也应该删除所有迁移的数据?”
    • 是的,这是个好主意。作为初始插件设置的一部分,也许会向用户询问它? (如果需要,可以选择稍后更改)。
    【解决方案2】:
    do_action( 'pre_uninstall_plugin', function( $plugin ) {
        if ( $plugin === 'path to your main plugin file from plugins directory' ) {
            wp_redirect( 'url of your custom uninstall script' );
            exit();
        }
    } );
    

    这将中止内置的 wordPress 卸载代码,您的自定义卸载脚本可以做任何您想做的事情,但当然您需要实现相当多的代码,如果您不太了解 WordPress,这将是困难的,但如果您这样做这你会学到很多关于 WordPress 如何在管理员模式下工作的知识。

    附录

    进一步考虑,我认为这可以很容易地完成。您的自定义脚本应在自定义管理页面中显示您的表单。提交此表单可以将您的设置临时保存在 wp_options 表中,然后重定向到原始删除 URL。如果瞬态存在,则在操作“pre_uninstall_plugin”中什么都不做,让 WordPress 调用您的卸载脚本。当然,您的卸载脚本应该从 wp_options 表中的瞬态中读取您的设置并进行相应的处理。重定向回原始删除 URL 将使 WordPress 处理删除插件的通用部分,而您的卸载脚本只需要处理删除插件的插件特定部分。如果此删除是作为批量删除请求的一部分完成的,那么在重定向之前,您应该通过删除以前删除的插件来清理原始删除 URL。

    附录到附录

    事实上还可以做得更好。基本思路是拦截插件删除请求,做一个HTTP重定向到配置删除请求的页面,将删除配置保存到数据库,然后做一个HTTP重定向到原来的删除请求。当插件的卸载脚本被调用时,它会从数据库中读取其删除配置并相应地删除。在这种情况下,应尽早进行拦截,因此操作“admin_init”将是一个不错的选择。提前拦截的好处是,如果插件作为批量请求的一部分被删除,因为拦截是在处理任何内容之前完成的,原始删除 URL 仍然有效,您无需担心以前删除的插件。

    要编写很多代码来实现这个解决方案,我没有时间去做,但我可以给你一个大纲。

    1. 使用 add_submenu_page() 创建一个管理页面来配置插件的卸载。尽管此页面将通过 HTTP 重定向调用,但管理页面是通过挂钩调用的,并且此挂钩需要全局 $menu 中的条目。 add_submenu_page() 在这里仅用于在全局 $menu 中为将显示管理页面的功能创建一个条目。同样创建的菜单项是不需要的,可以隐藏。

    2. 对“admin_init”使用操作拦截插件的删除请求。删除请求如下所示。

      http://aaa.bbb.ccc/wp-admin/plugins.php?action=delete-selected&checked[0]=your-plugin-path.php&plugin_status=all&paged=1&s&_wpnonce=027649d7ff

    您可以使用 $_SERVER 和 $_GET 全局变量来帮助您解析请求 URL。 (全局 $pagenow 在这里可能很有用。)如果请求是对您的插件的删除请求。使用 wp_redirect() 将 HTTP 重定向到您使用 add_submenu_page() 创建的管理页面。您需要将使用 urlencode 编码后的原始 URL 作为查询参数传递到您的管理页面。您的管理页面的 URL 如下所示。

    http://aaa.bbb.ccc/wp-admin/admin.php?page=your-settings-page
    

    您可以从菜单项中获取此 URL,因为它只是 HTML A 元素的 href。

    1. 管理页面的处理程序应显示用于配置插件卸载的设置表单。您可以将原始删除 URL 作为隐藏输入字段传递,因此在提交此表单时它也会发送原始删除 URL。

    2. 提交表单的处理程序应使用 set_transient() 将设置保存为数据库中的瞬态。然后它应该对原始删除 URL 执行 wp_redirect()。

    3. 将再次调用“admin_init”处理程序,并检查是否已设置瞬态,如果已设置,则什么也不做,让 WordPress 处理删除请求。

    4. 您的卸载脚本应从数据库中读取瞬态并进行相应处理,然后从数据库中删除瞬态。

    【讨论】:

    • 感谢您提供如此详细的回复,尽管我在实现它时遇到了一些麻烦。我现在正在显示我的表单的 html,但这是一个管理员通知。 Wordpress 正在剥离表单的功能/样式。我很确定我没有正确实施您的解决方案,所以是否可以看到您在解决方案中描述的示例?提前致谢。
    • 我会尝试管理页面,而不是管理员通知。不幸的是,两者看起来都不像一个理想的弹出窗口。老实说,我并没有真正实现这个解决方案,只是因为它看起来像一个有趣的问题才考虑它。有很多代码要写,我现在还有一些其他的事情需要处理。 AFAIK 可以设置管理员通知的样式,所以我认为你可以让它工作。我认为管理页面更可取,因为它可以真正让用户专注于设置配置,而不是其他。
    【解决方案3】:

    或者,您可以使用 jQuery 拦截对“删除”HTML A 元素的单击并显示您的表单。然后使用 AJAX 请求将您的删除设置临时保存在 wp_options 表中。当 AJAX 请求返回时,您可以转发到原始删除 URL。您的卸载脚本需要读取先前保存在瞬态中的删除设置。

    这种方法涉及的代码较少,但依赖于 HTML 删除元素的特定 HTML 实现(当前是具有类 'delete' 的 HTML A 元素)。由于 WordPress 可以更改此实现,因此这种方法在升级方面并不安全。当然,这不适用于批量删除,但在这种情况下,您可以拦截批量删除操作并显示您的表单并像以前一样继续。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多