如何以编程方式和自动下载、安装、激活和替换 WordPress 插件

已发表: 2018-09-18

让用户做任何事情都很难。 无论是填写表格还是仅仅点击几下——都有一种内在的阻力。 即使该操作是为了用户的利益,例如更改弱密码,他们也不会这样做。 这同样适用于让用户安装所需的插件,或者更糟糕的是,用新插件替换活动插件。 这是不可能的边界任务。

值得庆幸的是,在一些代码和用户同意的情况下,我们可以下载、安装、激活、停用甚至删除 WordPress 插件。 如果以负责任的方式部署此自动化过程,可以显着改善用户体验并提高 WordPress 管理员中必要用户操作的转化率。

让用户做任何事情都很难。 那么为什么不自动下载、安装和激活#WordPress 插件呢? 它只需要几行代码。

点击推文

为什么要通过代码下载、安装和激活插件?

有多种情况,但抛开理论不谈,让我们看看 WP Reset 手头的情况。 我已经写了一篇关于将 reset-wp 重新命名为 WP Reset 的帖子。 除此之外,该过程还包括让已经使用 reset-wp 的人将其从他们的站点中删除,然后安装 WP Reset。 为什么有人会因为我们问而这样做? 即使他们想这样做,他们也会不愿意,因为这远非两次点击。 但是,如果我们解释所有内容并将其归结为一个按钮“是的,继续,将 reset-wp 替换为 Reset WP”,那么事情看起来并没有那么糟糕。

未经他人许可,请勿乱用他人的网站! 时期。 即使它是“一件小事”也不行。 这不酷。 这不是你的网站。 在用户更新插件或添加新功能时通知用户任何更改。

由于 wp.org 规则阻止我们跟踪用户的行为(未经他们的同意,我们不想打扰他们询问),不幸的是,我没有任何数字可以分享。 但我可以告诉你的是,我们没有收到来自 reset-wp 用户的投诉,他们完成了更换过程,或者只是在插件中看到了通知。 我们已经运行该流程超过七周。

这样做可以吗? 用户会介意吗?

用户肯定会介意你在他们背后做的任何事情! 不要那样做! 未经用户许可,不要做任何事情。 特别是如果插件托管在 wp.org 上,因为这违反了规则。 如果您这样做,管理员将立即从存储库中删除您的插件。

但是,如果你请求许可——“我们可以用插件 B 替换插件 A 吗? 请确认。” 那么这样做就OK了。 停用和删除一个插件以及下载和激活另一个插件的过程需要多次点击。 因此,如果您设法使该过程自动化,并将其减少到一键式用户会很高兴。

为主题激活所需插件的类似过程已经使用多年,用户对此表示满意。 他们没有按照多个链接来安装插件,而是确认他们对这个过程没有问题,并且一键安装了几个插件。

像往常一样,只需要很少的代码

在伪代码中,这是我们想要做的一般想法:

// pseudo code only!
// DO NOT copy & paste

var $old_plugin;
var $new_plugin;

if ( is_plugin_installed( $new_plugin ) ) {
  // new plugin is already installed
  // make sure we have the last version
  upgrade_plugin( $new_plugin );
} else {
  install_plugin( $new_plugin );
}

if ( !is_plugin_active( $new_plugin ) ) {
  // new plugin is not active - activate it
  activate_plugin( $new_plugin );
}

// deactivate old plugin
deactivate_plugin( $old_plugin );

// if needed delete old plugin
delete_plugin( $old_plugin );

// pseudo code only!
// DO NOT copy & paste

这非常简单明了。 只要用户设置了正确的文件权限,一切都会顺利进行。 整个更换不会超过一两秒即可完成。

我们需要几个函数

值得庆幸的是,WordPress 具有我们需要完成或半完成的大部分功能,因此只需将它们放在一起即可。

要理解的一个关键概念是 WordPress 如何识别插件,它如何知道哪个插件是哪个插件。 它是通过插件 slug 实现的——插件文件夹名称和主 PHP 文件的组合。 例如:hello-dolly/hello-dolly.php。 主 PHP 文件是带有插件标头的文件。 要获得 slug 运行plugin_basename( __FILE__ ) 。 每当您必须检查插件是否处于活动状态或想要对其进行处理时,您都需要使用插件 slug。 这个 slug 与 wp.org 的 slug 相似但不同。 在存储库上,slug 只是文件夹名称,没有文件名。 所以,对于 Hello Dolly,它是“hello-dolly”。 我们目前不需要,但需要澄清。 要更深入地了解这个有点令人困惑的主题,请查看 Stack Exchange 上的这个线程。

WordPress 通过它们的 slug 识别插件,即 hello-dolly/hello-dolly.php。 要获取插件,请在插件的主文件中运行plugin_basename( __FILE__ )

is_plugin_active( $plugin_slug )是内置的,所以我们无事可做。 Codex 页面没有透露太多额外内容,它是一个简单的功能。

is_plugin_installed( $plugin_slug )不是内置的,但只需几行代码即可。

function is_plugin_installed( $slug ) {
  if ( ! function_exists( 'get_plugins' ) ) {
    require_once ABSPATH . 'wp-admin/includes/plugin.php';
  }
  $all_plugins = get_plugins();
  
  if ( !empty( $all_plugins[$slug] ) ) {
    return true;
  } else {
    return false;
  }
}

