对于单站点安装(我没有在多站点上测试),您只需要从外部服务(如github或gitlab)更新两个挂钩。在下面的代码中,我使用gitlab,因为这就是我现在用来托管代码的地方。我可能应该把gitlab的部分提取出来。。。
你需要使用的第一个钩子是pre_set_site_transient_update_themes
. 这是WordPress用来设置site\\u transient以显示是否有可用更新的过滤器。使用此挂钩连接到远程版本,并查看是否有可用的更新。如果有,则修改瞬态,以便WordPress知道有更新,并可以向用户显示通知。
你需要使用的另一个钩子是upgrader_source_selection
. 无论如何,gitlab都需要这个过滤器,因为下载文件夹的名称与主题不同,所以我们使用这个钩子将其重命名为正确的名称。如果远程存储库提供了具有正确名称的zip,那么您甚至不需要这个挂钩。
您可以使用的第三个可选挂钩是auto_update_theme
如果要自动更新主题。在下面的示例中,我使用此挂钩仅自动更新此特定主题。
此代码仅使用WordPress 4.9进行了测试。x、 它需要PHP>7.0。
功能。php
//* Load the updater.
require PATH_TO . \'updater.php\';
$updater = new updater();
\\add_action( \'init\', [ $updater, \'init\' ] );
更新程序。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 );
}
}