从个人API更新插件


9

目前,我正在开发Wordpress插件,而我不想在Wordpress插件存储库中使用。但是,我仍然希望能够从自己的API存储库向我的客户推送更新。

我已经阅读了很多有关此内容的内容,其中似乎有一件事是pre_set_site_transient_update_plugins过滤器,但是我找不到太多有关此的信息。我已经尝试了本教程(http://konstruktors.com/blog/wordpress/2538-automatic-updates-for-plugins-and-themes-hosted-outside-wordpress-extend/),但是该教程无法正常工作。从评论中可以看出,其他人实际上可以使用几乎是最新版本的WP来工作(最新的响应时间为4月22日)。

我尝试从站点安装插件并将API文件夹放在第二个域中,但是当有可用更新时,我通常会收到更新通知,但根本没有显示。

我不确定是否确实可以让自定义插件从其他存储库运行自动更新,所以我想听听这里是否有人对此有任何经验?教程中的解决方案似乎是一个简单的解决方案-我想知道是否有可能以更高级的方式来实现?

从我自己的存储库中获取此自动更新的任何帮助将不胜感激!

(PS:我正在运行WP版本3.1.3)


我可能参加聚会的时间很晚,但是您可以找到我专门为此目的构建的插件:WP插件更新服务器
froger.me,

Answers:



2

是的,这是可能的。专业WordPress插件开发中有一整章专门讨论这一点。如果还没有,请选择副本。肯定会有所帮助。


我实际上在网上找到了该版本的PDF版本,但是这似乎也不适合我。
西蒙

如果您做对了,它确实可以工作,我已经完成了,请查看HTTP API,codex.wordpress.org / HTTP_API
Wyck

我又重新开始了。到目前为止add_filter("pre_set_site_transient_update_plugins","dne_altapi_check"); ,我所使用的是使用dne_altapi_check函数进行的插件更新检查。该函数包含dne_altapi_check- print_r("hi");但是,当我按更新下的“再次检查”按钮时,它根本不会打印任何内容。挂在更新检查器上时做错了什么?
西蒙(Simon)

我记得有人为插件更新人员编写了课程,但可以找到该帖子的链接:/
Mamaduka '10


1

http://wp-updates.com/上也提供一项整洁的服务-您可以免费获得一个主题或插件。仅供参考-这不是我的网站,但我已经尝试了一段时间,它看起来还不错。


似乎是一项不错的服务,但我没有在网络控制面板或通讯中注意到(几乎免费计划)HTTPS:此外,在进行更新检查时,我没有发现任何类型的所有权检查(在我看来,这很简单) POST请求),我知道东西可以被窃取,知道插件名称并做出一些猜测。如果它在安全性方面似乎更专业,我会喜欢使用它。
realnice 2015年

1

对于单站点安装(我没有在多站点上进行过测试),您只需从外部服务(例如github或gitlab)更新两个钩子。在下面的代码中,我使用gitlab,因为这是我现在用来托管代码的方式。我可能应该将gitlab部分抽象出来...

您需要使用的第一个钩子是pre_set_site_transient_update_themes。这是WordPress用于设置site_transient以显示是否有可用更新的筛选器。使用此挂钩连接到您的远程版本,并查看是否有可用的更新。如果存在,请修改瞬态,以便WordPress知道有更新,并可以向用户显示通知。

您需要使用的另一个钩子是upgrader_source_selection。无论如何,对于gitlab来说,都需要此过滤器,因为下载的文件夹的名称与主题名称不同,因此我们使用此钩子将其重命名为正确的名称。如果您在远程存储库中提供了具有正确名称的zip,那么您甚至不需要此钩子。

auto_update_theme如果要自动更新主题,则可以使用第三个(可选)挂钩。在下面的示例中,我使用此挂钩仅自动更新此特定主题。

此代码仅在WordPress 4.9.x上进行了测试。它要求PHP> 7.0。

functions.php

//* Load the updater.
require PATH_TO . 'updater.php';
$updater = new updater();
\add_action( 'init', [ $updater, 'init' ] );

updater.php

/**
 * @package StackExchange\WordPress
 */
declare( strict_types = 1 );
namespace StackExchange\WordPress;

/**
 * Class for updating the theme.
 */
class updater {

  /**
   * @var Theme slug.
   */
  protected $theme = 'theme';

  /**
   * @var Theme repository name.
   */
  protected $repository = 'project/theme';

  /**
   * @var Repository domain.
   */
  protected $domain = 'https://gitlab.com/';

  /**
   * @var CSS endpoint for repository.
   */
  protected $css_endpoint = '/raw/master/style.css';

  /**
   * @var ZIP endpoint for repository.
   */
  protected $zip_endpoint = '/repository/archive.zip';

  /**
   * @var Remote CSS URI.
   */
  protected $remote_css_uri;

  /**
   * @var Remote ZIP URI.
   */
  protected $remote_zip_uri;

  /**
   * @var Remote version.
   */
  protected $remote_version;

  /**
   * @var Local version.
   */
  protected $local_version;

