PluginProbe ʕ •ᴥ•ʔ
Advanced Access Manager – Access Governance for WordPress / 5.3.5
Advanced Access Manager – Access Governance for WordPress v5.3.5
6.8.4 6.8.5 6.9.0 6.9.1 6.9.10 6.9.11 6.9.12 6.9.13 6.9.14 6.9.15 6.9.16 6.9.17 6.9.18 6.9.19 6.9.2 6.9.20 6.9.21 6.9.22 6.9.23 6.9.24 6.9.25 6.9.26 6.9.27 6.9.28 6.9.29 6.9.3 6.9.30 6.9.31 6.9.32 6.9.33 6.9.34 6.9.35 6.9.36 6.9.37 6.9.38 6.9.39 6.9.4 6.9.41 6.9.42 6.9.43 6.9.44 6.9.45 6.9.46 6.9.47 6.9.48 6.9.49 6.9.5 6.9.51 6.9.6 6.9.7 6.9.8 6.9.9 7.0.0 7.0.0-alpha.6 7.0.0-alpha.7 7.0.0-beta.1 7.0.0-rc1 7.0.0-rc2 7.0.0-rc3 7.0.1 7.0.10 7.0.11 7.0.2 7.0.3 7.0.4 7.0.5 7.0.6 7.0.7 7.0.8 7.0.9 7.1.0 7.1.1 trunk 3.0 4.0 4.0.1 4.1 4.2 4.3 4.4 4.4.1 4.5 4.6 4.6.1 4.6.2 4.7 4.7.1 4.7.2 4.7.5 4.7.6 4.8 4.8.1 4.9 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 4.9.5.1 4.9.5.2 5.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1 5.1.1 5.10 5.11 5.2 5.2.1 5.2.5 5.2.6 5.2.7 5.3 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.4 5.4.1 5.4.2 5.4.3 5.4.3.1 5.4.3.2 5.5 5.5.1 5.5.2 5.6 5.6.1 5.6.1.1 5.7 5.7.1 5.7.2 5.7.3 5.8 5.8.1 5.8.2 5.8.3 5.9 5.9.1 5.9.1.1 5.9.2 5.9.2.1 5.9.3 5.9.4 5.9.5 5.9.6 5.9.6.1 5.9.6.2 5.9.6.3 5.9.7 5.9.7.1 5.9.7.2 5.9.7.3 5.9.8 5.9.8.1 5.9.9 5.9.9.1 6.0.0 6.0.1 6.0.2 6.0.3 6.0.4 6.0.5 6.1.0 6.1.1 6.2.0 6.2.1 6.2.2 6.3.0 6.3.1 6.3.2 6.3.3 6.4.0 6.4.1 6.4.2 6.4.3 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 6.6.0 6.6.1 6.6.2 6.6.3 6.6.4 6.7.0 6.7.1 6.7.2 6.7.3 6.7.4 6.7.5 6.7.6 6.7.7 6.7.8 6.7.9 6.8.0 6.8.1 6.8.2 6.8.3
advanced-access-manager / Application / Extension / Repository.php
advanced-access-manager / Application / Extension Last commit date
List.php 8 years ago Repository.php 8 years ago
Repository.php
432 lines
1 <?php
2
3 /**
4 * ======================================================================
5 * LICENSE: This file is subject to the terms and conditions defined in *
6 * file 'license.txt', which is part of this source code package. *
7 * ======================================================================
8 */
9
10 /**
11 * Extension Repository
12 *
13 * @package AAM
14 * @author Vasyl Martyniuk <vasyl@vasyltech.com>
15 */
16 class AAM_Extension_Repository {
17
18 /**
19 * Extension status: installed
20 *
21 * Extension has been installed and is up to date
22 */
23 const STATUS_INSTALLED = 'installed';
24
25 /**
26 * License violation
27 *
28 * Extension is inactive
29 */
30 const STATUS_INACTIVE = 'inactive';
31
32 /**
33 * Extension status: download
34 *
35 * Extension is not installed and either needs to be purchased or
36 * downloaded for free.
37 */
38 const STATUS_DOWNLOAD = 'download';
39
40 /**
41 * Extension status: update
42 *
43 * New version of the extension has been detected.
44 */
45 const STATUS_UPDATE = 'update';
46
47 /**
48 * Single instance of itself
49 *
50 * @var AAM_Extension_Repository
51 *
52 * @access private
53 * @static
54 */
55 private static $_instance = null;
56
57 /**
58 * Extension list
59 *
60 * @var array
61 *
62 * @access protected
63 */
64 protected $list = array();
65
66 /**
67 * Constructor
68 *
69 * @return void
70 *
71 * @access protected
72 */
73 protected function __construct() {}
74
75 /**
76 * Load active extensions
77 *
78 * @return void
79 *
80 * @access public
81 */
82 public function load($dir = null) {
83 $basedir = (is_null($dir) ? $this->getBasedir() : $dir);
84
85 //since release 3.4 some extensions get intergreated into core
86 AAM_Core_Compatibility::initExtensions();
87
88 if (file_exists($basedir)) {
89 //iterate through each active extension and load it
90 foreach (scandir($basedir) as $extension) {
91 if (!in_array($extension, array('.', '..'))) {
92 $this->bootstrapExtension($basedir . '/' . $extension);
93 }
94 }
95 // TODO: Rethink this hook
96 //Very important hook for cases when there is extensions dependancy.
97 //For example AAM Plus Package depends on AAM Utitlities properties
98 do_action('aam-post-extensions-load');
99 }
100 }
101
102 /**
103 * Bootstrap the Extension
104 *
105 * In case of any errors, the output can be found in console
106 *
107 * @param string $path
108 *
109 * @return void
110 * @access protected
111 */
112 protected function bootstrapExtension($path) {
113 static $cache = null;
114
115 if (is_null($cache)) {
116 $cache = AAM_Core_Compatibility::getLicenseList();
117 }
118
119 $load = true;
120 $config = "{$path}/config.php";
121 $bootstrap = "{$path}/bootstrap.php";
122
123 if (file_exists($config)) {
124 $conf = require $config;
125 $load = empty($cache[$conf['id']]['status']) || ($cache[$conf['id']]['status'] != self::STATUS_INACTIVE);
126 } else { // TODO - Remove May 2019
127 AAM_Core_Console::add(AAM_Backend_View_Helper::preparePhrase(
128 sprintf(
129 __('The [%s] file is missing. Update extension to the latest version. %sRead more.%s', AAM_KEY),
130 str_replace(AAM_EXTENSION_BASE . '/', '', $config),
131 '<a href="https://aamplugin.com/help/how-to-fix-the-config-php-file-is-missing-notification" target="_blank">',
132 '</a>'
133 ),
134 'b'
135 ));
136 }
137
138 if ($load && file_exists($bootstrap)) { //bootstrap the extension
139 require($bootstrap);
140 }
141 }
142
143 /**
144 * Store the license key
145 *
146 * This is important to have just for the update extension purposes
147 *
148 * @param stdClass $package
149 * @param string $license
150 *
151 * @return void
152 *
153 * @access public
154 */
155 public function storeLicense($package, $license) {
156 //retrieve the installed list of extensions
157 $list = AAM_Core_Compatibility::getLicenseList();
158
159 $list[$package->id] = array(
160 'license' => $license, 'expire' => $package->expire
161 );
162
163 //update the extension list
164 AAM_Core_API::updateOption('aam-extensions', $list);
165 }
166
167 /**
168 *
169 * @return type
170 */
171 public function getCommercialLicenses($details = true) {
172 $response = array();
173 $licenses = AAM_Core_API::getOption('aam-extensions', array());
174 $extensions = AAM_Extension_List::get();
175
176 foreach((array) $licenses as $key => $data) {
177 if (isset($extensions[$key])
178 && !empty($data['license'])
179 && $extensions[$key]['type'] == 'commercial') {
180
181 if ($details) {
182 $response[] = array(
183 'license' => $data['license'],
184 'extension' => $extensions[$key]['title'],
185 'expires' => (isset($data['expires']) ? $data['expires'] : null)
186 );
187 } else {
188 $response[] = $data['license'];
189 }
190 }
191 }
192
193 return $response;
194 }
195
196 /**
197 * Add new extension
198 *
199 * @param blob $zip
200 *
201 * @return boolean
202 * @access public
203 */
204 public function add($zip) {
205 $filepath = $this->getBasedir() . '/' . uniqid('aam_');
206 $result = false;
207
208 if (file_put_contents($filepath, $zip)) { //unzip the archive
209 WP_Filesystem(false, false, true); //init filesystem
210 $result = unzip_file($filepath, $this->getBasedir());
211 if (!is_wp_error($result)) {
212 $result = true;
213 }
214 @unlink($filepath); //remove the working archive
215 }
216
217 return $result;
218 }
219
220 /**
221 * Update extension status
222 *
223 * @param string $id
224 * @param string $status
225 */
226 public function updateStatus($id, $status) {
227 //retrieve the installed list of extensions
228 $list = AAM_Core_Compatibility::getLicenseList();
229
230 $list[$id]['status'] = $status;
231
232 //update the extension list
233 AAM_Core_API::updateOption('aam-extensions', $list);
234 }
235
236 /**
237 * Get extension version
238 *
239 * @param string $id
240 *
241 * @return string|null
242 *
243 * @access public
244 */
245 public function getVersion($id) {
246 return (defined($id) ? constant($id) : null);
247 }
248
249 /**
250 * Get extension list
251 *
252 * @return array
253 *
254 * @access public
255 */
256 public function getList() {
257 if (empty($this->list)) {
258 $list = AAM_Extension_List::get();
259 $index = AAM_Core_Compatibility::getLicenseList();
260 $check = AAM_Core_API::getOption('aam-check', array(), 'site');
261
262 foreach ($list as $id => &$item) {
263 //get premium license from the stored license index
264 if (empty($item['license'])) {
265 if (!empty($index[$id]['license'])) {
266 $item['license'] = $index[$id]['license'];
267 $item['expire'] = (isset($index[$id]['expire']) ? date('Y-m-d', strtotime($index[$id]['expire'])) : null);
268 } else {
269 $item['license'] = '';
270 }
271 }
272
273 //update extension status
274 $item['status'] = $this->checkStatus($item, $check, $index);
275 }
276
277 $this->list = $list;
278 }
279
280 return $this->list;
281 }
282
283 /**
284 *
285 * @param type $item
286 * @param type $index
287 * @return type
288 */
289 protected function checkStatus($item, $retrieved, $stored) {
290 $id = $item['id'];
291 $status = !empty($stored[$id]['status']) ? $stored[$id]['status'] : null;
292
293 if (is_null($status)) {
294 $status = AAM_Extension_Repository::STATUS_DOWNLOAD;
295
296 if (defined($id)) {
297 $status = AAM_Extension_Repository::STATUS_INSTALLED;
298
299 if ($this->isOutdatedVersion($item, $retrieved, constant($id))) {
300 $status = AAM_Extension_Repository::STATUS_UPDATE;
301 AAM_Core_Console::add(
302 AAM_Backend_View_Helper::preparePhrase(sprintf(
303 'The [%s] extension has new update available for download;',
304 $item['title']
305 ), 'b')
306 );
307 }
308 }
309 } elseif ($status == AAM_Extension_Repository::STATUS_INSTALLED) {
310 if (!defined($id)) {
311 $status = AAM_Extension_Repository::STATUS_DOWNLOAD;
312 } elseif ($this->isOutdatedVersion($item, $retrieved, constant($id))) {
313 $status = AAM_Extension_Repository::STATUS_UPDATE;
314 }
315 }
316
317 return $status;
318 }
319
320 /**
321 *
322 * @param type $item
323 * @param type $retrieved
324 * @param type $version
325 * @return type
326 */
327 protected function isOutdatedVersion($item, $retrieved, $version) {
328 $id = $item['id'];
329
330 if ($item['type'] == 'commercial') {
331 $valid = !empty($item['license']);
332 } else {
333 $valid = true;
334 }
335
336 $outdated = false;
337
338 if ($valid) {
339 // first check the retrieved version from the server
340 if (isset($retrieved->$id)) {
341 $outdated = version_compare($version, $retrieved->$id->version) == -1;
342 } else {
343 $outdated = version_compare($version, $item['latest']) == -1;
344 }
345 }
346
347 return $outdated;
348 }
349
350 /**
351 * Check extension directory
352 *
353 * @return boolean|sstring
354 *
355 * @access public
356 *
357 * @global type $wp_filesystem
358 */
359 public function checkDirectory() {
360 $error = false;
361 $basedir = $this->getBasedir();
362
363 if (!file_exists($basedir)) {
364 if (!@mkdir($basedir, fileperms(ABSPATH) & 0777 | 0755, true)) {
365 $error = sprintf(__('Failed to create %s', AAM_KEY), $basedir);
366 }
367 } elseif (!is_writable($basedir)) {
368 $error = sprintf(
369 __('Directory %s is not writable', AAM_KEY), $basedir
370 );
371 }
372
373 return $error;
374 }
375
376 /**
377 * Get base directory
378 *
379 * @return string
380 *
381 * @access public
382 */
383 public function getBasedir($relative = false) {
384 $dir = AAM_Core_Config::get('core.extention.directory', AAM_EXTENSION_BASE);
385
386 return ($relative ? str_replace(ABSPATH, '', $dir) : $dir);
387 }
388
389 /**
390 *
391 * @return type
392 */
393 public function isWriteableDirectory() {
394 $directory = $this->getBasedir();
395
396 return file_exists($directory) && is_writeable($directory);
397 }
398
399 /**
400 * Check if there are any updates
401 *
402 * @return type
403 */
404 public function hasUpdates() {
405 $updates = 0;
406
407 foreach($this->getList() as $item) {
408 $updates += ($item['status'] == self::STATUS_UPDATE);
409 }
410
411 return $updates ? true : false;
412 }
413
414 /**
415 * Get single instance of itself
416 *
417 * @param AAM $parent
418 *
419 * @return AAM_Extension_Repository
420 *
421 * @access public
422 * @static
423 */
424 public static function getInstance() {
425 if (is_null(self::$_instance)) {
426 self::$_instance = new self;
427 }
428
429 return self::$_instance;
430 }
431
432 }