PluginProbe ʕ •ᴥ•ʔ
Advanced Access Manager – Access Governance for WordPress / 5.8.2
Advanced Access Manager – Access Governance for WordPress v5.8.2
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 7 years ago Repository.php 7 years ago
Repository.php
452 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 * List of detected extensions during the boot
59 *
60 * @var array
61 *
62 * @access protected
63 */
64 protected $depectedExtensions = array();
65
66 /**
67 * Extension list
68 *
69 * @var array
70 *
71 * @access protected
72 */
73 protected $list = array();
74
75 /**
76 * Constructor
77 *
78 * @return void
79 *
80 * @access protected
81 */
82 protected function __construct() {}
83
84 /**
85 * Load active extensions
86 *
87 * @return void
88 *
89 * @access public
90 */
91 public function load($dir = null) {
92 $basedir = (is_null($dir) ? $this->getBasedir() : $dir);
93
94 //since release 3.4 some extensions get intergreated into core
95 AAM_Core_Compatibility::initExtensions();
96
97 if (file_exists($basedir)) {
98 //iterate through each active extension and load it
99 foreach (scandir($basedir) as $extension) {
100 if (!in_array($extension, array('.', '..'), true)) {
101 $this->bootstrapExtension($basedir . '/' . $extension);
102 }
103 }
104 // TODO: Rethink this hook
105 //Very important hook for cases when there is extensions dependancy.
106 //For example AAM Plus Package depends on AAM Utitlities properties
107 do_action('aam-post-extensions-load');
108 }
109 }
110
111 /**
112 * Bootstrap the Extension
113 *
114 * In case of any errors, the output can be found in console
115 *
116 * @param string $path
117 *
118 * @return void
119 * @access protected
120 */
121 protected function bootstrapExtension($path) {
122 static $cache = null;
123
124 if (is_null($cache)) {
125 $cache = AAM_Core_Compatibility::getLicenseList();
126 }
127
128 $load = false;
129 $config = "{$path}/config.php";
130 $bootstrap = "{$path}/bootstrap.php";
131
132 if (file_exists($config)) {
133 $conf = require $config;
134
135 $this->depectedExtensions[$conf['id']] = $conf['version'];
136
137 // determin if extension needs to be loaded based on the status
138 $status = empty($cache[$conf['id']]['status']) || ($cache[$conf['id']]['status'] !== self::STATUS_INACTIVE);
139
140 // determin if extension meets minimum required AAM version
141 $list = AAM_Extension_List::get();
142 $issue = !empty($conf['requires']['aam']) && (version_compare(AAM_Core_API::version(), $conf['requires']['aam']) === -1);
143 $load = $status && !$issue;
144
145 if ($issue) {
146 if (!empty($list[$conf['id']]['title'])) { // Any custom extensions
147 AAM_Core_Console::add(AAM_Backend_View_Helper::preparePhrase(
148 sprintf(
149 __('[%s] was not loaded. Update AAM plugin to the latest version.', AAM_KEY),
150 $list[$conf['id']]['title']
151 ),
152 'b'
153 ));
154 }
155 }
156 } else { // TODO - Remove May 2019
157 AAM_Core_Console::add(AAM_Backend_View_Helper::preparePhrase(
158 sprintf(
159 __('The [%s] does not appear to be a valid AAM extension. %sRead more.%s', AAM_KEY),
160 str_replace(AAM_EXTENSION_BASE . '/', '', $config),
161 '<a href="https://aamplugin.com/help/how-to-fix-the-config-php-file-is-missing-notification" target="_blank">',
162 '</a>'
163 ),
164 'b'
165 ));
166 }
167
168 if ($load && file_exists($bootstrap)) { //bootstrap the extension
169 require($bootstrap);
170 }
171 }
172
173 /**
174 * Store the license key
175 *
176 * This is important to have just for the update extension purposes
177 *
178 * @param stdClass $package
179 * @param string $license
180 *
181 * @return void
182 *
183 * @access public
184 */
185 public function storeLicense($package, $license) {
186 //retrieve the installed list of extensions
187 $list = AAM_Core_Compatibility::getLicenseList();
188
189 $list[$package->id] = array(
190 'license' => $license, 'expire' => $package->expire
191 );
192
193 //update the extension list
194 AAM_Core_API::updateOption('aam-extensions', $list);
195 }
196
197 /**
198 *
199 * @return type
200 */
201 public function getCommercialLicenses($details = true) {
202 $response = array();
203 $licenses = AAM_Core_API::getOption('aam-extensions', array());
204 $extensions = AAM_Extension_List::get();
205
206 foreach((array) $licenses as $key => $data) {
207 if (isset($extensions[$key])
208 && !empty($data['license'])
209 && $extensions[$key]['type'] === 'commercial') {
210
211 if ($details) {
212 $response[] = array(
213 'license' => $data['license'],
214 'extension' => $extensions[$key]['title'],
215 'expires' => (!empty($data['expires']) ? $data['expires'] : null)
216 );
217 } else {
218 $response[] = $data['license'];
219 }
220 }
221 }
222
223 return $response;
224 }
225
226 /**
227 * Add new extension
228 *
229 * @param blob $zip
230 *
231 * @return boolean
232 * @access public
233 */
234 public function add($zip) {
235 $filepath = $this->getBasedir() . '/' . uniqid('aam_');
236 $result = false;
237
238 if (file_put_contents($filepath, $zip)) { //unzip the archive
239 WP_Filesystem(false, false, true); //init filesystem
240 $result = unzip_file($filepath, $this->getBasedir());
241 if (!is_wp_error($result)) {
242 $result = true;
243 }
244 @unlink($filepath); //remove the working archive
245 }
246
247 return $result;
248 }
249
250 /**
251 * Update extension status
252 *
253 * @param string $id
254 * @param string $status
255 */
256 public function updateStatus($id, $status) {
257 //retrieve the installed list of extensions
258 $list = AAM_Core_Compatibility::getLicenseList();
259
260 $list[$id]['status'] = $status;
261
262 //update the extension list
263 AAM_Core_API::updateOption('aam-extensions', $list);
264 }
265
266 /**
267 * Get extension version
268 *
269 * @param string $id
270 *
271 * @return string|null
272 *
273 * @access public
274 */
275 public function getVersion($id) {
276 return (isset($this->depectedExtensions[$id]) ? $this->depectedExtensions[$id] : null);
277 }
278
279 /**
280 * Get extension list
281 *
282 * @return array
283 *
284 * @access public
285 */
286 public function getList() {
287 if (empty($this->list)) {
288 $list = AAM_Extension_List::get();
289 $index = AAM_Core_Compatibility::getLicenseList();
290 $check = AAM_Core_API::getOption('aam-check', array(), 'site');
291
292 foreach ($list as $id => &$item) {
293 //get premium license from the stored license index
294 if (empty($item['license'])) {
295 if (!empty($index[$id]['license'])) {
296 $item['license'] = $index[$id]['license'];
297 $item['expire'] = (!empty($index[$id]['expire']) ? date('Y-m-d', strtotime($index[$id]['expire'])) : null);
298 } else {
299 $item['license'] = '';
300 }
301 }
302
303 //update extension status
304 $item['status'] = $this->checkStatus($item, $check, $index);
305 }
306
307 $this->list = $list;
308 }
309
310 return $this->list;
311 }
312
313 /**
314 *
315 * @param type $item
316 * @param type $index
317 * @return type
318 */
319 protected function checkStatus($item, $retrieved, $stored) {
320 $id = $item['id'];
321 $status = !empty($stored[$id]['status']) ? $stored[$id]['status'] : null;
322
323 if (is_null($status)) {
324 $status = AAM_Extension_Repository::STATUS_DOWNLOAD;
325
326 if (isset($this->depectedExtensions[$id])) {
327 $status = AAM_Extension_Repository::STATUS_INSTALLED;
328
329 if ($this->isOutdatedVersion($item, $retrieved, $this->depectedExtensions[$id])) {
330 $status = AAM_Extension_Repository::STATUS_UPDATE;
331 AAM_Core_Console::add(
332 AAM_Backend_View_Helper::preparePhrase(sprintf(
333 'The [%s] extension has new update available for download;',
334 $item['title']
335 ), 'b')
336 );
337 }
338 }
339 } elseif ($status === AAM_Extension_Repository::STATUS_INSTALLED) {
340 if (!isset($this->depectedExtensions[$id])) {
341 $status = AAM_Extension_Repository::STATUS_DOWNLOAD;
342 } elseif ($this->isOutdatedVersion($item, $retrieved, $this->depectedExtensions[$id])) {
343 $status = AAM_Extension_Repository::STATUS_UPDATE;
344 }
345 }
346
347 return $status;
348 }
349
350 /**
351 *
352 * @param type $item
353 * @param type $retrieved
354 * @param type $version
355 * @return type
356 */
357 protected function isOutdatedVersion($item, $retrieved, $version) {
358 $id = $item['id'];
359
360 // first check the retrieved version from the server
361 if (isset($retrieved->$id)) {
362 $outdated = version_compare($version, $retrieved->$id->version) === -1;
363 } else {
364 $outdated = version_compare($version, $item['latest']) === -1;
365 }
366
367 return $outdated;
368 }
369
370 /**
371 * Check extension directory
372 *
373 * @return boolean|sstring
374 *
375 * @access public
376 *
377 * @global type $wp_filesystem
378 */
379 public function checkDirectory() {
380 $error = false;
381 $basedir = $this->getBasedir();
382
383 if (!file_exists($basedir)) {
384 if (!@mkdir($basedir, fileperms(ABSPATH) & 0777 | 0755, true)) {
385 $error = sprintf(__('Failed to create %s', AAM_KEY), $basedir);
386 }
387 } elseif (!is_writable($basedir)) {
388 $error = sprintf(
389 __('Directory %s is not writable', AAM_KEY), $basedir
390 );
391 }
392
393 return $error;
394 }
395
396 /**
397 * Get base directory
398 *
399 * @return string
400 *
401 * @access public
402 */
403 public function getBasedir($relative = false) {
404 $dir = AAM_Core_Config::get('core.extention.directory', AAM_EXTENSION_BASE);
405
406 return ($relative ? str_replace(ABSPATH, '', $dir) : $dir);
407 }
408
409 /**
410 *
411 * @return type
412 */
413 public function isWriteableDirectory() {
414 $directory = $this->getBasedir();
415
416 return file_exists($directory) && is_writeable($directory);
417 }
418
419 /**
420 * Check if there are any updates
421 *
422 * @return type
423 */
424 public function hasUpdates() {
425 $updates = 0;
426
427 foreach($this->getList() as $item) {
428 $updates += ($item['status'] === self::STATUS_UPDATE);
429 }
430
431 return $updates ? true : false;
432 }
433
434 /**
435 * Get single instance of itself
436 *
437 * @param AAM $parent
438 *
439 * @return AAM_Extension_Repository
440 *
441 * @access public
442 * @static
443 */
444 public static function getInstance() {
445 if (is_null(self::$_instance)) {
446 self::$_instance = new self;
447 }
448
449 return self::$_instance;
450 }
451
452 }