  /**
   * Method called from the init hook to initiate the updater
   */
  public function init() {
    \add_filter( 'auto_update_theme', [ $this, 'auto_update_theme' ], 20, 2 );
    \add_filter( 'upgrader_source_selection', [ $this, 'upgrader_source_selection' ], 10, 4 );
    \add_filter( 'pre_set_site_transient_update_themes', [ $this, 'pre_set_site_transient_update_themes' ] );
  }

  /**
   * Method called from the auto_update_theme hook.
   * Only auto update this theme.
   * This hook and method are only needed if you want to auto update the theme.
   *
   * @return bool Whether to update the theme.
   */
  public function auto_update_theme( bool $update, \stdClass $item ) : bool {
    return $this->theme === $item->theme;
  }

  /**
   * Rename the unzipped folder to be the same as the existing folder
   *
   * @param string       $source        File source location
   * @param string       $remote_source Remote file source location
   * @param \WP_Upgrader $upgrader      \WP_Upgrader instance
   * @param array        $hook_extra    Extra arguments passed to hooked filters
   *
   * @return string | \WP_Error The updated source location or a \WP_Error object on failure
   */
  public function upgrader_source_selection( string $source, string $remote_source, \WP_Upgrader $upgrader, array $hook_extra ) {
    global $wp_filesystem;

    $update = [ 'update-selected', 'update-selected-themes', 'upgrade-theme' ];

    if( ! isset( $_GET[ 'action' ] ) || ! in_array( $_GET[ 'action' ], $update, true ) ) {
      return $source;
    }

    if( ! isset( $source, $remote_source ) ) {
      return $source;
    }

    if( false === stristr( basename( $source ), $this->theme ) ) {
      return $source;
    }

    $basename = basename( $source );
    $upgrader->skin->feedback( esc_html_e( 'Renaming theme directory.', 'bootstrap' ) );
    $corrected_source = str_replace( $basename, $this->theme, $source );

    if( $wp_filesystem->move( $source, $corrected_source, true ) ) {
      $upgrader->skin->feedback( esc_html_e( 'Rename successful.', 'bootstrap' ) );
      return $corrected_source;
    }

    return new \WP_Error();
  }

  /**
   * Add respoinse to update transient if theme has an update.
   *
   * @param $transient
   *
   * @return
   */
  public function pre_set_site_transient_update_themes( $transient ) {
    require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
    $this->local_version = ( \wp_get_theme( $this->theme ) )->get( 'Version' );

    if( $this->hasUpdate() ) {
      $response = [
        'theme'       => $this->theme,
        'new_version' => $this->remote_version,
        'url'         => $this->construct_repository_uri(),
        'package'     => $this->construct_remote_zip_uri(),
        'branch'      => 'master',
      ];
      $transient->response[ $this->theme ] = $response;
    }

    return $transient;
  }

  /**
   * Construct and return the URI to the remote stylesheet
   *
   * @return string The remote stylesheet URI
   */
  protected function construct_remote_stylesheet_uri() : string {
    return $this->remote_css_uri = $this->domain . $this->repository . $this->css_endpoint;
  }

  /**
   * Construct and return the URI to the remote ZIP file
   *
   * @return string The remote ZIP URI
   */
  protected function construct_remote_zip_uri() : string {
    return $this->remote_zip_uri = $this->domain . $this->repository . $this->zip_endpoint;
  }

  /**
   * Construct and return the URI to remote repository
   *
   * @access protected
   * @since  1.0
   *
   * @return string The remote repository URI
   */
  protected function construct_repository_uri() : string {
    return $this->repository_uri = $this->domain . \trailingslashit( $this->repository );
  }

  /**
   * Get and return the remote version
   *
   * @return string The remote version
   */
  protected function get_remote_version() : string {
    $this->remote_stylesheet_uri = $this->construct_remote_stylesheet_uri();
    $response = $this->remote_get( $this->remote_stylesheet_uri );
    $response = str_replace( "\r", "\n", \wp_remote_retrieve_body( $response ) );
    $headers = [ 'Version' => 'Version' ];

    foreach( $headers as $field => $regex ) {
      if( preg_match( '/^[ \t\/*#@]*' . preg_quote( $regex, '/' ) . ':(.*)$/mi', $response, $match ) && $match[1] ) {
        $headers[ $field ] = _cleanup_header_comment( $match[1] );
      }
      else {
        $headers[ $field ] = '';
      }
    }

    return $this->remote_version = ( '' === $headers[ 'Version' ] ) ? '' : $headers[ 'Version' ];
  }

  /**
   * Return whether the theme has an update
   *
   * @return bool Whether the theme has an update
   */
  protected function hasUpdate() : bool {
    if( ! $this->remote_version ) $this->remote_version = $this->get_remote_version();
    return version_compare( $this->remote_version, $this->local_version, '>' );
  }

  /**
   * Wrapper for \wp_remote_get()
   *
   * @param string $url  The URL to get
   * @param array  $args Array or arguments to pass through to \wp_remote_get()
   *
   * @return array|WP_Error Return the request or an error object
   */
  protected function remote_get( string $url, array $args = [] ) {
    return \wp_remote_get( $url, $args );
  }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.