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

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