这些都是我们需要的条件测试功能。 现在对于那些做某事的人。 activate_plugin( )是内置的,有四个参数,因此请查看 Codex 页面。

deactivate_plugins( $plugin_slug )也可以开箱即用,但请务必注意函数名称中的“s”(复数)。 它也有一些参数,所以请阅读 Codex 页面。

install_plugin( $plugin_zip )作为Plugin_Upgrader类的一部分提供。 不需要任何额外的代码,只需要一个新的类实例。 upgrade_plugin( $plugin_slug )

function install_plugin( $plugin_zip ) {
  include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
  wp_cache_flush();

  $upgrader = new Plugin_Upgrader();
  $installed = $upgrader->install( $plugin_zip );

  return $installed;
}

function upgrade_plugin( $plugin_slug ) {
  include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
  wp_cache_flush();

  $upgrader = new Plugin_Upgrader();
  $upgraded = $upgrader->upgrade( $plugin_slug );

  return $upgraded;
}

wp_cache_flush()可能不需要,但我添加它只是为了安全起见。 除了运行时间延长 10 毫秒之外,它不会造成任何伤害。

把它们放在一起

如果您不是出于好奇而阅读本文,而是出于真正需要在插件中实现代码,我强烈建议您安装 reset-wp 插件。 阅读代码很好,但没有什么能比得上在野外测试。

我的偏好是将 admin_action 用于几乎不需要完整管理 GUI 的所有内容。 因此,将其添加到添加其他操作和过滤器的函数中: add_action( 'admin_action_replace_plugin', 'replace_plugin' ); . 当用户打开 admin.php?action=replace_plugin 我们的代码将运行。 请不要对该 URL 进行硬编码。 使用类似: $url = add_query_arg(array('action' => 'replace_plugin'), admin_url('admin.php')); . 它充分说明了您的代码质量。

这是您可以复制/粘贴的代码。 显然,用您的值修改顶部的三个变量。

function replace_plugin() {
  // modify these variables with your new/old plugin values
  $plugin_slug = 'wp-reset/wp-reset.php';
  $plugin_zip = 'https://downloads.wordpress.org/plugin/wp-reset.latest-stable.zip';
  $old_plugin_slug = 'reset-wp/reset-wp.php';
  
  echo 'If things are not done in a minute <a href="plugins.php">click here to return to Plugins page</a><br><br>';
  echo 'Starting ...<br><br>';
  
  echo 'Check if new plugin is already installed - ';
  if ( is_plugin_installed( $plugin_slug ) ) {
    echo 'it\'s installed! Making sure it\'s the latest version.';
    upgrade_plugin( $plugin_slug );
    $installed = true;
  } else {
    echo 'it\'s not installed. Installing.';
    $installed = install_plugin( $plugin_zip );
  }
  
  if ( !is_wp_error( $installed ) && $installed ) {
    echo 'Activating new plugin.';
    $activate = activate_plugin( $plugin_slug );
    
    if ( is_null($activate) ) {
      echo '<br>Deactivating old plugin.<br>';
      deactivate_plugins( array( $old_plugin_slug ) );
      
      echo '<br>Done! Everything went smooth.';
    }
  } else {
    echo 'Could not install the new plugin.';
  }
}
  
function is_plugin_installed( $slug ) {
  if ( ! function_exists( 'get_plugins' ) ) {
    require_once ABSPATH . 'wp-admin/includes/plugin.php';
  }
  $all_plugins = get_plugins();
  
  if ( !empty( $all_plugins[$slug] ) ) {
    return true;
  } else {
    return false;
  }
}

function install_plugin( $plugin_zip ) {
  include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
  wp_cache_flush();
  
  $upgrader = new Plugin_Upgrader();
  $installed = $upgrader->install( $plugin_zip );

  return $installed;
}

function upgrade_plugin( $plugin_slug ) {
  include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
  wp_cache_flush();
  
  $upgrader = new Plugin_Upgrader();
  $upgraded = $upgrader->upgrade( $plugin_slug );

  return $upgraded;
}

该代码使用了我们已经讨论过的所有内容。 GUI 和消息是非常基本的,所以添加一些 CSS 或在灯箱中加载 URL,就像我们在 reset-wp 中所做的那样。

为用户自动执行无聊的平凡任务始终是#UX 的一大优势。 了解如何通过单击轻松下载、安装和激活多个 #WordPress 插件。

点击推文

一键总比十键好

让用户点击一次而不是十次总是一件好事! 这是良好 UX(用户体验)的标志。 因此,如果您的插件或主题需要其他插件,我建议您为所有依赖项实施一键式安装过程。 在插件使用的早期阶段,您无疑会从人们那里获得更少的支持票。

至于用另一个插件替换一个插件 - 尽量远离这些情况。 有时这是不可避免的,但问题是您永远不会让所有用户切换到新插件,这意味着您要么必须支持两个插件,要么放弃并让继续使用旧插件的部分用户群失望。 我们面临与 reset-wp 相同的决定,并且不喜欢这两种解决方案中的任何一种