PluginProbe
CSS & JavaScript Toolbox / 11
CSS & JavaScript Toolbox v11
trunk 0.3 0.8 10 10.1 11 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 11.9.1 12 12.0 12.0.1 12.0.3 12.0.4 12.0.5 12.0.6 12.0.7 6.0 6.0.11 All 60 releases
css-javascript-toolbox / framework / extensions / extensions.class.php

extensions.class.php in CSS & JavaScript Toolbox 11, at framework/extensions/extensions.class.php

465 lines 13.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 *
4 */
5
6 // Disallow direct access.
7 defined('ABSPATH') or die("Access denied");
8
9 /**
10 *
11 */
12 class CJTExtensions extends CJTHookableClass {
13
14 /**
15 *
16 */
17 const CACHE_OPTION_NAME = 'cjt_extensions';
18
19 /**
20 *
21 */
22 const LOAD_METHOD = 'getInvolved';
23
24 /**
25 *
26 */
27 const PREFIXS = 'cjte-,css-javascript-toolbox-';
28
29 /**
30 * put your comment there...
31 *
32 * @var mixed
33 */
34 protected $defDocs;
35
36 /**
37 * put your comment there...
38 *
39 * @var mixed
40 */
41 protected $extensions;
42
43 /**
44 * put your comment there...
45 *
46 * @var mixed
47 */
48 protected $file2Classmap;
49
50 /**
51 * put your comment there...
52 *
53 * @var mixed
54 */
55 protected $incompatibilies;
56
57 /**
58 * put your comment there...
59 *
60 * @var mixed
61 */
62 protected $incompatibleAddons = array();
63
64
65 /**
66 * put your comment there...
67 *
68 * @var mixed
69 */
70 protected $loadMethod;
71
72 /**
73 * put your comment there...
74 *
75 * @var mixed
76 */
77 protected $onautoload = array('parameters' => array('file', 'class'));
78
79 /**
80 * put your comment there...
81 *
82 * @var mixed
83 */
84 protected $onbindevent = array('parameters' => array('event', 'callback'));
85
86 /**
87 * put your comment there...
88 *
89 * @var mixed
90 */
91 protected $ondetectextension = array('parameters' => array('extension'));
92
93 /**
94 * put your comment there...
95 *
96 * @var mixed
97 */
98 protected $ongetactiveplugins = array('parameters' => array('plugins'));
99
100 /**
101 * put your comment there...
102 *
103 * @var mixed
104 */
105 protected $onload = array('parameters' => array('params'));
106
107 /**
108 * put your comment there...
109 *
110 * @var mixed
111 */
112 protected $onloadcallback = array('parameters' => array('callback'));
113
114 /**
115 * put your comment there...
116 *
117 * @var mixed
118 */
119 protected $onloaddefinition = array('parameters' => array('definition'));
120
121 /***
122 * put your comment there...
123 *
124 * @var mixed
125 */
126 protected $ontregisterautoload = array('parameters' => array('callback'));
127
128 /**
129 * put your comment there...
130 *
131 * @var mixed
132 */
133 protected $onreloadcacheparameters = array('parameters' => array('params'));
134
135 /**
136 * put your comment there...
137 *
138 * @var mixed
139 */
140 protected $onloaded = array(
141 'hookType' => CJTWordpressEvents::HOOK_ACTION,
142 'parameters' => array('class', 'extension', 'definition', 'result')
143 );
144
145 /**
146 * put your comment there...
147 *
148 * @var mixed
149 */
150 protected $prefix;
151
152 /**
153 * put your comment there...
154 *
155 * @param mixed $className
156 */
157 public function _autoload($className) {
158
159 // Load only classed defined on the list!
160 if (isset($this->extensions[$className])) {
161 $classFile = $this->onautoload($this->extensions[$className]['runtime']['classFile'], $className);
162 // Import class file!
163 require_once $classFile;
164 }
165 }
166
167 /**
168 * put your comment there...
169 *
170 * @param mixed $prefix
171 * @param mixed $loadMethod
172 * @return CJTExtensions
173 */
174 public function __construct($prefix = self::PREFIXS, $loadMethod = self::LOAD_METHOD) {
175 // Hookable!
176 parent::__construct();
177
178 // Initialize incomapiblt addons meta data
179 $this->incompatibleAddons = array(
180
181 'css-javascript-toolbox-plus' => array(
182 '9.4',
183 '<',
184 'Aborted',
185
186 function() {
187
188 ob_start();
189
190 require CJTOOLBOX_PATH . DIRECTORY_SEPARATOR . 'includes' .
191 DIRECTORY_SEPARATOR . 'html' . DIRECTORY_SEPARATOR .
192 'incompatible_cjtplus_version.html.php';
193
194 $content = ob_get_clean();
195
196 return $content;
197 }
198
199 ),
200
201 );
202
203 // Initializing!
204 $this->prefix = explode( ',', $prefix );
205 $this->loadMethod = $loadMethod;
206 }
207
208 /**
209 * put your comment there...
210 *
211 */
212 public function __destruct() {
213 spl_autoload_unregister(array($this, '_autoload'));
214 }
215
216 /**
217 * put your comment there...
218 *
219 * @param mixed $reload
220 * @return CJTExtensions
221 */
222 public function & getExtensions($reload = false) {
223 // Get cached extensions or cache then if not yest cached!
224 extract($this->onreloadcacheparameters(compact('reload')));
225 if ($reload || (!($extensions = $this->extensions) && !($extensions = get_option(self::CACHE_OPTION_NAME, array())))) {
226 //Resting!
227 $this->file2Classmap = array();
228 $extensions = array();
229 # Get all active plugins
230 $activePlugins = wp_get_active_and_valid_plugins();
231 # Get Network plugins
232 if (is_multisite()) {
233 $activePlugins = array_merge(wp_get_active_network_plugins(), $activePlugins);
234 }
235 // filter all installed Plugins to fetch all out Extensions!
236 $activePlugins = $this->ongetactiveplugins($activePlugins);
237 foreach ($activePlugins as $file) {
238 $pluginDir = dirname($file);
239 $pluginName = basename($pluginDir);
240 // Any plugin with our prefix is a CJT extension!
241 if ( ( strpos( $pluginName, $this->prefix[0] ) === 0 ) ||
242 ( strpos( $pluginName, $this->prefix[1] ) === 0 ) ) {
243 // CJT Extsnsion must has the definition XML file!
244 // First try for Edition-Specific file
245 // if not exists try the generic one.
246 $xmlFile = "{$pluginDir}/{$pluginName}.xml";
247 if (file_exists($xmlFile)) {
248 // Get Plugin primary data!
249 $extension = array();
250 $extension['pluginFile'] = $file;
251 $extension['file'] = basename($file);
252 $extension['defFile'] = basename($pluginDir) . DIRECTORY_SEPARATOR . basename($xmlFile);
253 // Its useful to use ABS path only at runtime as it might changed as host might get moved.
254 $extension['dir'] = basename($pluginDir);
255 $extension['name'] = $pluginName;
256 // Cache XML file.
257 $extension['definition']['raw'] = file_get_contents($xmlFile);
258 // Filer!
259 $extension = $this->ondetectextension($extension);
260 // Read Basic XML Definition!
261 $definitionXML = $this->onloaddefinition(new SimpleXMLElement($extension['definition']['raw']));
262 $attrs = $definitionXML->attributes();
263 $extension['defDoc'] = $definitionXML;
264 $extension['definition']['primary']['loadMethod'] = (string) $attrs->loadMethod;
265 $extension['definition']['primary']['requiredLicense'] = (string) $definitionXML->license;
266 $className = ((string) $attrs->class);
267 // Add to list!
268 $extensions[$className] = $extension;
269 // Map Plugin FILE-2-CLASS name!
270 $this->file2Classmap["{$extension['dir']}/{$extension['file']}"] = $className;
271 }
272 }
273 }
274 }
275 $this->extensions = $this->onload($extensions);
276 // Chaining
277 return $this->extensions;
278 }
279
280 /**
281 * put your comment there...
282 *
283 */
284 public function load() {
285
286 // Initialize.
287 $frameworkVersion = new CJT_Framework_Version_Version(CJTPlugin::FW_Version);
288
289 // Auto load CJT extensions files when requested.
290 spl_autoload_register($this->ontregisterautoload(array($this, '_autoload')));
291
292 // Load all CJT extensions!
293 foreach ($this->getExtensions() as $class => $extension) {
294 // Filters!
295 extract($this->onload($extension, compact('class', 'extension')));
296 // Build Extension plugin path
297 $pluginPath = ABSPATH . PLUGINDIR . "/{$extension['name']}";
298 // Set runtime variables.
299 $this->extensions[$class]['runtime']['classFile'] = "{$pluginPath}/{$extension['name']}.class.php";
300 // Load definition.
301 $definitionXML = $extension['defDoc'];
302 // Extensions below version 1.0 use static classes
303 // while version 1.0 and up use objects
304 if (((string) $definitionXML->attributes()->version) == '1.0') {
305 // Instantiate extension object
306 $extensionObject = new $class($extension);
307 // Hold extension object
308 $extension['exObject'] = $extensionObject;
309 // Obejct callback
310 $callback = array($extensionObject, $this->loadMethod);
311 }
312 else {
313 # Static callback
314 $callback = array($class, $this->loadMethod);
315 }
316 // Callback filter
317 $callback = $this->onloadcallback($callback);
318 // If auto load is speicifd then import class file and bind events.
319 if ($extension['definition']['primary']['loadMethod'] == 'auto') {
320
321 // Don't load Incompatible extensions/addons
322 if (isset($this->incompatibleAddons[$extension['name']])) {
323
324 require_once ABSPATH . DIRECTORY_SEPARATOR . 'wp-admin' .
325 DIRECTORY_SEPARATOR . 'includes' .
326 DIRECTORY_SEPARATOR . 'plugin.php';
327
328 $incomapatibleAddon = $this->incompatibleAddons[$extension['name']];
329 $addonVersion = get_plugin_data($extension['pluginFile'], false, false)['Version'];
330 $currentVersion = get_plugin_data( CJTOOLBOX_PLUGIN_FILE )['Version'];
331
332 if (version_compare($addonVersion,
333 $currentVersion,
334 $incomapatibleAddon[1])) {
335
336 $extension['incompatibleMessage']['flag'] = $incomapatibleAddon[2];
337 $extension['incompatibleMessage']['msg'] = $incomapatibleAddon[3];
338
339 $this->incompatibilies[$pluginPath] = $extension;
340
341 continue;
342 }
343
344 }
345
346 // If frameworkVersion is not provided assume its 0 (Older version)
347 // before frameworkversion chech even supported.
348 // otherwise compare it with current frameworkversion
349 // If the version MAJOR is different current
350 // then its incompatible.
351 $extensionVer = new CJT_Framework_Version_Version((int) ((string) $definitionXML->attributes()->requireFrameworkVersion));
352 if ($frameworkVersion->getMajor() < $extensionVer->getMajor()) {
353 // Detects which requird updates CJT or the Extension itself.
354 $extension['incompatibleMessage']['msg'] = cssJSToolbox::getText('Extension is required CJT Framework Version higher than currently installed, CJT need to get updated!!!');
355 $extension['incompatibleMessage']['flag'] = cssJSToolbox::getText('Aborted');
356 // Add to incomaptibility list.
357 $this->incompatibilies[$pluginPath] = $extension;
358 }
359 else {
360 # Detect extensions required old Framework
361 if ($frameworkVersion->getMajor() > $extensionVer->getMajor()) {
362 $extension['incompatibleMessage']['msg'] = cssJSToolbox::getText('Extension is required old CJT Framework Version than the installed. This extension might need to get update. Please check if this extension is currently behaving correctly!!!');
363 $extension['incompatibleMessage']['flag'] = cssJSToolbox::getText('Ignored');
364 // Add to incomaptibility list.
365 $this->incompatibilies[$pluginPath] = $extension;
366 }
367 // Bind events for compatible extensions.
368 foreach ($definitionXML->getInvolved->event as $event) {
369 // filter!
370 extract($this->onbindevent(compact('event', 'callback')));
371 // Bind!
372 CJTPlugin::on((string) $event->attributes()->type, $callback);
373 }
374 }
375 }
376 else { // If manual load specified just
377 if (class_exists($class)) { // Make sure the class is loaded!
378 $this->onloaded($class, $extension, $definitionXML, call_user_func($callback));
379 }
380 }
381 }
382 if (!empty($this->incompatibilies)) {
383 // Hook for processing incomaptible extensions.
384 add_action('admin_notices', array(& $this, 'processIncompatibles'));
385 }
386 }
387
388 /**
389 * put your comment there...
390 *
391 * @param mixed $pluginName
392 */
393 public function & getDefDoc($pluginName) {
394 # Find if cached or create it
395 if (!isset($this->defDocs[$pluginName])) {
396 // Add CJT Def doc to def docs list
397 $pluginXMLFile = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $pluginName . DIRECTORY_SEPARATOR . "{$pluginName}.xml";
398 // Extension might removed while its license key still in the database
399 // Make sure the extension still exists
400 if (file_exists($pluginXMLFile)) {
401 $this->defDocs[$pluginName] = new SimpleXMLElement(file_get_contents($pluginXMLFile));
402 }
403 else {
404 # Return null when extension is absent!
405 $this->defDocs[$pluginName] = null;
406 }
407 }
408 return $this->defDocs[$pluginName];
409 }
410
411 /**
412 * put your comment there...
413 *
414 */
415 public function & getFiles2ClassesMap() {
416 return $this->file2Classmap;
417 }
418
419 /**
420 * put your comment there...
421 *
422 * @TODO: REMOVE HTML-MARKUP. CJT PLUGIN NEVER WRITE MARKUP IMIXED WITH HTML. ITS VERY BAD PROGRAMMING PRACTICE. THIS WILL BE REMOVED NEXT TIME AS WE IN RUSH!!!
423 */
424 public function processIncompatibles() {
425 global $current_screen;
426
427 // Proces only if in CJT page.
428 if (!preg_match('/\/plugins\.php|page\=cjtoolbox/', $_SERVER['REQUEST_URI'])) {
429 return;
430 }
431 // INitialize.
432 $message = cssJSToolbox::getText('CJT detects incompatible installed extensions, listed below with status message for every extension:');
433 $list = '';
434 // For every compatible extension add
435 // an list item with details
436 // if there is an update available or provide
437 // a direct link to CJT website if no upgrade is available.
438 // Upgrade wont be available in case no license key is activated!
439 foreach ($this->incompatibilies as $class => $extension) {
440 // Show details.
441 $pluginInfo = get_plugin_data($extension['pluginFile']);
442 // List item Markup
443 $list .= is_callable($extension['incompatibleMessage']['msg']) ?
444 "<li style='list-style-type:none'>{$extension['incompatibleMessage']['msg']()}</li>" :
445 "<li><a target='_blank' href='{$pluginInfo['PluginURI']}'>{$pluginInfo['Name']}</a> (Status: {$extension['incompatibleMessage']['flag']}, Message: {$extension['incompatibleMessage']['msg']})</li>\n";
446 }
447
448 $noticeClasses = 'cjt-incomaptible-extensions-notice notice notice-error';
449
450 if ( $current_screen->id !== 'toplevel_page_cjtoolbox' ) {
451 $noticeClasses .= ' is-dismissible';
452 }
453
454 // Output full message.
455 // TODO: BAD PRACTICE1!!!!! NEVER MIX HTML WITH PHP, JUST TEMPORARY1!!!
456 echo "<div class='$noticeClasses' style='font-size:14px;font-weight:bold;margin-top: 20px;'>
457 <ul style='list-style-type: circle;font-size: 12px;'>{$list}</ul>
458 </div>";
459 }
460
461 } // End class.
462
463
464 // Hookable!
465 CJTExtensions::define('CJTExtensions', array('hookType' => CJTWordpressEvents::HOOK_FILTER));