PluginProbe
CSS & JavaScript Toolbox / 6.1.1
CSS & JavaScript Toolbox v6.1.1
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 / controllers / blocks-coupling.php

blocks-coupling.php in CSS & JavaScript Toolbox 6.1.1, at controllers/blocks-coupling.php

527 lines 14.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @version $ Id; blocks-coupling.php 21-03-2012 03:22:10 Ahmed Said $
4 */
5
6 // Disallow direct access.
7 defined('ABSPATH') or die("Access denied");
8
9 /**
10 * Applying Code blocks for the curren request.
11 *
12 * This controller is always loaded.
13 *
14 * The class resposibility is to output the code blocks
15 * tha associated with current request.
16 *
17 * @author Ahmed Said
18 * @version 6
19 */
20 class CJTBlocksCouplingController extends CJTController {
21
22 /**
23 * put your comment there...
24 *
25 * @var mixed
26 */
27 protected $blocks = array(
28 'code' => array('header' => '', 'footer' => ''),
29 'scripts' => array('header' => array(), 'footer' => array()),
30 );
31
32 /**
33 * put your comment there...
34 *
35 * @var mixed
36 */
37 protected $controllerInfo = array('model' => 'coupling');
38
39 /**
40 * put your comment there...
41 *
42 * @var mixed
43 */
44 protected $filters = null;
45
46 /**
47 * put your comment there...
48 *
49 * @var mixed
50 */
51 protected $hasRun = false;
52
53 /**
54 * put your comment there...
55 *
56 * @var mixed
57 */
58 protected static $instance = null;
59
60 /**
61 * put your comment there...
62 *
63 * @var mixed
64 */
65 private $onActionIds = array();
66
67 /**
68 * put your comment there...
69 *
70 * @var mixed
71 */
72 protected $onassigncouplingcallback = array('parameters' => array('callback'));
73
74 /**
75 * put your comment there...
76 *
77 * @var mixed
78 */
79 protected $onappendcode = array('parameters' => array('code'));
80
81 /**
82 * put your comment there...
83 *
84 * @var mixed
85 */
86 protected $oncancelmatching = array('parameters' => array('matched'));
87
88 /**
89 * put your comment there...
90 *
91 * @var mixed
92 */
93 protected $ondefaultfilters = array('parameters' => array('filters'));
94
95 /**
96 * put your comment there...
97 *
98 * @var mixed
99 */
100 protected $ondo = array('parameters' => array('data', 'method', 'condition'));
101
102 /**
103 * put your comment there...
104 *
105 * @var mixed
106 */
107 protected $onblocksorder = array('parameters' => array('order'));
108
109 /**
110 * put your comment there...
111 *
112 * @var mixed
113 */
114 protected $ongetblocks = array('parameters' => array('blocks'));
115
116 /**
117 * put your comment there...
118 *
119 * @var mixed
120 */
121 protected $ongetcache = array('parameters' => array('cache'));
122
123 /**
124 * put your comment there...
125 *
126 * @var mixed
127 */
128 protected $ongetfilters = array('parameters' => array('filters'));
129
130 /**
131 * put your comment there...
132 *
133 * @var mixed
134 */
135 protected $onmatchingurls = array('parameters' => array('urls'));
136
137 /**
138 * put your comment there...
139 *
140 * @var mixed
141 */
142 protected $onnoblocks = array('hookType' => CJTWordpressEvents::HOOK_ACTION);
143
144 /**
145 * put your comment there...
146 *
147 * @var mixed
148 */
149 protected $onoutput = array('parameters' => array('code', 'location'));
150
151 /**
152 * put your comment there...
153 *
154 * @var mixed
155 */
156 protected $onprocess = array('hookType' => CJTWordpressEvents::HOOK_ACTION);
157
158 /**
159 * put your comment there...
160 *
161 * @var mixed
162 */
163 protected $onprocessblock = array('parameters' => array('block'));
164
165 /**
166 * put your comment there...
167 *
168 * @var mixed
169 */
170 protected $onsetfilters = array('parameters' => array('filters'));
171
172 /**
173 * Initialize controller object.
174 *
175 * @see CJTController for more details
176 * @return void
177 */
178 public function __construct() {
179 // Only one instance is allowed.
180 if (self::$instance) {
181 throw new Exception('Trying to instantiate multiple coupling instances!!');
182 }
183 // Hold the single instance we've!
184 self::$instance = $this;
185 // Initialize controller.
186 parent::__construct(false);
187 // Import related libraries
188 CJTModel::import('block');
189 // Not default action needed.
190 $this->defaultAction = null;
191 // Initialize controller.
192 $initCouplingCallback = $this->onassigncouplingcallback(array(&$this, 'initCoupling'));
193 add_action('admin_init', $initCouplingCallback);
194 add_action('wp', $initCouplingCallback);
195 // Add Shortcode callbacks.
196 add_shortcode('cjtoolbox', array(&$this, 'shortcode'));
197 }
198
199 /**
200 * put your comment there...
201 *
202 * @param mixed $id
203 */
204 public function addOnActionIds($id) {
205 // Add ID is not exists.
206 if (!in_array($id, $this->onActionIds)) {
207 $this->onActionIds[] = $id;
208 }
209 // Chaining.
210 return $this;
211 }
212
213 /**
214 * put your comment there...
215 *
216 */
217 public function getBlocks() {
218 // Set request view filters used for querying database.
219 $this->setRequestFilters();
220 // Get blocks order. NOTE: This is all blocks order not only the queried/target blocks.
221 $blocksOrder = array();
222 $metaBoxesOrder = $this->onblocksorder($this->model->getOrder());
223 // Get ORDER-INDEX <TO> BLOCK-ID mapping.
224 preg_match_all('/cjtoolbox-(\d+)/', $metaBoxesOrder['normal'], $blocksOrder, PREG_SET_ORDER);
225 // Prepare request URL to match against Links & Expressions.
226 $linksRequestURL = self::getRequestURL();
227 $expressionsRequestURL = "{$linksRequestURL}?{$_SERVER['QUERY_STRING']}";
228 extract($this->onmatchingurls(compact('linksRequestURL', 'expressionsRequestURL')));
229 // Get all blocks including (Links & Expressions Blocks).
230 $blocks = $this->ongetblocks($this->model->getPinsBlocks(CJTBlockModel::PINS_LINK_EXPRESSION,
231 $this->getFilters()->pinPoint,
232 $this->getFilters()->customPins));
233 if (empty($blocks)) {
234 $this->onnoblocks();
235 return false;
236 }
237 // Import related libraries.
238 cssJSToolbox::import('framework:php:evaluator:evaluator.inc.php');
239 /**
240 * Iterator over all blocks by using they order.
241 * For each block get code and scripts.
242 */
243 $this->onprocess();
244 foreach ($blocksOrder as $blockOrder) {
245 $blockId = (int) $blockOrder[1];
246 // As mentioned above. Orders is for all blocks not just those queried from db.
247 if (isset($blocks[$blockId])) {
248 $block = $this->onprocessblock($blocks[$blockId]);
249 /**
250 * Process Links & Expressions blocks.
251 * For better performace check only those with links and expressions flags.
252 */
253 if ($block->blocksGroup & CJTBlockModel::PINS_LINK_EXPRESSION) {
254 /**
255 * Initiliaze $matchedLink and $matchedExpression inside IF statment.
256 * Those variables need to refresh state at each block.
257 * If there is no link or expression flags, they will be FALSE.
258 * Otherwise they'll get the correct value inside each statement.
259 */
260 /// Check if there is a matched link.
261 if ($matchedLink = ($block->blocksGroup & CJTBlockModel::PINS_LINKS)) {
262 $links = explode("\n", trim($block->links));
263 $matchedLink = in_array($linksRequestURL, $links);
264 }
265 /// Check if there is a matched expression.
266 if ($matchedExpression = ($block->blocksGroup & CJTBlockModel::PINS_EXPRESSIONS)) {
267 $expressions = explode("\n", $block->expressions);
268 foreach ($expressions as $expression) {
269 /// @TODO: Matches may be used later to evaulate variables inside code block.
270 if($matchedExpression = @preg_match("/{$expression}/", $expressionsRequestURL)) {
271 break;
272 }
273 }
274 }
275 /**
276 * Exclude Links & Expressions Blocks that doesn't has a match.
277 * If there is no matched link or expression then exclude block.
278 */
279 if ($this->oncancelmatching(!($matchedExpression || $matchedLink))) {
280 continue;
281 }
282 }
283 // For every location store blocks code into single string
284 $evaluatedCode = CJTPHPCodeEvaluator::getInstance($block)->exec()->getOutput();
285 /** @todo Include Debuging info only if we're in debuging mode! */
286 if (1) {
287 $evaluatedCode = "\n<!-- Block ({$blockId}) START-->\n{$evaluatedCode}\n<!-- Block ({$blockId}) END -->\n";
288 }
289 $this->blocks['code'][$block->location] .= $this->onappendcode($evaluatedCode);
290 // Store all used Ids in the CORRECT ORDER.
291 $this->addOnActionIds($blockId);
292 }
293 }
294 // Return true if there is at least 1 block return within the set.
295 return true;
296 }
297
298 /**
299 * put your comment there...
300 *
301 */
302 public function getCached() {
303 // Cache is not implemented yet might be supported by extenal Extensions!
304 return $this->ongetcache(false);
305 }
306
307 /**
308 * put your comment there...
309 *
310 */
311 public function getFilters() {
312 return $this->ongetfilters($this->filters);
313 }
314
315 /**
316 * put your comment there...
317 *
318 */
319 public function getOnActionIds() {
320 return $this->onActionIds;
321 }
322
323 /**
324 * put your comment there...
325 *
326 */
327 public static function getRequestURL() {
328 // URL Protocol.
329 $protocol = 'http' . ((isset($_SERVER["HTTPS"]) && ($_SERVER["HTTPS"] == "on")) ? 's' : '') . '://';
330 // Host name & port.
331 $host = $_SERVER['HTTP_HOST'];
332 $port = ($_SERVER["SERVER_PORT"] != "80") ? ":{$_SERVER["SERVER_PORT"]}" : '';
333 // Request URI.
334 $requestURI = $_SERVER['REQUEST_URI'];
335 // Final URL.
336 $url = "{$protocol}{$host}{$port}{$requestURI}";
337 return $url;
338 }
339
340 /**
341 * put your comment there...
342 *
343 */
344 public function hasOnActionIds() {
345 return !empty($this->onActionIds);
346 }
347
348 /**
349 * put your comment there...
350 *
351 */
352 public function initCoupling() {
353 // For some reasons wp action is fired twice.
354 // The wrong call won't has $wp_query object set,
355 // but this is only valid at Front end.
356 if (!is_admin() && !$GLOBALS['wp_query']) {
357 return;
358 }
359 // Don't run twice!
360 if (!$this->hasRun) {
361 // Stop running it again!
362 $this->hasRun = true;
363 // Get cache or get blocks if not cached.
364 // If there is no cache or no blocks for output
365 // do nothing.
366 if ($this->getCached() || $this->getBlocks()) {
367 $actionsPrefix = is_admin() ? 'admin' : 'wp';
368 // Output blocks on various locations!
369 add_action("{$actionsPrefix}_head", array(&$this, 'outputBlocks'), 30);
370 add_action("{$actionsPrefix}_footer", array(&$this, 'outputBlocks'), 30);
371 }
372 }
373 }
374
375 /**
376 * put your comment there...
377 *
378 */
379 public function outputBlocks() {
380 // Derived location name from wordpress filter name.
381 $currentFilter = current_filter();
382 // Map "wp hook location" to "block hook location".
383 $locationsMap = array('head' => 'header', 'footer' => 'footer');
384 // This hook is used across both ends, front and back ends.
385 // Remove application prefix (wp_ or admin_).
386 // Remining is head or footer.
387 $location = str_replace(array('wp_', 'admin_'), '', $currentFilter);
388 // Map to block location.
389 $location = $locationsMap[$location];
390 echo $this->onoutput($this->blocks['code'][$location], $location);
391 }
392
393 /**
394 * put your comment there...
395 *
396 */
397 protected function setRequestFilters() {
398 // Get request blocks.
399 $filters = $this->ondefaultfilters((object) array(
400 'pinPoint' => 0x00000000,
401 'customPins' => array(),
402 ));
403 if (is_admin()) {
404 // Include all backend blocks.
405 $filters->pinPoint |= CJTBlockModel::PINS_BACKEND;
406 }
407 else {
408 $filters->pinPoint |= CJTBlockModel::PINS_FRONTEND;
409 // Pages.
410 if (is_page()) {
411 // Blocks with ALL PAGES selected.
412 $filters->pinPoint |= CJTBlockModel::PINS_PAGES_ALL_PAGES;
413 // Blocks with PAGE-ID selected.
414 $filters->customPins[] = array(
415 'pin' => 'pages',
416 'pins' => array($GLOBALS['post']->ID),
417 'flag' => CJTBlockModel::PINS_PAGES_CUSTOM_PAGE,
418 );
419 // Blocks with FRONT-PAGE selected.
420 if (is_front_page()) {
421 $filters->pinPoint |= CJTBlockModel::PINS_PAGES_FRONT_PAGE;
422 }
423 } // End is_page()
424 else if (is_attachment()) {
425 $filters->pinPoint |= CJTBlockModel::PINS_ATTACHMENT;
426 }
427 // Posts.
428 else if (is_single()) {
429 // Blocks with ALL POSTS & ALL CATEGORIES selected.
430 $filters->pinPoint |= CJTBlockModel::PINS_POSTS_ALL_POSTS | CJTBlockModel::PINS_CATEGORIES_ALL_CATEGORIES;
431 // Blocks with POST-ID selected.
432 $filters->customPins[] = array(
433 'pin' => 'posts',
434 'pins' => array($GLOBALS['post']->ID),
435 'flag' => CJTBlockModel::PINS_POSTS_CUSTOM_POST,
436 );
437 // Include POST PARENT CATRGORIES blocks.
438 $parentCategoriesIds = wp_get_post_categories($GLOBALS['post']->ID, array('fields' => 'ids'));
439 /**
440 * Custom-Posts just added "ON THE RUN/FLY"
441 * Need simple fix by confirming that the post is belong to
442 * specific category or not.
443 * Custom posts NOW unlike Posts, it doesn't inherit parent
444 * taxonomis Code Blocks!!
445 */
446 if (!empty($parentCategoriesIds)) {
447 $filters->customPins[] = array(
448 'pin' => 'categories',
449 'pins' => $parentCategoriesIds,
450 'flag' => CJTBlockModel::PINS_CATEGORIES_CUSTOM_CATEGORY,
451 );
452 }
453 /**
454 * @TODO check for recent posts Based on user configuration.
455 * Recent posts should be detcted by comparing
456 * user condifguration with post date.
457 */
458 if (0) {
459
460 }
461 } // End is_single()
462 // Categories.
463 else if(is_category()) {
464 // Blocks with ALL CATEGORIES selected.
465 $filters->pinPoint |= CJTBlockModel::PINS_CATEGORIES_ALL_CATEGORIES;
466 // Blocks with CATEGORY-ID selected.
467 $filters->customPins[] = array(
468 'pin' => 'categories',
469 'pins' => array(get_queried_object()->term_id),
470 'flag' => CJTBlockModel::PINS_CATEGORIES_CUSTOM_CATEGORY,
471 );
472 } // End is_category()
473 // Blocks with BLOG-INDEX selected.
474 else if (is_home()) {
475 $filters->pinPoint |= CJTBlockModel::PINS_POSTS_BLOG_INDEX;
476 }
477 else if (is_search()) {
478 $filters->pinPoint |= CJTBlockModel::PINS_SEARCH;
479 }
480 else if (is_tag()) {
481 $filters->pinPoint |= CJTBlockModel::PINS_TAG;
482 }
483 else if (is_author()) {
484 $filters->pinPoint |= CJTBlockModel::PINS_AUTHOR;
485 }
486 else if (is_archive()) {
487 $filters->pinPoint |= CJTBlockModel::PINS_ARCHIVE;
488 }
489 else if (is_404()) {
490 $filters->pinPoint |= CJTBlockModel::PINS_404_ERROR;
491 }
492 }
493 $this->filters = $this->onsetfilters($filters);
494 }
495
496 /**
497 * Wordpress do shortcode callback for
498 * CJT Shortcodes ([cjtoolbox ....])!
499 *
500 * This method role is to load the shortcode routines
501 * in order to handle the request.
502 *
503 * It doesn't do anything except deferring the shortcode
504 * codes from loaded until shortcode is really used!
505 *
506 * @param mixed $attributes
507 */
508 public function shortcode($attributes, $content) {
509 // Instantiate Shortcode handler class.
510 cssJSToolbox::import('controllers:coupling:shortcode:shortcode.php');
511 $shortcode = new CJT_Controllers_Coupling_Shortcode($attributes, $content);
512 // Return Shortcode replacement!
513 return ((string) $shortcode);
514 }
515
516 /**
517 * put your comment there...
518 *
519 */
520 public static function & theInstance() {
521 return self::$instance;
522 }
523
524 } // End class.
525
526 // Hookable!
527 CJTBlocksCouplingController::define('CJTBlocksCouplingController', array('hookType' => CJTWordpressEvents::HOOK_FILTER));