Skip to content

Commit 7d8cddb

Browse files
committed
Add plugin updating from WordPress
1 parent bb8a60f commit 7d8cddb

File tree

3 files changed

+1710
-2
lines changed

3 files changed

+1710
-2
lines changed

carpenter.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
/**
44
* Plugin Name: Carpenter
5-
* Version: 1.0.4
5+
* Version: 1.1.0
66
* Author: Apsis Labs
77
* Author URI: www.apsis.io
88
*/
@@ -15,8 +15,14 @@ function __construct() {
1515
include_once('core/post-type.cls.php');
1616
include_once('core/taxonomy.cls.php');
1717
include_once('core/carpenter.cls.php');
18+
include_once('core/updater.cls.php');
1819
}
1920
}
2021

22+
if ( is_admin() ) {
23+
// Check for Update on GitHub
24+
new CarpenterUpdater( __FILE__, 'apsislabs', 'carpenter' );
25+
}
26+
2127
new aps_carpenter();
22-
}
28+
}

core/updater.cls.php

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
<?php
2+
3+
class CarpenterUpdater {
4+
private $slug;
5+
private $pluginData;
6+
private $username;
7+
private $repo;
8+
private $pluginFile;
9+
private $githubAPIResult;
10+
private $accessToken;
11+
private $pluginActivated;
12+
13+
public function __construct($pluginFile, $gitHubUsername, $gitHubProjectName, $accessToken = '') {
14+
add_filter('pre_set_site_transient_update_plugins', array($this, 'setTransitent'));
15+
add_filter('plugins_api', array($this, 'setPluginInfo'), 10, 3);
16+
add_filter('upgrader_pre_install', array($this, 'preInstall'), 10, 3);
17+
add_filter('upgrader_post_install', array($this, 'postInstall'), 10, 3);
18+
19+
$this->pluginFile = $pluginFile;
20+
$this->username = $gitHubUsername;
21+
$this->repo = $gitHubProjectName;
22+
$this->accessToken = $accessToken;
23+
}
24+
25+
private function initPluginData() {
26+
$this->slug = plugin_basename($this->pluginFile);
27+
$this->pluginData = get_plugin_data($this->pluginFile);
28+
}
29+
30+
private function getRepoReleaseInfo() {
31+
if ( !empty($this->githubAPIResult) ) { return; }
32+
33+
$url = "https://api.github.com/repos/{$this->username}/{$this->repo}/releases";
34+
35+
if (! empty($this->accessToken)) {
36+
$url = add_query_arg(array('access_token' => $this->accessToken), $url);
37+
}
38+
39+
$this->githubAPIResult = wp_remote_retrieve_body(wp_remote_get($url));
40+
41+
if (! empty($this->githubAPIResult)) {
42+
$this->githubAPIResult = @json_decode($this->githubAPIResult);
43+
}
44+
45+
// Use only the latest release
46+
if (is_array($this->githubAPIResult)) {
47+
$this->githubAPIResult = $this->githubAPIResult[0];
48+
}
49+
}
50+
51+
public function setTransitent($transient) {
52+
if (empty($transient->checked)) { return $transient; }
53+
54+
// Get plugin & GitHub release information
55+
$this->initPluginData();
56+
$this->getRepoReleaseInfo();
57+
58+
$doUpdate = version_compare($this->githubAPIResult->tag_name, $transient->checked[$this->slug]);
59+
60+
if ($doUpdate) {
61+
$package = $this->githubAPIResult->zipball_url;
62+
63+
if (! empty($this->accessToken)) {
64+
$package = add_query_arg(array('access_token' => $this->accessToken), $package);
65+
}
66+
67+
// Plugin object
68+
$obj = new stdClass();
69+
$obj->slug = $this->slug;
70+
$obj->new_version = $this->githubAPIResult->tag_name;
71+
$obj->url = $this->pluginData['PluginURI'];
72+
$obj->package = $package;
73+
74+
$transient->response[$this->slug] = $obj;
75+
}
76+
77+
return $transient;
78+
}
79+
80+
public function setPluginInfo($false, $action, $response) {
81+
$this->initPluginData();
82+
$this->getRepoReleaseInfo();
83+
84+
if (empty($response->slug) || $response->slug != $this->slug) {
85+
return $false;
86+
}
87+
88+
// Add our plugin information
89+
$response->last_updated = $this->githubAPIResult->published_at;
90+
$response->slug = $this->slug;
91+
$response->plugin_name = $this->pluginData['Name'];
92+
$response->version = $this->githubAPIResult->tag_name;
93+
$response->author = $this->pluginData['AuthorName'];
94+
$response->homepage = $this->pluginData['PluginURI'];
95+
96+
// This is our release download zip file
97+
$downloadLink = $this->githubAPIResult->zipball_url;
98+
99+
if (!empty($this->accessToken)) {
100+
$downloadLink = add_query_arg( array('access_token' => $this->accessToken), $downloadLink );
101+
}
102+
103+
$response->download_link = $downloadLink;
104+
105+
// Load Parsedown
106+
$parsedownPath = join(array( dirname(__DIR__), 'lib', 'parsedown.cls.php' ), DIRECTORY_SEPARATOR);
107+
require_once $parsedownPath;
108+
109+
$changelog = $this->githubAPIResult->body;
110+
111+
if ( class_exists('Parsedown') ) {
112+
$changelog = Parsedown::instance()->parse($this->githubAPIResult->body);
113+
}
114+
115+
// Create tabs in the lightbox
116+
$response->sections = array(
117+
'Description' => $this->pluginData['Description'],
118+
'changelog' => $changelog
119+
);
120+
121+
// Gets the required version of WP if available
122+
$matches = null;
123+
124+
preg_match("/requires:\s([\d\.]+)/i", $this->githubAPIResult->body, $matches);
125+
126+
if (! empty($matches)) {
127+
if (is_array($matches)) {
128+
if (count($matches) > 1) {
129+
$response->requires = $matches[1];
130+
}
131+
}
132+
}
133+
134+
// Gets the tested version of WP if available
135+
$matches = null;
136+
137+
preg_match("/tested:\s([\d\.]+)/i", $this->githubAPIResult->body, $matches);
138+
139+
if (! empty($matches)) {
140+
if (is_array($matches)) {
141+
if (count($matches) > 1) {
142+
$response->tested = $matches[1];
143+
}
144+
}
145+
}
146+
147+
return $response;
148+
}
149+
150+
public function preInstall($true, $args) {
151+
// Get plugin information
152+
$this->initPluginData();
153+
154+
// Check if the plugin was installed before...
155+
$this->pluginActivated = is_plugin_active($this->slug);
156+
}
157+
158+
public function postInstall($true, $hook_extra, $result) {
159+
global $wp_filesystem;
160+
161+
// Since we are hosted in GitHub, our plugin folder would have a dirname of
162+
// reponame-tagname change it to our original one:
163+
$pluginFolder = WP_PLUGIN_DIR.DIRECTORY_SEPARATOR.dirname($this->slug);
164+
$wp_filesystem->move($result['destination'], $pluginFolder);
165+
$result['destination'] = $pluginFolder;
166+
167+
// Re-activate plugin if needed
168+
if ($this->pluginActivated) {
169+
$activate = activate_plugin($this->slug);
170+
}
171+
172+
return $result;
173+
}
174+
}

0 commit comments

Comments
 (0)