PluginProbe
CSS & JavaScript Toolbox / 6.1.2
CSS & JavaScript Toolbox v6.1.2
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.2, at controllers/blocks-coupling.php

528 lines 14.2 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 $siteHook = cssJSToolbox::$config->core->siteHook;
186 // Initialize controller.
187 parent::__construct(false);
188 // Import related libraries
189 CJTModel::import('block');
190 // Not default action needed.
191 $this->defaultAction = null;
192 // Initialize controller.
193 $initCouplingCallback = $this->onassigncouplingcallback(array(&$this, 'initCoupling'));
194 add_action('admin_init', $initCouplingCallback);
195 add_action($siteHook->tag, $initCouplingCallback, $siteHook->priority);
196 // Add Shortcode callbacks.
197 add_shortcode('cjtoolbox', array(&$this, 'shortcode'));
198 }
199
200 /**
201 * put your comment there...
202 *
203 * @param mixed $id
204 */
205 public function addOnActionIds($id) {
206 // Add ID is not exists.
207 if (!in_array($id, $this->onActionIds)) {
208 $this->onActionIds[] = $id;
209 }
210 // Chaining.
211 return $this;
212 }
213
214 /**
215 * put your comment there...
216 *
217 */
218 public function getBlocks() {
219 // Set request view filters used for querying database.
220 $this->setRequestFilters();
221 // Get blocks order. NOTE: This is all blocks order not only the queried/target blocks.
222 $blocksOrder = array();
223 $metaBoxesOrder = $this->onblocksorder($this->model->getOrder());
224 // Get ORDER-INDEX <TO> BLOCK-ID mapping.
225 preg_match_all('/cjtoolbox-(\d+)/', $metaBoxesOrder['normal'], $blocksOrder, PREG_SET_ORDER);
226 // Prepare request URL to match against Links & Expressions.
227 $linksRequestURL = self::getRequestURL();
228 $expressionsRequestURL = "{$linksRequestURL}?{$_SERVER['QUERY_STRING']}";
229 extract($this->onmatchingurls(compact('linksRequestURL', 'expressionsRequestURL')));
230 // Get all blocks including (Links & Expressions Blocks).
231 $blocks = $this->ongetblocks($this->model->getPinsBlocks(CJTBlockModel::PINS_LINK_EXPRESSION,
232 $this->getFilters()->pinPoint,
233 $this->getFilters()->customPins));
234 if (empty($blocks)) {
235 $this->onnoblocks();
236 return false;
237 }
238 // Import related libraries.
239 cssJSToolbox::import('framework:php:evaluator:evaluator.inc.php');
240 /**
241 * Iterator over all blocks by using they order.
242 * For each block get code and scripts.
243 */
244 $this->onprocess();
245 foreach ($blocksOrder as $blockOrder) {
246 $blockId = (int) $blockOrder[1];
247 // As mentioned above. Orders is for all blocks not just those queried from db.
248 if (isset($blocks[$blockId])) {
249 $block = $this->onprocessblock($blocks[$blockId]);
250 /**
251 * Process Links & Expressions blocks.
252 * For better performace check only those with links and expressions flags.
253 */
254 if ($block->blocksGroup & CJTBlockModel::PINS_LINK_EXPRESSION) {
255 /**
256 * Initiliaze $matchedLink and $matchedExpression inside IF statment.
257 * Those variables need to refresh state at each block.
258 * If there is no link or expression flags, they will be FALSE.
259 * Otherwise they'll get the correct value inside each statement.
260 */
261 /// Check if there is a matched link.
262 if ($matchedLink = ($block->blocksGroup & CJTBlockModel::PINS_LINKS)) {
263 $links = explode("\n", trim($block->links));
264 $matchedLink = in_array($linksRequestURL, $links);
265 }
266 /// Check if there is a matched expression.
267 if ($matchedExpression = ($block->blocksGroup & CJTBlockModel::PINS_EXPRESSIONS)) {
268 $expressions = explode("\n", $block->expressions);
269 foreach ($expressions as $expression) {
270 /// @TODO: Matches may be used later to evaulate variables inside code block.
271 if($matchedExpression = @preg_match("/{$expression}/", $expressionsRequestURL)) {
272 break;
273 }
274 }
275 }
276 /**
277 * Exclude Links & Expressions Blocks that doesn't has a match.
278 * If there is no matched link or expression then exclude block.
279 */
280 if ($this->oncancelmatching(!($matchedExpression || $matchedLink))) {
281 continue;
282 }
283 }
284 // For every location store blocks code into single string
285 $evaluatedCode = CJTPHPCodeEvaluator::getInstance($block)->exec()->getOutput();
286 /** @todo Include Debuging info only if we're in debuging mode! */
287 if (1) {
288 $evaluatedCode = "\n<!-- Block ({$blockId}) START-->\n{$evaluatedCode}\n<!-- Block ({$blockId}) END -->\n";
289 }
290 $this->blocks['code'][$block->location] .= $this->onappendcode($evaluatedCode);
291 // Store all used Ids in the CORRECT ORDER.
292 $this->addOnActionIds($blockId);
293 }
294 }
295 // Return true if there is at least 1 block return within the set.
296 return true;
297 }
298
299 /**
300 * put your comment there...
301 *
302 */
303 public function getCached() {
304 // Cache is not implemented yet might be supported by extenal Extensions!
305 return $this->ongetcache(false);
306 }
307
308 /**
309 * put your comment there...
310 *
311 */
312 public function getFilters() {
313 return $this->ongetfilters($this->filters);
314 }
315
316 /**
317 * put your comment there...
318 *
319 */
320 public function getOnActionIds() {
321 return $this->onActionIds;
322 }
323
324 /**
325 * put your comment there...
326 *
327 */
328 public static function getRequestURL() {
329 // URL Protocol.
330 $protocol = 'http' . ((isset($_SERVER["HTTPS"]) && ($_SERVER["HTTPS"] == "on")) ? 's' : '') . '://';
331 // Host name & port.
332 $host = $_SERVER['HTTP_HOST'];
333 $port = ($_SERVER["SERVER_PORT"] != "80") ? ":{$_SERVER["SERVER_PORT"]}" : '';
334 // Request URI.
335 $requestURI = $_SERVER['REQUEST_URI'];
336 // Final URL.
337 $url = "{$protocol}{$host}{$port}{$requestURI}";
338 return $url;
339 }
340
341 /**
342 * put your comment there...
343 *
344 */
345 public function hasOnActionIds() {
346 return !empty($this->onActionIds);
347 }
348
349 /**
350 * put your comment there...
351 *
352 */
353 public function initCoupling() {
354 // For some reasons wp action is fired twice.
355 // The wrong call won't has $wp_query object set,
356 // but this is only valid at Front end.
357 if (!is_admin() && !$GLOBALS['wp_query']) {
358 return;
359 }
360 // Don't run twice!
361 if (!$this->hasRun) {
362 // Stop running it again!
363 $this->hasRun = true;
364 // Get cache or get blocks if not cached.
365 // If there is no cache or no blocks for output
366 // do nothing.
367 if ($this->getCached() || $this->getBlocks()) {
368 $actionsPrefix = is_admin() ? 'admin' : 'wp';
369 // Output blocks on various locations!
370 add_action("{$actionsPrefix}_head", array(&$this, 'outputBlocks'), 30);
371 add_action("{$actionsPrefix}_footer", array(&$this, 'outputBlocks'), 30);
372 }
373 }
374 }
375
376 /**
377 * put your comment there...
378 *
379 */
380 public function outputBlocks() {
381 // Derived location name from wordpress filter name.
382 $currentFilter = current_filter();
383 // Map "wp hook location" to "block hook location".
384 $locationsMap = array('head' => 'header', 'footer' => 'footer');
385 // This hook is used across both ends, front and back ends.
386 // Remove application prefix (wp_ or admin_).
387 // Remining is head or footer.
388 $location = str_replace(array('wp_', 'admin_'), '', $currentFilter);
389 // Map to block location.
390 $location = $locationsMap[$location];
391 echo $this->onoutput($this->blocks['code'][$location], $location);
392 }
393
394 /**
395 * put your comment there...
396 *
397 */
398 protected function setRequestFilters() {
399 // Get request blocks.
400 $filters = $this->ondefaultfilters((object) array(
401 'pinPoint' => 0x00000000,
402 'customPins' => array(),
403 ));
404 if (is_admin()) {
405 // Include all backend blocks.
406 $filters->pinPoint |= CJTBlockModel::PINS_BACKEND;
407 }
408 else {
409 $filters->pinPoint |= CJTBlockModel::PINS_FRONTEND;
410 // Pages.
411 if (is_page()) {
412 // Blocks with ALL PAGES selected.
413 $filters->pinPoint |= CJTBlockModel::PINS_PAGES_ALL_PAGES;
414 // Blocks with PAGE-ID selected.
415 $filters->customPins[] = array(
416 'pin' => 'pages',
417 'pins' => array($GLOBALS['post']->ID),
418 'flag' => CJTBlockModel::PINS_PAGES_CUSTOM_PAGE,
419 );
420 // Blocks with FRONT-PAGE selected.
421 if (is_front_page()) {
422 $filters->pinPoint |= CJTBlockModel::PINS_PAGES_FRONT_PAGE;
423 }
424 } // End is_page()
425 else if (is_attachment()) {
426 $filters->pinPoint |= CJTBlockModel::PINS_ATTACHMENT;
427 }
428 // Posts.
429 else if (is_single()) {
430 // Blocks with ALL POSTS & ALL CATEGORIES selected.
431 $filters->pinPoint |= CJTBlockModel::PINS_POSTS_ALL_POSTS | CJTBlockModel::PINS_CATEGORIES_ALL_CATEGORIES;
432 // Blocks with POST-ID selected.
433 $filters->customPins[] = array(
434 'pin' => 'posts',
435 'pins' => array($GLOBALS['post']->ID),
436 'flag' => CJTBlockModel::PINS_POSTS_CUSTOM_POST,
437 );
438 // Include POST PARENT CATRGORIES blocks.
439 $parentCategoriesIds = wp_get_post_categories($GLOBALS['post']->ID, array('fields' => 'ids'));
440 /**
441 * Custom-Posts just added "ON THE RUN/FLY"
442 * Need simple fix by confirming that the post is belong to
443 * specific category or not.
444 * Custom posts NOW unlike Posts, it doesn't inherit parent
445 * taxonomis Code Blocks!!
446 */
447 if (!empty($parentCategoriesIds)) {
448 $filters->customPins[] = array(
449 'pin' => 'categories',
450 'pins' => $parentCategoriesIds,
451 'flag' => CJTBlockModel::PINS_CATEGORIES_CUSTOM_CATEGORY,
452 );
453 }
454 /**
455 * @TODO check for recent posts Based on user configuration.
456 * Recent posts should be detcted by comparing
457 * user condifguration with post date.
458 */
459 if (0) {
460
461 }
462 } // End is_single()
463 // Categories.
464 else if(is_category()) {
465 // Blocks with ALL CATEGORIES selected.
466 $filters->pinPoint |= CJTBlockModel::PINS_CATEGORIES_ALL_CATEGORIES;
467 // Blocks with CATEGORY-ID selected.
468 $filters->customPins[] = array(
469 'pin' => 'categories',
470 'pins' => array(get_queried_object()->term_id),
471 'flag' => CJTBlockModel::PINS_CATEGORIES_CUSTOM_CATEGORY,
472 );
473 } // End is_category()
474 // Blocks with BLOG-INDEX selected.
475 else if (is_home()) {
476 $filters->pinPoint |= CJTBlockModel::PINS_POSTS_BLOG_INDEX;
477 }
478 else if (is_search()) {
479 $filters->pinPoint |= CJTBlockModel::PINS_SEARCH;
480 }
481 else if (is_tag()) {
482 $filters->pinPoint |= CJTBlockModel::PINS_TAG;
483 }
484 else if (is_author()) {
485 $filters->pinPoint |= CJTBlockModel::PINS_AUTHOR;
486 }
487 else if (is_archive()) {
488 $filters->pinPoint |= CJTBlockModel::PINS_ARCHIVE;
489 }
490 else if (is_404()) {
491 $filters->pinPoint |= CJTBlockModel::PINS_404_ERROR;
492 }
493 }
494 $this->filters = $this->onsetfilters($filters);
495 }
496
497 /**
498 * Wordpress do shortcode callback for
499 * CJT Shortcodes ([cjtoolbox ....])!
500 *
501 * This method role is to load the shortcode routines
502 * in order to handle the request.
503 *
504 * It doesn't do anything except deferring the shortcode
505 * codes from loaded until shortcode is really used!
506 *
507 * @param mixed $attributes
508 */
509 public function shortcode($attributes, $content) {
510 // Instantiate Shortcode handler class.
511 cssJSToolbox::import('controllers:coupling:shortcode:shortcode.php');
512 $shortcode = new CJT_Controllers_Coupling_Shortcode($attributes, $content);
513 // Return Shortcode replacement!
514 return ((string) $shortcode);
515 }
516
517 /**
518 * put your comment there...
519 *
520 */
521 public static function & theInstance() {
522 return self::$instance;
523 }
524
525 } // End class.
526
527 // Hookable!
528 CJTBlocksCouplingController::define('CJTBlocksCouplingController', array('hookType' => CJTWordpressEvents::HOOK_FILTER));