Refactoring GitHub and BitBucket support.
Move most GitHub and BitBucket stuff to a general "VCS checker" class and put service-specific logic in API classes that follow a common interface.
Rationale: Upon further reflection, there's no need to have different theme & plugin checker implementations for each Git hosting service. The overall update detection algorithm stays the same. Only the API and authentication are different.
Not entirely happy with the code duplication in Vcs_PluginUpdateChecker and Vcs_ThemeUpdateChecker. Traits would be one solution, but can't use that in PHP 5.2. There's probably a "good enough" way to achieve the same thing through composition, but I haven't figured it out yet.
For private GH repositories, use setAuthentication('access_token_here') instead of setAccessToken().
This commit is contained in:
parent
cde890f5d4
commit
cdf2d22243
|
|
@ -23,13 +23,13 @@ if ( !class_exists('Puc_v4_Factory', false) ):
|
|||
*
|
||||
* @see PluginUpdateChecker::__construct()
|
||||
*
|
||||
* @param string $metadataUrl The URL of the metadata file, or a GitHub repository, etc.
|
||||
* @param string $metadataUrl The URL of the metadata file, a GitHub repository, or another supported update source.
|
||||
* @param string $fullPath Full path to the main plugin file or to the theme directory.
|
||||
* @param string $slug Custom slug. Defaults to the name of the main plugin file or the theme directory.
|
||||
* @param int $checkPeriod How often to check for updates (in hours).
|
||||
* @param string $optionName Where to store book-keeping info about update checks.
|
||||
* @param string $muPluginFile The plugin filename relative to the mu-plugins directory.
|
||||
* @return Puc_v4_Plugin_UpdateChecker|Puc_v4_Theme_UpdateChecker
|
||||
* @return Puc_v4_Plugin_UpdateChecker|Puc_v4_Theme_UpdateChecker|Puc_v4_Vcs_BaseChecker
|
||||
*/
|
||||
public static function buildUpdateChecker($metadataUrl, $fullPath, $slug = '', $checkPeriod = 12, $optionName = '', $muPluginFile = '') {
|
||||
$fullPath = wp_normalize_path($fullPath);
|
||||
|
|
@ -68,31 +68,63 @@ if ( !class_exists('Puc_v4_Factory', false) ):
|
|||
}
|
||||
}
|
||||
|
||||
$class = null;
|
||||
$checkerClass = null;
|
||||
$apiClass = null;
|
||||
if ( empty($service) ) {
|
||||
//The default is to get update information from a remote JSON file.
|
||||
$class = $type . '_UpdateChecker';
|
||||
$checkerClass = $type . '_UpdateChecker';
|
||||
} else {
|
||||
$class = $service . '_' . $type . 'UpdateChecker';
|
||||
//You can also use a VCS repository like GitHub.
|
||||
$checkerClass = 'Vcs_' . $type . 'UpdateChecker';
|
||||
$apiClass = $service . 'Api';
|
||||
}
|
||||
|
||||
if ( !isset(self::$classVersions[$class][self::$greatestCompatVersion]) ) {
|
||||
$checkerClass = self::getCompatibleClass($checkerClass);
|
||||
if ( !$checkerClass ) {
|
||||
trigger_error(
|
||||
sprintf(
|
||||
'PUC %s does not support updates for %ss hosted on %s',
|
||||
'PUC %s does not support updates for %ss %s',
|
||||
htmlentities(self::$greatestCompatVersion),
|
||||
strtolower($type),
|
||||
$service
|
||||
$service ? ('hosted on ' . htmlentities($service)) : 'using JSON metadata'
|
||||
),
|
||||
E_USER_ERROR
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
$class = self::$classVersions[$class][self::$greatestCompatVersion];
|
||||
return new $class($metadataUrl, $id, $slug, $checkPeriod, $optionName, $muPluginFile);
|
||||
if ( !isset($apiClass) ) {
|
||||
//Plain old update checker.
|
||||
return new $checkerClass($metadataUrl, $id, $slug, $checkPeriod, $optionName, $muPluginFile);
|
||||
} else {
|
||||
//VCS checker + an API client.
|
||||
$apiClass = self::getCompatibleClass($apiClass);
|
||||
if ( !$apiClass ) {
|
||||
trigger_error(sprintf(
|
||||
'PUC %s does not support %s',
|
||||
htmlentities(self::$greatestCompatVersion),
|
||||
htmlentities($service)
|
||||
), E_USER_ERROR);
|
||||
return null;
|
||||
}
|
||||
|
||||
return new $checkerClass(
|
||||
new $apiClass($metadataUrl),
|
||||
$id,
|
||||
$slug,
|
||||
$checkPeriod,
|
||||
$optionName,
|
||||
$muPluginFile
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the path points to something inside the "plugins" or "mu-plugins" directories.
|
||||
*
|
||||
* @param string $absolutePath
|
||||
* @return bool
|
||||
*/
|
||||
protected static function isPluginFile($absolutePath) {
|
||||
$pluginDir = wp_normalize_path(WP_PLUGIN_DIR);
|
||||
$muPluginDir = wp_normalize_path(WPMU_PLUGIN_DIR);
|
||||
|
|
@ -101,6 +133,20 @@ if ( !class_exists('Puc_v4_Factory', false) ):
|
|||
return (strpos($absolutePath, $pluginDir) === 0) || (strpos($absolutePath, $muPluginDir) === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest version of the specified class that has the same major version number
|
||||
* as this factory class.
|
||||
*
|
||||
* @param string $class Partial class name.
|
||||
* @return string|null Full class name.
|
||||
*/
|
||||
protected static function getCompatibleClass($class) {
|
||||
if ( isset(self::$classVersions[$class][self::$greatestCompatVersion]) ) {
|
||||
return self::$classVersions[$class][self::$greatestCompatVersion];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specific class name for the latest available version of a class.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,224 +0,0 @@
|
|||
<?php
|
||||
|
||||
if ( !class_exists('Puc_v4_GitHub_PluginUpdateChecker', false) ):
|
||||
|
||||
class Puc_v4_GitHub_PluginUpdateChecker extends Puc_v4_Plugin_UpdateChecker {
|
||||
/**
|
||||
* @var string Either a fully qualified repository URL, or just "user/repo-name".
|
||||
*/
|
||||
protected $repositoryUrl;
|
||||
|
||||
/**
|
||||
* @var string The branch to use as the latest version. Defaults to "master".
|
||||
*/
|
||||
protected $branch = 'master';
|
||||
|
||||
/**
|
||||
* @var string GitHub authentication token. Optional.
|
||||
*/
|
||||
protected $accessToken;
|
||||
|
||||
/**
|
||||
* @var Puc_v4_GitHub_Api
|
||||
*/
|
||||
protected $api;
|
||||
|
||||
public function __construct(
|
||||
$repositoryUrl,
|
||||
$pluginFile,
|
||||
$slug = '',
|
||||
$checkPeriod = 12,
|
||||
$optionName = '',
|
||||
$muPluginFile = ''
|
||||
) {
|
||||
$this->repositoryUrl = $repositoryUrl;
|
||||
parent::__construct($repositoryUrl, $pluginFile, $slug, $checkPeriod, $optionName, $muPluginFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the GitHub branch to use for updates. Defaults to 'master'.
|
||||
*
|
||||
* @param string $branch
|
||||
* @return $this
|
||||
*/
|
||||
public function setBranch($branch) {
|
||||
$this->branch = empty($branch) ? 'master' : $branch;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve details about the latest plugin version from GitHub.
|
||||
*
|
||||
* @param array $unusedQueryArgs Unused.
|
||||
* @return Puc_v4_Plugin_Info
|
||||
*/
|
||||
public function requestInfo($unusedQueryArgs = array()) {
|
||||
$api = $this->api = new Puc_v4_GitHub_Api($this->repositoryUrl, $this->accessToken);
|
||||
|
||||
$info = new Puc_v4_Plugin_Info();
|
||||
$info->filename = $this->pluginFile;
|
||||
$info->slug = $this->slug;
|
||||
|
||||
$this->setInfoFromHeader($this->getPluginHeader(), $info);
|
||||
|
||||
//Figure out which reference (tag or branch) we'll use to get the latest version of the plugin.
|
||||
$updateSource = $this->chooseReference();
|
||||
if ( $updateSource ) {
|
||||
$ref = $updateSource->name;
|
||||
$info->version = $updateSource->version;
|
||||
$info->last_updated = $updateSource->updated;
|
||||
$info->download_url = $updateSource->downloadUrl;
|
||||
|
||||
if ( !empty($updateSource->changelog) ) {
|
||||
$info->sections['changelog'] = $updateSource->changelog;
|
||||
}
|
||||
if ( isset($updateSource->downloadCount) ) {
|
||||
$info->downloaded = $updateSource->downloadCount;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( !empty($info->download_url) && !empty($this->accessToken) ) {
|
||||
$info->download_url = add_query_arg('access_token', $this->accessToken, $info->download_url);
|
||||
}
|
||||
|
||||
//Get headers from the main plugin file in this branch/tag. Its "Version" header and other metadata
|
||||
//are what the WordPress install will actually see after upgrading, so they take precedence over releases/tags.
|
||||
$mainPluginFile = basename($this->pluginFile);
|
||||
$remotePlugin = $api->getRemoteFile($mainPluginFile, $ref);
|
||||
if ( !empty($remotePlugin) ) {
|
||||
$remoteHeader = $this->getFileHeader($remotePlugin);
|
||||
$this->setInfoFromHeader($remoteHeader, $info);
|
||||
}
|
||||
|
||||
//Try parsing readme.txt. If it's formatted according to WordPress.org standards, it will contain
|
||||
//a lot of useful information like the required/tested WP version, changelog, and so on.
|
||||
if ( $this->readmeTxtExistsLocally() ) {
|
||||
$this->setInfoFromRemoteReadme($ref, $info);
|
||||
}
|
||||
|
||||
//The changelog might be in a separate file.
|
||||
if ( empty($info->sections['changelog']) ) {
|
||||
$info->sections['changelog'] = $api->getRemoteChangelog($ref, dirname($this->getAbsolutePath()));
|
||||
if ( empty($info->sections['changelog']) ) {
|
||||
$info->sections['changelog'] = __('There is no changelog available.', 'plugin-update-checker');
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty($info->last_updated) ) {
|
||||
//Fetch the latest commit that changed the tag/branch and use it as the "last_updated" date.
|
||||
$info->last_updated = $api->getLatestCommitTime($ref);
|
||||
}
|
||||
|
||||
$info = apply_filters($this->getUniqueName('request_info_result'), $info, null);
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Puc_v4_VcsReference|null
|
||||
*/
|
||||
protected function chooseReference() {
|
||||
$api = $this->api;
|
||||
$updateSource = null;
|
||||
|
||||
if ( $this->branch === 'master' ) {
|
||||
//Use the latest release.
|
||||
$updateSource = $api->getLatestRelease();
|
||||
if ( $updateSource === null ) {
|
||||
//Failing that, use the tag with the highest version number.
|
||||
$updateSource = $api->getLatestTag();
|
||||
}
|
||||
}
|
||||
//Alternatively, just use the branch itself.
|
||||
if ( empty($ref) ) {
|
||||
$updateSource = $api->getBranch($this->branch);
|
||||
}
|
||||
|
||||
return $updateSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the access token that will be used to make authenticated GitHub API requests.
|
||||
*
|
||||
* @param string $accessToken
|
||||
* @return $this
|
||||
*/
|
||||
public function setAccessToken($accessToken) {
|
||||
$this->accessToken = $accessToken;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy plugin metadata from a file header to a PluginInfo object.
|
||||
*
|
||||
* @param array $fileHeader
|
||||
* @param Puc_v4_Plugin_Info $pluginInfo
|
||||
*/
|
||||
protected function setInfoFromHeader($fileHeader, $pluginInfo) {
|
||||
$headerToPropertyMap = array(
|
||||
'Version' => 'version',
|
||||
'Name' => 'name',
|
||||
'PluginURI' => 'homepage',
|
||||
'Author' => 'author',
|
||||
'AuthorName' => 'author',
|
||||
'AuthorURI' => 'author_homepage',
|
||||
|
||||
'Requires WP' => 'requires',
|
||||
'Tested WP' => 'tested',
|
||||
'Requires at least' => 'requires',
|
||||
'Tested up to' => 'tested',
|
||||
);
|
||||
foreach ($headerToPropertyMap as $headerName => $property) {
|
||||
if ( isset($fileHeader[$headerName]) && !empty($fileHeader[$headerName]) ) {
|
||||
$pluginInfo->$property = $fileHeader[$headerName];
|
||||
}
|
||||
}
|
||||
|
||||
if ( !empty($fileHeader['Description']) ) {
|
||||
$pluginInfo->sections['description'] = $fileHeader['Description'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy plugin metadata from the remote readme.txt file.
|
||||
*
|
||||
* @param string $ref GitHub tag or branch where to look for the readme.
|
||||
* @param Puc_v4_Plugin_Info $pluginInfo
|
||||
*/
|
||||
protected function setInfoFromRemoteReadme($ref, $pluginInfo) {
|
||||
$readme = $this->api->getRemoteReadme($ref);
|
||||
if ( empty($readmeTxt) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isset($readme['sections']) ) {
|
||||
$pluginInfo->sections = array_merge($pluginInfo->sections, $readme['sections']);
|
||||
}
|
||||
if ( !empty($readme['tested_up_to']) ) {
|
||||
$pluginInfo->tested = $readme['tested_up_to'];
|
||||
}
|
||||
if ( !empty($readme['requires_at_least']) ) {
|
||||
$pluginInfo->requires = $readme['requires_at_least'];
|
||||
}
|
||||
|
||||
if ( isset($readme['upgrade_notice'], $readme['upgrade_notice'][$pluginInfo->version]) ) {
|
||||
$pluginInfo->upgrade_notice = $readme['upgrade_notice'][$pluginInfo->version];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the currently installed version has a readme.txt file.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function readmeTxtExistsLocally() {
|
||||
$pluginDirectory = dirname($this->pluginAbsolutePath);
|
||||
if ( empty($this->pluginAbsolutePath) || !is_dir($pluginDirectory) || ($pluginDirectory === '.') ) {
|
||||
return false;
|
||||
}
|
||||
return is_file($pluginDirectory . '/readme.txt');
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
<?php
|
||||
if ( !class_exists('Puc_v4_GitHub_ThemeUpdateChecker', false) ):
|
||||
|
||||
class Puc_v4_GitHub_ThemeUpdateChecker extends Puc_v4_Theme_UpdateChecker {
|
||||
protected $repositoryUrl;
|
||||
protected $branch = 'master';
|
||||
protected $accessToken;
|
||||
|
||||
public function __construct($repositoryUrl, $stylesheet = null, $customSlug = null, $checkPeriod = 12, $optionName = '') {
|
||||
$this->repositoryUrl = $repositoryUrl;
|
||||
parent::__construct($repositoryUrl, $stylesheet, $customSlug, $checkPeriod, $optionName);
|
||||
}
|
||||
|
||||
public function requestUpdate() {
|
||||
$api = new Puc_v4_GitHub_Api($this->repositoryUrl, $this->accessToken);
|
||||
|
||||
$update = new Puc_v4_Theme_Update();
|
||||
$update->slug = $this->slug;
|
||||
|
||||
//Figure out which reference (tag or branch) we'll use to get the latest version of the theme.
|
||||
$ref = $this->branch;
|
||||
if ( $this->branch === 'master' ) {
|
||||
//Use the latest release.
|
||||
$release = $api->getLatestRelease();
|
||||
if ( $release !== null ) {
|
||||
$ref = $release->name;
|
||||
$update->version = ltrim($release->name, 'v'); //Remove the "v" prefix from "v1.2.3".
|
||||
$update->download_url = $release->downloadUrl;
|
||||
} else {
|
||||
//Failing that, use the tag with the highest version number.
|
||||
$tag = $api->getLatestTag();
|
||||
if ( $tag !== null ) {
|
||||
$ref = $tag->name;
|
||||
$update->version = $tag->version;
|
||||
$update->download_url = $tag->downloadUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty($update->download_url) ) {
|
||||
$update->download_url = $api->buildArchiveDownloadUrl($ref);
|
||||
} else if ( !empty($this->accessToken) ) {
|
||||
$update->download_url = add_query_arg('access_token', $this->accessToken, $update->download_url);
|
||||
}
|
||||
|
||||
//Get headers from the main stylesheet in this branch/tag. Its "Version" header and other metadata
|
||||
//are what the WordPress install will actually see after upgrading, so they take precedence over releases/tags.
|
||||
$remoteStylesheet = $api->getRemoteFile('style.css', $ref);
|
||||
if ( !empty($remoteStylesheet) ) {
|
||||
$remoteHeader = $this->getFileHeader($remoteStylesheet);
|
||||
if ( !empty($remoteHeader['Version']) ) {
|
||||
$update->version = $remoteHeader['Version'];
|
||||
}
|
||||
if ( !empty($remoteHeader['ThemeURI']) ) {
|
||||
$update->details_url = $remoteHeader['ThemeURI'];
|
||||
}
|
||||
}
|
||||
|
||||
//The details URL defaults to the Theme URI header or the repository URL.
|
||||
if ( empty($update->details_url) ) {
|
||||
$update->details_url = $this->theme->get('ThemeURI');
|
||||
}
|
||||
if ( empty($update->details_url) ) {
|
||||
$update->details_url = $this->repositoryUrl;
|
||||
}
|
||||
|
||||
if ( empty($update->version) ) {
|
||||
//It looks like we didn't find a valid update after all.
|
||||
$update = null;
|
||||
}
|
||||
|
||||
$update = $this->filterUpdateResult($update);
|
||||
return $update;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the GitHub branch to use for updates. Defaults to 'master'.
|
||||
*
|
||||
* @param string $branch
|
||||
* @return $this
|
||||
*/
|
||||
public function setBranch($branch) {
|
||||
$this->branch = empty($branch) ? 'master' : $branch;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the access token that will be used to make authenticated GitHub API requests.
|
||||
*
|
||||
* @param string $accessToken
|
||||
* @return $this
|
||||
*/
|
||||
public function setAccessToken($accessToken) {
|
||||
$this->accessToken = $accessToken;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
|
|
@ -1,9 +1,46 @@
|
|||
<?php
|
||||
if ( !class_exists('Puc_v4_VcsApi') ):
|
||||
if ( !class_exists('Puc_v4_Vcs_Api') ):
|
||||
|
||||
abstract class Puc_v4_VcsApi {
|
||||
abstract class Puc_v4_Vcs_Api {
|
||||
protected $tagNameProperty = 'name';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $repositoryUrl = '';
|
||||
|
||||
/**
|
||||
* @var mixed Authentication details for private repositories. Format depends on service.
|
||||
*/
|
||||
protected $credentials = null;
|
||||
|
||||
/**
|
||||
* Puc_v4_Vcs_Api constructor.
|
||||
*
|
||||
* @param string $repositoryUrl
|
||||
* @param array|string|null $credentials
|
||||
*/
|
||||
public function __construct($repositoryUrl, $credentials = null) {
|
||||
$this->repositoryUrl = $repositoryUrl;
|
||||
$this->setAuthentication($credentials);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRepositoryUrl() {
|
||||
return $this->repositoryUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Figure out which reference (i.e tag or branch) contains the latest version.
|
||||
*
|
||||
* @param string $configBranch Start looking in this branch.
|
||||
* @param bool $useStableTag
|
||||
* @return null|Puc_v4_Vcs_Reference
|
||||
*/
|
||||
abstract public function chooseReference($configBranch, $useStableTag = true);
|
||||
|
||||
/**
|
||||
* Get the readme.txt file from the remote repository and parse it
|
||||
* according to the plugin readme standard.
|
||||
|
|
@ -25,7 +62,7 @@ if ( !class_exists('Puc_v4_VcsApi') ):
|
|||
* Get a branch.
|
||||
*
|
||||
* @param string $branchName
|
||||
* @return Puc_v4_VcsReference|null
|
||||
* @return Puc_v4_Vcs_Reference|null
|
||||
*/
|
||||
abstract public function getBranch($branchName);
|
||||
|
||||
|
|
@ -33,7 +70,7 @@ if ( !class_exists('Puc_v4_VcsApi') ):
|
|||
* Get a specific tag.
|
||||
*
|
||||
* @param string $tagName
|
||||
* @return Puc_v4_VcsReference|null
|
||||
* @return Puc_v4_Vcs_Reference|null
|
||||
*/
|
||||
abstract public function getTag($tagName);
|
||||
|
||||
|
|
@ -41,7 +78,7 @@ if ( !class_exists('Puc_v4_VcsApi') ):
|
|||
* Get the tag that looks like the highest version number.
|
||||
* (Implementations should skip pre-release versions if possible.)
|
||||
*
|
||||
* @return Puc_v4_VcsReference|null
|
||||
* @return Puc_v4_Vcs_Reference|null
|
||||
*/
|
||||
abstract public function getLatestTag();
|
||||
|
||||
|
|
@ -64,6 +101,33 @@ if ( !class_exists('Puc_v4_VcsApi') ):
|
|||
return (preg_match('@^(\d{1,5}?)(\.\d{1,10}?){0,4}?($|[abrdp+_\-]|\s)@i', $name) === 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a tag appears to be named like a version number.
|
||||
*
|
||||
* @param stdClass $tag
|
||||
* @return bool
|
||||
*/
|
||||
protected function isVersionTag($tag) {
|
||||
$property = $this->tagNameProperty;
|
||||
return isset($tag->$property) && $this->looksLikeVersion($tag->$property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort a list of tags as if they were version numbers.
|
||||
* Tags that don't look like version number will be removed.
|
||||
*
|
||||
* @param stdClass[] $tags Array of tag objects.
|
||||
* @return stdClass[] Filtered array of tags sorted in descending order.
|
||||
*/
|
||||
protected function sortTagsByVersion($tags) {
|
||||
//Keep only those tags that look like version numbers.
|
||||
$versionTags = array_filter($tags, array($this, 'isVersionTag'));
|
||||
//Sort them in descending order.
|
||||
usort($versionTags, array($this, 'compareTagNames'));
|
||||
|
||||
return $versionTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two tags as if they were version number.
|
||||
*
|
||||
|
|
@ -141,6 +205,23 @@ if ( !class_exists('Puc_v4_VcsApi') ):
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set authentication credentials.
|
||||
*
|
||||
* @param $credentials
|
||||
*/
|
||||
public function setAuthentication($credentials) {
|
||||
$this->credentials = $credentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @return string
|
||||
*/
|
||||
public function signDownloadUrl($url) {
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
if ( !interface_exists('Puc_v4_Vcs_BaseChecker', false) ):
|
||||
|
||||
interface Puc_v4_Vcs_BaseChecker {
|
||||
/**
|
||||
* Set the repository branch to use for updates. Defaults to 'master'.
|
||||
*
|
||||
* @param string $branch
|
||||
* @return $this
|
||||
*/
|
||||
public function setBranch($branch);
|
||||
|
||||
/**
|
||||
* Set authentication credentials.
|
||||
*
|
||||
* @param array|string $credentials
|
||||
* @return $this
|
||||
*/
|
||||
public function setAuthentication($credentials);
|
||||
}
|
||||
|
||||
endif;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
if ( !class_exists('Puc_v4_BitBucket_Api', false) ):
|
||||
if ( !class_exists('Puc_v4_Vcs_BitBucketApi', false) ):
|
||||
|
||||
class Puc_v4_BitBucket_Api extends Puc_v4_VcsApi {
|
||||
class Puc_v4_Vcs_BitBucketApi extends Puc_v4_Vcs_Api {
|
||||
/**
|
||||
* @var Puc_v4_OAuthSignature
|
||||
*/
|
||||
|
|
@ -12,19 +12,12 @@ if ( !class_exists('Puc_v4_BitBucket_Api', false) ):
|
|||
*/
|
||||
private $username;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $repositoryUrl;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
public function __construct($repositoryUrl, $credentials = array()) {
|
||||
$this->repositoryUrl = $repositoryUrl;
|
||||
|
||||
$path = @parse_url($repositoryUrl, PHP_URL_PATH);
|
||||
if ( preg_match('@^/?(?P<username>[^/]+?)/(?P<repository>[^/#?&]+?)/?$@', $path, $matches) ) {
|
||||
$this->username = $matches['username'];
|
||||
|
|
@ -33,12 +26,45 @@ if ( !class_exists('Puc_v4_BitBucket_Api', false) ):
|
|||
throw new InvalidArgumentException('Invalid BitBucket repository URL: "' . $repositoryUrl . '"');
|
||||
}
|
||||
|
||||
if ( !empty($credentials) && !empty($credentials['consumer_key']) ) {
|
||||
$this->oauth = new Puc_v4_OAuthSignature(
|
||||
$credentials['consumer_key'],
|
||||
$credentials['consumer_secret']
|
||||
);
|
||||
parent::__construct($repositoryUrl, $credentials);
|
||||
}
|
||||
|
||||
/**
|
||||
* Figure out which reference (i.e tag or branch) contains the latest version.
|
||||
*
|
||||
* @param string $configBranch Start looking in this branch.
|
||||
* @param bool $useStableTag
|
||||
* @return null|Puc_v4_Vcs_Reference
|
||||
*/
|
||||
public function chooseReference($configBranch, $useStableTag = true) {
|
||||
$updateSource = null;
|
||||
|
||||
//Check if there's a "Stable tag: 1.2.3" header that points to a valid tag.
|
||||
if ( $useStableTag ) {
|
||||
$remoteReadme = $this->getRemoteReadme($configBranch);
|
||||
if ( !empty($remoteReadme['stable_tag']) ) {
|
||||
$tag = $remoteReadme['stable_tag'];
|
||||
|
||||
//You can explicitly opt out of using tags by setting "Stable tag" to
|
||||
//"trunk" or the name of the current branch.
|
||||
if ( ($tag === $configBranch) || ($tag === 'trunk') ) {
|
||||
return $this->getBranch($configBranch);
|
||||
}
|
||||
|
||||
$updateSource = $this->getTag($tag);
|
||||
}
|
||||
}
|
||||
|
||||
//Look for version-like tags.
|
||||
if ( !$updateSource && ($configBranch === 'master') ) {
|
||||
$updateSource = $this->getLatestTag();
|
||||
}
|
||||
//If all else fails, use the specified branch itself.
|
||||
if ( !$updateSource ) {
|
||||
$updateSource = $this->getBranch($configBranch);
|
||||
}
|
||||
|
||||
return $updateSource;
|
||||
}
|
||||
|
||||
public function getBranch($branchName) {
|
||||
|
|
@ -47,7 +73,7 @@ if ( !class_exists('Puc_v4_BitBucket_Api', false) ):
|
|||
return null;
|
||||
}
|
||||
|
||||
return new Puc_v4_VcsReference(array(
|
||||
return new Puc_v4_Vcs_Reference(array(
|
||||
'name' => $branch->name,
|
||||
'updated' => $branch->target->date,
|
||||
'downloadUrl' => $this->getDownloadUrl($branch->name),
|
||||
|
|
@ -58,7 +84,7 @@ if ( !class_exists('Puc_v4_BitBucket_Api', false) ):
|
|||
* Get a specific tag.
|
||||
*
|
||||
* @param string $tagName
|
||||
* @return Puc_v4_VcsReference|null
|
||||
* @return Puc_v4_Vcs_Reference|null
|
||||
*/
|
||||
public function getTag($tagName) {
|
||||
$tag = $this->api('/refs/tags/' . $tagName);
|
||||
|
|
@ -66,7 +92,7 @@ if ( !class_exists('Puc_v4_BitBucket_Api', false) ):
|
|||
return null;
|
||||
}
|
||||
|
||||
return new Puc_v4_VcsReference(array(
|
||||
return new Puc_v4_Vcs_Reference(array(
|
||||
'name' => $tag->name,
|
||||
'version' => ltrim($tag->name, 'v'),
|
||||
'updated' => $tag->target->date,
|
||||
|
|
@ -77,7 +103,7 @@ if ( !class_exists('Puc_v4_BitBucket_Api', false) ):
|
|||
/**
|
||||
* Get the tag that looks like the highest version number.
|
||||
*
|
||||
* @return Puc_v4_VcsReference|null
|
||||
* @return Puc_v4_Vcs_Reference|null
|
||||
*/
|
||||
public function getLatestTag() {
|
||||
$tags = $this->api('/refs/tags');
|
||||
|
|
@ -85,15 +111,13 @@ if ( !class_exists('Puc_v4_BitBucket_Api', false) ):
|
|||
return null;
|
||||
}
|
||||
|
||||
//Keep only those tags that look like version numbers.
|
||||
$versionTags = array_filter($tags->values, array($this, 'isVersionTag'));
|
||||
//Sort them in descending order.
|
||||
usort($versionTags, array($this, 'compareTagNames'));
|
||||
//Filter and sort the list of tags.
|
||||
$versionTags = $this->sortTagsByVersion($tags->values);
|
||||
|
||||
//Return the first result.
|
||||
if ( !empty($versionTags) ) {
|
||||
$tag = $versionTags[0];
|
||||
return new Puc_v4_VcsReference(array(
|
||||
return new Puc_v4_Vcs_Reference(array(
|
||||
'name' => $tag->name,
|
||||
'version' => ltrim($tag->name, 'v'),
|
||||
'updated' => $tag->target->date,
|
||||
|
|
@ -111,10 +135,6 @@ if ( !class_exists('Puc_v4_BitBucket_Api', false) ):
|
|||
return trailingslashit($this->repositoryUrl) . 'get/' . $ref . '.zip';
|
||||
}
|
||||
|
||||
protected function isVersionTag($tag) {
|
||||
return isset($tag->name) && $this->looksLikeVersion($tag->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contents of a file from a specific branch or tag.
|
||||
*
|
||||
|
|
@ -185,6 +205,32 @@ if ( !class_exists('Puc_v4_BitBucket_Api', false) ):
|
|||
'BitBucket API error. HTTP status: ' . $code
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $credentials
|
||||
*/
|
||||
public function setAuthentication($credentials) {
|
||||
parent::setAuthentication($credentials);
|
||||
|
||||
if ( !empty($credentials) && !empty($credentials['consumer_key']) ) {
|
||||
$this->oauth = new Puc_v4_OAuthSignature(
|
||||
$credentials['consumer_key'],
|
||||
$credentials['consumer_secret']
|
||||
);
|
||||
} else {
|
||||
$this->oauth = null;
|
||||
}
|
||||
}
|
||||
|
||||
public function signDownloadUrl($url) {
|
||||
//Add authentication data to download URLs. Since OAuth signatures incorporate
|
||||
//timestamps, we have to do this immediately before inserting the update. Otherwise
|
||||
//authentication could fail due to a stale timestamp.
|
||||
if ( $this->oauth ) {
|
||||
$url = $this->oauth->sign($url);
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
if ( !class_exists('Puc_v4_GitHub_Api', false) ):
|
||||
if ( !class_exists('Puc_v4_Vcs_GitHubApi', false) ):
|
||||
|
||||
class Puc_v4_GitHub_Api extends Puc_v4_VcsApi {
|
||||
class Puc_v4_Vcs_GitHubApi extends Puc_v4_Vcs_Api {
|
||||
/**
|
||||
* @var string GitHub username.
|
||||
*/
|
||||
|
|
@ -23,9 +23,6 @@ if ( !class_exists('Puc_v4_GitHub_Api', false) ):
|
|||
protected $accessToken;
|
||||
|
||||
public function __construct($repositoryUrl, $accessToken = null) {
|
||||
$this->repositoryUrl = $repositoryUrl;
|
||||
$this->accessToken = $accessToken;
|
||||
|
||||
$path = @parse_url($repositoryUrl, PHP_URL_PATH);
|
||||
if ( preg_match('@^/?(?P<username>[^/]+?)/(?P<repository>[^/#?&]+?)/?$@', $path, $matches) ) {
|
||||
$this->userName = $matches['username'];
|
||||
|
|
@ -33,12 +30,14 @@ if ( !class_exists('Puc_v4_GitHub_Api', false) ):
|
|||
} else {
|
||||
throw new InvalidArgumentException('Invalid GitHub repository URL: "' . $repositoryUrl . '"');
|
||||
}
|
||||
|
||||
parent::__construct($repositoryUrl, $accessToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest release from GitHub.
|
||||
*
|
||||
* @return Puc_v4_VcsReference|null
|
||||
* @return Puc_v4_Vcs_Reference|null
|
||||
*/
|
||||
public function getLatestRelease() {
|
||||
$release = $this->api('/repos/:user/:repo/releases/latest');
|
||||
|
|
@ -46,10 +45,10 @@ if ( !class_exists('Puc_v4_GitHub_Api', false) ):
|
|||
return null;
|
||||
}
|
||||
|
||||
$reference = new Puc_v4_VcsReference(array(
|
||||
$reference = new Puc_v4_Vcs_Reference(array(
|
||||
'name' => $release->tag_name,
|
||||
'version' => ltrim($release->tag_name, 'v'), //Remove the "v" prefix from "v1.2.3".
|
||||
'downloadUrl' => $release->zipball_url,
|
||||
'downloadUrl' => $this->signDownloadUrl($release->zipball_url),
|
||||
'updated' => $release->created_at,
|
||||
));
|
||||
|
||||
|
|
@ -67,7 +66,7 @@ if ( !class_exists('Puc_v4_GitHub_Api', false) ):
|
|||
/**
|
||||
* Get the tag that looks like the highest version number.
|
||||
*
|
||||
* @return Puc_v4_VcsReference|null
|
||||
* @return Puc_v4_Vcs_Reference|null
|
||||
*/
|
||||
public function getLatestTag() {
|
||||
$tags = $this->api('/repos/:user/:repo/tags');
|
||||
|
|
@ -76,13 +75,16 @@ if ( !class_exists('Puc_v4_GitHub_Api', false) ):
|
|||
return null;
|
||||
}
|
||||
|
||||
usort($tags, array($this, 'compareTagNames')); //Sort from highest to lowest.
|
||||
$versionTags = $this->sortTagsByVersion($tags);
|
||||
if ( empty($versionTags) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$tag = $tags[0];
|
||||
return new Puc_v4_VcsReference(array(
|
||||
$tag = $versionTags[0];
|
||||
return new Puc_v4_Vcs_Reference(array(
|
||||
'name' => $tag->name,
|
||||
'version' => ltrim($tag->name, 'v'),
|
||||
'downloadUrl' => $tag->zipball_url,
|
||||
'downloadUrl' => $this->signDownloadUrl($tag->zipball_url),
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +92,7 @@ if ( !class_exists('Puc_v4_GitHub_Api', false) ):
|
|||
* Get a branch by name.
|
||||
*
|
||||
* @param string $branchName
|
||||
* @return null|Puc_v4_VcsReference
|
||||
* @return null|Puc_v4_Vcs_Reference
|
||||
*/
|
||||
public function getBranch($branchName) {
|
||||
$branch = $this->api('/repos/:user/:repo/branches/' . $branchName);
|
||||
|
|
@ -98,7 +100,7 @@ if ( !class_exists('Puc_v4_GitHub_Api', false) ):
|
|||
return null;
|
||||
}
|
||||
|
||||
$reference = new Puc_v4_VcsReference(array(
|
||||
$reference = new Puc_v4_Vcs_Reference(array(
|
||||
'name' => $branch->name,
|
||||
'downloadUrl' => $this->buildArchiveDownloadUrl($branch->name),
|
||||
));
|
||||
|
|
@ -218,7 +220,7 @@ if ( !class_exists('Puc_v4_GitHub_Api', false) ):
|
|||
urlencode($ref)
|
||||
);
|
||||
if ( !empty($this->accessToken) ) {
|
||||
$url = add_query_arg('access_token', $this->accessToken, $url);
|
||||
$url = $this->signDownloadUrl($url);
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
|
@ -227,12 +229,43 @@ if ( !class_exists('Puc_v4_GitHub_Api', false) ):
|
|||
* Get a specific tag.
|
||||
*
|
||||
* @param string $tagName
|
||||
* @return Puc_v4_VcsReference|null
|
||||
* @return Puc_v4_Vcs_Reference|null
|
||||
*/
|
||||
public function getTag($tagName) {
|
||||
//The current GitHub update checker doesn't use getTag, so didn't bother to implement it.
|
||||
//The current GitHub update checker doesn't use getTag, so I didn't bother to implement it.
|
||||
throw new LogicException('The ' . __METHOD__ . ' method is not implemented and should not be used.');
|
||||
}
|
||||
|
||||
public function setAuthentication($credentials) {
|
||||
parent::setAuthentication($credentials);
|
||||
$this->accessToken = is_string($credentials) ? $credentials : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Figure out which reference (i.e tag or branch) contains the latest version.
|
||||
*
|
||||
* @param string $configBranch Start looking in this branch.
|
||||
* @param bool $useStableTag Ignored. The GitHub client doesn't use the "Stable tag" header.
|
||||
* @return null|Puc_v4_Vcs_Reference
|
||||
*/
|
||||
public function chooseReference($configBranch, $useStableTag = false) {
|
||||
$updateSource = null;
|
||||
|
||||
if ( $configBranch === 'master' ) {
|
||||
//Use the latest release.
|
||||
$updateSource = $this->getLatestRelease();
|
||||
if ( $updateSource === null ) {
|
||||
//Failing that, use the tag with the highest version number.
|
||||
$updateSource = $this->getLatestTag();
|
||||
}
|
||||
}
|
||||
//Alternatively, just use the branch itself.
|
||||
if ( empty($updateSource) ) {
|
||||
$updateSource = $this->getBranch($configBranch);
|
||||
}
|
||||
|
||||
return $updateSource;
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
|
|
@ -1,25 +1,38 @@
|
|||
<?php
|
||||
if ( !class_exists('Puc_v4_BitBucket_PluginUpdateChecker') ):
|
||||
if ( !class_exists('Puc_v4_Vcs_PluginUpdateChecker') ):
|
||||
|
||||
class Puc_v4_BitBucket_PluginUpdateChecker extends Puc_v4_Plugin_UpdateChecker {
|
||||
class Puc_v4_Vcs_PluginUpdateChecker extends Puc_v4_Plugin_UpdateChecker implements Puc_v4_Vcs_BaseChecker {
|
||||
/**
|
||||
* @var string
|
||||
* @var string The branch where to look for updates. Defaults to "master".
|
||||
*/
|
||||
protected $branch = 'master';
|
||||
|
||||
/**
|
||||
* @var Puc_v4_BitBucket_Api
|
||||
* @var Puc_v4_Vcs_Api Repository API client.
|
||||
*/
|
||||
protected $api;
|
||||
protected $api = null;
|
||||
|
||||
protected $credentials = array();
|
||||
/**
|
||||
* Puc_v4_Vcs_PluginUpdateChecker constructor.
|
||||
*
|
||||
* @param Puc_v4_Vcs_Api $api
|
||||
* @param string $pluginFile
|
||||
* @param string $slug
|
||||
* @param int $checkPeriod
|
||||
* @param string $optionName
|
||||
* @param string $muPluginFile
|
||||
*/
|
||||
public function __construct($api, $pluginFile, $slug = '', $checkPeriod = 12, $optionName = '', $muPluginFile = '') {
|
||||
$this->api = $api;
|
||||
parent::__construct($api->getRepositoryUrl(), $pluginFile, $slug, $checkPeriod, $optionName, $muPluginFile);
|
||||
}
|
||||
|
||||
public function requestInfo($queryArgs = array()) {
|
||||
//We have to make several remote API requests to gather all the necessary info
|
||||
//which can take a while on slow networks.
|
||||
set_time_limit(60);
|
||||
|
||||
$api = $this->api = new Puc_v4_BitBucket_Api($this->metadataUrl, $this->credentials);
|
||||
$api = $this->api;
|
||||
|
||||
$info = new Puc_v4_Plugin_Info();
|
||||
$info->filename = $this->pluginFile;
|
||||
|
|
@ -28,12 +41,19 @@ if ( !class_exists('Puc_v4_BitBucket_PluginUpdateChecker') ):
|
|||
$this->setInfoFromHeader($this->getPluginHeader(), $info);
|
||||
|
||||
//Pick a branch or tag.
|
||||
$updateSource = $this->chooseReference();
|
||||
$updateSource = $api->chooseReference($this->branch);
|
||||
if ( $updateSource ) {
|
||||
$ref = $updateSource->name;
|
||||
$info->version = $updateSource->version;
|
||||
$info->last_updated = $updateSource->updated;
|
||||
$info->download_url = $updateSource->downloadUrl;
|
||||
|
||||
if ( !empty($updateSource->changelog) ) {
|
||||
$info->sections['changelog'] = $updateSource->changelog;
|
||||
}
|
||||
if ( isset($updateSource->downloadCount) ) {
|
||||
$info->downloaded = $updateSource->downloadCount;
|
||||
}
|
||||
} else {
|
||||
//There's probably a network problem or an authentication error.
|
||||
return null;
|
||||
|
|
@ -74,56 +94,6 @@ if ( !class_exists('Puc_v4_BitBucket_PluginUpdateChecker') ):
|
|||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Figure out which reference (tag or branch) we'll use to get the latest version of the plugin.
|
||||
*
|
||||
* @return Puc_v4_VcsReference|null
|
||||
*/
|
||||
protected function chooseReference() {
|
||||
$api = $this->api;
|
||||
$updateSource = null;
|
||||
|
||||
//Check if there's a "Stable tag: v1.2.3" header that points to a valid tag.
|
||||
$remoteReadme = $api->getRemoteReadme($this->branch);
|
||||
if ( !empty($remoteReadme['stable_tag']) ) {
|
||||
$tag = $remoteReadme['stable_tag'];
|
||||
|
||||
//You can explicitly opt out of using tags by setting "Stable tag" to
|
||||
//"trunk" or the name of the current branch.
|
||||
if ( ($tag === $this->branch) || ($tag === 'trunk') ) {
|
||||
return $api->getBranch($this->branch);
|
||||
}
|
||||
|
||||
$updateSource = $api->getTag($tag);
|
||||
}
|
||||
//Look for version-like tags.
|
||||
if ( !$updateSource && ($this->branch === 'master') ) {
|
||||
$updateSource = $api->getLatestTag();
|
||||
}
|
||||
//If all else fails, use the specified branch itself.
|
||||
if ( !$updateSource ) {
|
||||
$updateSource = $api->getBranch($this->branch);
|
||||
}
|
||||
|
||||
return $updateSource;
|
||||
}
|
||||
|
||||
public function setAuthentication($credentials) {
|
||||
$this->credentials = array_merge(
|
||||
array(
|
||||
'consumer_key' => '',
|
||||
'consumer_secret' => '',
|
||||
),
|
||||
$credentials
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setBranch($branchName = 'master') {
|
||||
$this->branch = $branchName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the currently installed version has a readme.txt file.
|
||||
*
|
||||
|
|
@ -195,20 +165,21 @@ if ( !class_exists('Puc_v4_BitBucket_PluginUpdateChecker') ):
|
|||
}
|
||||
}
|
||||
|
||||
public function setBranch($branch) {
|
||||
$this->branch = $branch;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setAuthentication($credentials) {
|
||||
$this->api->setAuthentication($credentials);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUpdate() {
|
||||
$update = parent::getUpdate();
|
||||
|
||||
//Add authentication data to download URLs. Since OAuth signatures incorporate
|
||||
//timestamps, we have to do this immediately before inserting the update. Otherwise
|
||||
//authentication could fail due to a stale timestamp.
|
||||
if ( isset($update, $update->download_url) && !empty($update->download_url) && !empty($this->credentials) ) {
|
||||
if ( !empty($this->credentials['consumer_key']) ) {
|
||||
$oauth = new Puc_v4_OAuthSignature(
|
||||
$this->credentials['consumer_key'],
|
||||
$this->credentials['consumer_secret']
|
||||
);
|
||||
$update->download_url = $oauth->sign($update->download_url);
|
||||
}
|
||||
if ( isset($update) && !empty($update->download_url) ) {
|
||||
$update->download_url = $this->api->signDownloadUrl($update->download_url);
|
||||
}
|
||||
|
||||
return $update;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
if ( !class_exists('Puc_v4_VcsReference', false) ):
|
||||
if ( !class_exists('Puc_v4_Vcs_Reference', false) ):
|
||||
|
||||
/**
|
||||
* This class represents a VCS branch or tag. It's intended as a read only, short-lived container
|
||||
|
|
@ -13,7 +13,7 @@ if ( !class_exists('Puc_v4_VcsReference', false) ):
|
|||
* @property string|null $changelog
|
||||
* @property int|null $downloadCount
|
||||
*/
|
||||
class Puc_v4_VcsReference {
|
||||
class Puc_v4_Vcs_Reference {
|
||||
private $properties = array();
|
||||
|
||||
public function __construct($properties = array()) {
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
|
||||
if ( !class_exists('Puc_v4_Vcs_ThemeUpdateChecker', false) ):
|
||||
|
||||
class Puc_v4_Vcs_ThemeUpdateChecker extends Puc_v4_Theme_UpdateChecker implements Puc_v4_Vcs_BaseChecker {
|
||||
/**
|
||||
* @var string The branch where to look for updates. Defaults to "master".
|
||||
*/
|
||||
protected $branch = 'master';
|
||||
|
||||
/**
|
||||
* @var Puc_v4_Vcs_Api Repository API client.
|
||||
*/
|
||||
protected $api = null;
|
||||
|
||||
/**
|
||||
* Puc_v4_Vcs_ThemeUpdateChecker constructor.
|
||||
*
|
||||
* @param Puc_v4_Vcs_Api $api
|
||||
* @param null $stylesheet
|
||||
* @param null $customSlug
|
||||
* @param int $checkPeriod
|
||||
* @param string $optionName
|
||||
*/
|
||||
public function __construct($api, $stylesheet = null, $customSlug = null, $checkPeriod = 12, $optionName = '') {
|
||||
$this->api = $api;
|
||||
parent::__construct($api->getRepositoryUrl(), $stylesheet, $customSlug, $checkPeriod, $optionName);
|
||||
}
|
||||
|
||||
public function requestUpdate() {
|
||||
$api = $this->api;
|
||||
|
||||
$update = new Puc_v4_Theme_Update();
|
||||
$update->slug = $this->slug;
|
||||
|
||||
//Figure out which reference (tag or branch) we'll use to get the latest version of the theme.
|
||||
$updateSource = $api->chooseReference($this->branch, false);
|
||||
if ( $updateSource ) {
|
||||
$ref = $updateSource->name;
|
||||
$update->version = $updateSource->version;
|
||||
$update->download_url = $updateSource->downloadUrl;
|
||||
} else {
|
||||
$ref = $this->branch;
|
||||
}
|
||||
|
||||
//Get headers from the main stylesheet in this branch/tag. Its "Version" header and other metadata
|
||||
//are what the WordPress install will actually see after upgrading, so they take precedence over releases/tags.
|
||||
$remoteStylesheet = $api->getRemoteFile('style.css', $ref);
|
||||
if ( !empty($remoteStylesheet) ) {
|
||||
$remoteHeader = $this->getFileHeader($remoteStylesheet);
|
||||
if ( !empty($remoteHeader['Version']) ) {
|
||||
$update->version = $remoteHeader['Version'];
|
||||
}
|
||||
if ( !empty($remoteHeader['ThemeURI']) ) {
|
||||
$update->details_url = $remoteHeader['ThemeURI'];
|
||||
}
|
||||
}
|
||||
|
||||
//The details URL defaults to the Theme URI header or the repository URL.
|
||||
if ( empty($update->details_url) ) {
|
||||
$update->details_url = $this->theme->get('ThemeURI');
|
||||
}
|
||||
if ( empty($update->details_url) ) {
|
||||
$update->details_url = $this->metadataUrl;
|
||||
}
|
||||
|
||||
if ( empty($update->version) ) {
|
||||
//It looks like we didn't find a valid update after all.
|
||||
$update = null;
|
||||
}
|
||||
|
||||
$update = $this->filterUpdateResult($update);
|
||||
return $update;
|
||||
}
|
||||
|
||||
public function setBranch($branch) {
|
||||
$this->branch = $branch;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setAuthentication($credentials) {
|
||||
$this->api->setAuthentication($credentials);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUpdate() {
|
||||
$update = parent::getUpdate();
|
||||
|
||||
if ( isset($update) && !empty($update->download_url) ) {
|
||||
$update->download_url = $this->api->signDownloadUrl($update->download_url);
|
||||
}
|
||||
|
||||
return $update;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
endif;
|
||||
|
|
@ -13,7 +13,9 @@ new Puc_v4_Autoloader();
|
|||
//Register classes defined in this file with the factory.
|
||||
Puc_v4_Factory::addVersion('Plugin_UpdateChecker', 'Puc_v4_Plugin_UpdateChecker', '4.0');
|
||||
Puc_v4_Factory::addVersion('Theme_UpdateChecker', 'Puc_v4_Theme_UpdateChecker', '4.0');
|
||||
Puc_v4_Factory::addVersion('GitHub_PluginUpdateChecker', 'Puc_v4_GitHub_PluginUpdateChecker', '4.0');
|
||||
Puc_v4_Factory::addVersion('GitHub_ThemeUpdateChecker', 'Puc_v4_GitHub_ThemeUpdateChecker', '4.0');
|
||||
|
||||
Puc_v4_Factory::addVersion('BitBucket_PluginUpdateChecker', 'Puc_v4_BitBucket_PluginUpdateChecker', '4.0');
|
||||
Puc_v4_Factory::addVersion('Vcs_PluginUpdateChecker', 'Puc_v4_Vcs_PluginUpdateChecker', '4.0');
|
||||
Puc_v4_Factory::addVersion('Vcs_ThemeUpdateChecker', 'Puc_v4_Vcs_ThemeUpdateChecker', '4.0');
|
||||
|
||||
Puc_v4_Factory::addVersion('GitHubApi', 'Puc_v4_Vcs_GitHubApi', '4.0');
|
||||
Puc_v4_Factory::addVersion('BitBucketApi', 'Puc_v4_Vcs_BitBucketApi', '4.0');
|
||||
|
|
|
|||
Loading…
Reference in New Issue