Add support for GitHub release assets. See #93
Usage: Set up the update checker instance as usual, then call the new enableReleaseAssets() method of the GitHub API class.
`$gitHubUpdateChecker->getVcsApi()->enableReleaseAssets();`
Notes:
- You can make PUC look for a specific asset by passing a regular expression to enableReleaseAssets(). For example, `$api->enableReleaseAssets('/custom-asset/')` will make PUC use the first asset where the file name contains the string "custom-asset".
- PUC always chooses the first matching asset.
- If the latest release has no assets or none of them match the regex, PUC will fall back to the old behaviour of using the automatically generated ZIP file.
- Private repositories only work with WP 3.7 or later. Older WordPress versions will throw an error when trying to download the update.
This commit is contained in:
parent
af5207d349
commit
60add5f915
|
|
@ -17,6 +17,11 @@ if ( !interface_exists('Puc_v4p3_Vcs_BaseChecker', false) ):
|
|||
* @return $this
|
||||
*/
|
||||
public function setAuthentication($credentials);
|
||||
|
||||
/**
|
||||
* @return Puc_v4p3_Vcs_Api
|
||||
*/
|
||||
public function getVcsApi();
|
||||
}
|
||||
|
||||
endif;
|
||||
|
|
@ -22,6 +22,21 @@ if ( !class_exists('Puc_v4p3_Vcs_GitHubApi', false) ):
|
|||
*/
|
||||
protected $accessToken;
|
||||
|
||||
/**
|
||||
* @var bool Whether to download release assets instead of the auto-generated source code archives.
|
||||
*/
|
||||
protected $releaseAssetsEnabled = false;
|
||||
|
||||
/**
|
||||
* @var string|null Regular expression that's used to filter release assets by name. Optional.
|
||||
*/
|
||||
protected $assetFilterRegex = null;
|
||||
|
||||
/**
|
||||
* @var string|null The unchanging part of a release asset URL. Used to identify download attempts.
|
||||
*/
|
||||
protected $assetApiBaseUrl = null;
|
||||
|
||||
public function __construct($repositoryUrl, $accessToken = null) {
|
||||
$path = @parse_url($repositoryUrl, PHP_URL_PATH);
|
||||
if ( preg_match('@^/?(?P<username>[^/]+?)/(?P<repository>[^/#?&]+?)/?$@', $path, $matches) ) {
|
||||
|
|
@ -53,13 +68,34 @@ if ( !class_exists('Puc_v4p3_Vcs_GitHubApi', false) ):
|
|||
'apiResponse' => $release,
|
||||
));
|
||||
|
||||
if ( isset($release->assets[0]) ) {
|
||||
$reference->downloadCount = $release->assets[0]->download_count;
|
||||
}
|
||||
|
||||
if ( $this->releaseAssetsEnabled && isset($release->assets, $release->assets[0]) ) {
|
||||
//Use the first release asset that matches the specified regular expression.
|
||||
$matchingAssets = array_filter($release->assets, array($this, 'matchesAssetFilter'));
|
||||
if ( !empty($matchingAssets) ) {
|
||||
if ( $this->isAuthenticationEnabled() ) {
|
||||
/**
|
||||
* Keep in mind that we'll need to add an "Accept" header to download this asset.
|
||||
* @see setReleaseDownloadHeader()
|
||||
*/
|
||||
$reference->downloadUrl = $this->signDownloadUrl($matchingAssets[0]->url);
|
||||
} else {
|
||||
//It seems that browser_download_url only works for public repositories.
|
||||
//Using an access_token doesn't help. Maybe OAuth would work?
|
||||
$reference->downloadUrl = $matchingAssets[0]->browser_download_url;
|
||||
}
|
||||
|
||||
$reference->downloadCount = $matchingAssets[0]->download_count;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !empty($release->body) ) {
|
||||
/** @noinspection PhpUndefinedClassInspection */
|
||||
$reference->changelog = Parsedown::instance()->text($release->body);
|
||||
}
|
||||
if ( isset($release->assets[0]) ) {
|
||||
$reference->downloadCount = $release->assets[0]->download_count;
|
||||
}
|
||||
|
||||
return $reference;
|
||||
}
|
||||
|
|
@ -302,6 +338,76 @@ if ( !class_exists('Puc_v4p3_Vcs_GitHubApi', false) ):
|
|||
return add_query_arg('access_token', $this->credentials, $url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable updating via release assets.
|
||||
*
|
||||
* If the latest release contains no usable assets, the update checker
|
||||
* will fall back to using the automatically generated ZIP archive.
|
||||
*
|
||||
* Private repositories will only work with WordPress 3.7 or later.
|
||||
*
|
||||
* @param string|null $fileNameRegex Optional. Use only those assets where the file name matches this regex.
|
||||
*/
|
||||
public function enableReleaseAssets($fileNameRegex = null) {
|
||||
$this->releaseAssetsEnabled = true;
|
||||
$this->assetFilterRegex = $fileNameRegex;
|
||||
$this->assetApiBaseUrl = sprintf(
|
||||
'//api.github.com/repos/%1$s/%2$s/releases/assets/',
|
||||
$this->userName,
|
||||
$this->repositoryName
|
||||
);
|
||||
|
||||
//Optimization: Instead of filtering all HTTP requests, let's do it only when
|
||||
//WordPress is about to download an update.
|
||||
add_filter('upgrader_pre_download', array($this, 'addHttpRequestFilter'), 10, 1); //WP 3.7+
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this asset match the file name regex?
|
||||
*
|
||||
* @param stdClass $releaseAsset
|
||||
* @return bool
|
||||
*/
|
||||
protected function matchesAssetFilter($releaseAsset) {
|
||||
if ( $this->assetFilterRegex === null ) {
|
||||
//The default is to accept all assets.
|
||||
return true;
|
||||
}
|
||||
return isset($releaseAsset->name) && preg_match($this->assetFilterRegex, $releaseAsset->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @param bool $result
|
||||
* @return bool
|
||||
*/
|
||||
public function addHttpRequestFilter($result) {
|
||||
static $filterAdded = false;
|
||||
if ( $this->releaseAssetsEnabled && !$filterAdded && $this->isAuthenticationEnabled() ) {
|
||||
add_filter('http_request_args', array($this, 'setReleaseDownloadHeader'), 10, 2);
|
||||
$filterAdded = true;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the HTTP header that's necessary to download private release assets.
|
||||
*
|
||||
* See GitHub docs:
|
||||
* @link https://developer.github.com/v3/repos/releases/#get-a-single-release-asset
|
||||
*
|
||||
* @internal
|
||||
* @param array $requestArgs
|
||||
* @param string $url
|
||||
* @return array
|
||||
*/
|
||||
public function setReleaseDownloadHeader($requestArgs, $url = '') {
|
||||
//Is WordPress trying to download one of our assets?
|
||||
if ( strpos($url, $this->assetApiBaseUrl) !== false ) {
|
||||
$requestArgs['headers']['accept'] = 'application/octet-stream';
|
||||
}
|
||||
return $requestArgs;
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
|
|
@ -192,6 +192,10 @@ if ( !class_exists('Puc_v4p3_Vcs_PluginUpdateChecker') ):
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function getVcsApi() {
|
||||
return $this->api;
|
||||
}
|
||||
|
||||
public function getUpdate() {
|
||||
$update = parent::getUpdate();
|
||||
|
||||
|
|
|
|||
|
|
@ -93,6 +93,10 @@ if ( !class_exists('Puc_v4p3_Vcs_ThemeUpdateChecker', false) ):
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function getVcsApi() {
|
||||
return $this->api;
|
||||
}
|
||||
|
||||
public function getUpdate() {
|
||||
$update = parent::getUpdate();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue