PluginProbe
CSS & JavaScript Toolbox / 0.8
CSS & JavaScript Toolbox v0.8
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 / css-js-toolbox.php

css-js-toolbox.php in CSS & JavaScript Toolbox 0.8, at css-js-toolbox.php

1,106 lines 35.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: CSS & JavaScript Toolbox
4 Plugin URI: http://wipeoutmedia.com/wordpress-plugins/css-javascript-toolbox
5 Description: WordPress plugin to easily add custom CSS and JavaScript to individual pages
6 Version: 0.8
7 Author: Wipeout Media
8 Author URI: http://wipeoutmedia.com/wordpress-plugins/css-javascript-toolbox
9
10 Copyright (c) 2011, Wipeout Media.
11
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 as published by the Free Software Foundation; either version 2
15 of the License, or (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 */
26
27
28 /**
29 * Avoid direct calls to this file where wp core files not present
30 */
31 if (!function_exists ('add_action')) {
32 header('Status: 403 Forbidden');
33 header('HTTP/1.1 403 Forbidden');
34 exit();
35 }
36
37 /**
38 * CJT info.
39 */
40 define('CJTOOLBOX_VERSION', '0.3');
41 define('CJTOOLBOX_NAME', plugin_basename(dirname(__FILE__)));
42 define('CJTOOLBOX_TEXT_DOMAIN', CJTOOLBOX_NAME);
43 define('CJTOOLBOX_DEBUG', FALSE);
44
45 /**
46 * CJT Paths.
47 */
48 define('CJTOOLBOX_PATH', dirname(__FILE__));
49 define('CJTOOLBOX_INCLUDE_PATH', CJTOOLBOX_PATH . '/includes');
50 define('CJTOOLBOX_VIEWS_PATH', CJTOOLBOX_PATH . '/views');
51 define('CJTOOLBOX_VIEWS_SNIPPETS_PATH', CJTOOLBOX_PATH . '/views/snippets');
52
53 /**
54 * CJT URLs.
55 */
56 define('CJTOOLBOX_URL', WP_PLUGIN_URL . '/' . CJTOOLBOX_NAME );
57 define('CJTOOLBOX_MEDIA_URL', CJTOOLBOX_URL . '/public/media');
58 define('CJTOOLBOX_CSS_URL', CJTOOLBOX_URL . '/public/css');
59 define('CJTOOLBOX_JS_URL', CJTOOLBOX_URL . '/public/js');
60
61 /**
62 * Wordpress option name Prefix for modules list cache.
63 *
64 * The directory name will be added to the option name,
65 * so each modules directory has different cached list.
66 */
67 define('MODULES_LIST_CACHE_VAR_PREFIX', 'cjt_modules_list');
68
69 if (!class_exists('cssJSToolbox')) {
70 /**
71 * CJT class.
72 */
73 class cssJSToolbox {
74 /**
75 * WOrdpress option name.
76 */
77 const BLOCKS_OPTION_NAME = 'cjtoolbox_data';
78
79 /**
80 * URL to check for premium update.
81 */
82 const CHECK_UPDATE_URL = 'http://wipeoutmedia.com/wp-admin/admin-ajax.php?action=cjts_dispatcher&procedure=Updates.getLatestPremiumVersion';
83
84 /**
85 * Version option name.
86 */
87 const DATABASE_VERSION_OPTION_NAME = 'cjtoolbox_db_version';
88
89 /**
90 * Dir for uploaded images.
91 */
92 const IMAGES_UPLOAD_DIR = 'upload';
93
94 /**
95 * Additional scripts directory name.
96 */
97 const ADDITIONAL_SCRIPTS_DIR = 'upload';
98
99 /**
100 * Blocks used to output the code for
101 * the current request.
102 *
103 * @see cssJSToolbox::setTargetBlocks.
104 *
105 * @var array|null
106 */
107 var $blocks = null;
108
109 /**
110 * Security nonce used in the blocks page.
111 *
112 * @var string
113 */
114 var $security_nonce = null;
115
116 /**
117 * CJT options.
118 *
119 * @var array
120 */
121 var $settings = array();
122
123 /**
124 * CSS?JS Blocks data.
125 *
126 * @var array
127 */
128 var $cjdata = array();
129
130 /**
131 * Note: self::$instance is used in all HOOKS callbacks instead of $this.
132 * This allow other modules to override the methods of this class.
133 *
134 * Allow only single instance.
135 *
136 * @var mixed
137 */
138 public static $instance = null;
139
140 /**
141 * Modules engine object.
142 *
143 * @var CJTModulesEngine
144 */
145 public static $modulesEngine = null;
146
147 /**
148 * Premium upgrade response trasient.
149 *
150 * @var array
151 */
152 public static $premiumUpgradeTransient = null;
153
154 /**
155 * Initialize Plugin.
156 *
157 * @return void
158 */
159 protected function __construct() {
160 // Set hooks pointer.
161 self::$instance = $this;
162 // Process/Load attached modules.
163 if (is_admin()) {
164 $this->processSDModules();
165 }
166 // Start this plugin once all other plugins are fully loaded.
167 add_action('plugins_loaded', array(&self::$instance, 'start_plugin'));
168 // Activation & Deactivbation.
169 register_activation_hook(__FILE__, array(&self::$instance, 'activate_plugin'));
170 register_deactivation_hook(__FILE__, array(&self::$instance, 'deactivate_plugin'));
171 }
172
173 /**
174 * Clean up single block data before saving to database.
175 *
176 * @param array Block data.
177 * @return array Cleaned block data.
178 */
179 protected function cleanSingleBlock($block) {
180 $fieldsToClean = array(
181 'code',
182 'links',
183 );
184 // New lines submitted to server as CRLF but displayed in browser as LF.
185 // PHP script and JS work on two different versions of texts.
186 // Replace CRLF with LF just as displayed in browsers.
187 foreach ($fieldsToClean as $field) {
188 $block[$field] = preg_replace("/\x0D\x0A/", "\x0A", $block[$field]);
189 }
190 return $block;
191 }
192
193 /**
194 * Get CJT Plugin object.
195 *
196 * @return cssJSToolbox.
197 */
198 public static function getInstance() {
199 if (!self::$instance) {
200 $instance = new cssJSToolbox();
201 }
202 return self::$instance;
203 }
204
205 /**
206 * Process CJT Self delete modules only if there is modules
207 * available.
208 *
209 * Note: Modules can deleted them self after a while.
210 *
211 * The main concern is to avoid
212 * CJTModulesEngine or any other modules
213 * is resposible for setting cjt_process_modules value.
214 *
215 * @return void.
216 */
217 private function processSDModules() {
218 $modulesDirectory = 'modules';
219 $modulesListOptionName = MODULES_LIST_CACHE_VAR_PREFIX . "-{$modulesDirectory}";
220 $processModules = get_option($modulesListOptionName);
221 // IF processmodules is not array it means that this is the first time to run after
222 // the plugin installed and no list cached list, so give the modules engine the chance to collect the data.
223 // IF processModules is array but empty it means that modules deleted themself
224 // and no more modules to process.
225 if (!is_array($processModules) || (is_array($processModules) && (!empty($processModules)))) {
226 // Process/Load modules.
227 require_once CJTOOLBOX_INCLUDE_PATH . '/modules.inc.php';
228 require_once CJTOOLBOX_INCLUDE_PATH . '/modulebase.inc.php';
229 self::$modulesEngine = CJTModulesEngine::getInstance($modulesDirectory);
230 self::$modulesEngine->processAll();
231 }
232 }
233
234 /**
235 * Save blocks data to database.
236 *
237 * @param array Save blocks parameters if provided.
238 * @return void
239 */
240 function saveData($blocks = null) {
241 $blocks = isset($blocks) ? $blocks : $this->cjdata;
242 update_option(self::BLOCKS_OPTION_NAME, $blocks);
243 }
244
245 /**
246 * Read blocks data from the database.
247 *
248 * @return array Blocks data array.
249 */
250 function getData() {
251 $cjdata = (array) get_option(self::BLOCKS_OPTION_NAME);
252 $this->cjdata = apply_filters('cjt_blocks_data', $cjdata);
253 // This is a Database Recovery condition.
254 // This is not for a well-known bug. All cases has been studied.
255 // If under any circumstances the cjdata is empty instead of having
256 // a broken Plugin we just recovery by returning a block object.
257 // Also this will fix previous version broken Plugins.
258 if (empty($this->cjdata)) {
259 $this->cjdata[] = array(
260 'block_name' => 'Default',
261 'location' => 'header',
262 'page' => array(),
263 'category' => array(),
264 'links' => '',
265 'scripts' => '',
266 'meta' => array(),
267 );
268 }
269 return $this->cjdata;
270 }
271
272 /**
273 * Check for premium update.
274 *
275 *
276 * @return void
277 */
278 public function checkPremiumUpdate() {
279 // Import Premium Update cron hook.
280 require_once 'premium-update-check.php';
281 CJTPremiumUpdate::check();
282 }
283
284 /**
285 * Bind Wordpress hooks.
286 *
287 * Callback for plugins_loaded.
288 */
289 function start_plugin() {
290 if (is_admin()) {
291 // New installation or check for upgrade.
292 // Plugin activation hook is not fired when the Plugin updated since Wordpress 3.1.
293 // No worries the code inside will not executed twice.
294 $this->checkInstallation();
295 // Load Plugin translation.
296 load_plugin_textdomain(CJTOOLBOX_TEXT_DOMAIN, null, 'css-javascript-toolbox/langs');
297 // Load for admin panel
298 add_action('admin_menu', array(&self::$instance, 'add_plugin_menu'));
299 // register ajax save function
300 add_action('wp_ajax_cjtoolbox_save', array(&self::$instance, 'ajax_save_changes'));
301 add_action('wp_ajax_cjtoolbox_save_newcode', array(&self::$instance, 'ajax_save_newcode'));
302 add_action('wp_ajax_cjtoolbox_form', array(&self::$instance, 'ajax_show_form'));
303 add_action('wp_ajax_cjtoolbox_get_code', array(&self::$instance, 'ajax_get_code'));
304 add_action('wp_ajax_cjtoolbox_delete_code', array(&self::$instance, 'ajax_delete_code'));
305 add_action('wp_ajax_cjtoolbox_add_block', array(&self::$instance, 'ajax_add_block'));
306 add_action('wp_ajax_cjtoolbox_request_template', array(&self::$instance, 'ajax_request_template'));
307 // Get latest update data.
308 self::$premiumUpgradeTransient = get_site_transient('cjt_premium_upgrade');
309 }
310 else {
311 // Add the script and style files to header/footer
312 add_action('wp_head', array(&self::$instance, 'cjtoolbox_insert_header_code'));
313 add_action('wp_print_scripts', array(&self::$instance, 'cjtoolbox_embedded_scripts'), 11);
314 add_action('wp_footer', array(&self::$instance, 'cjtoolbox_insert_footer_code'));
315 // Premium update check cron hook.
316 add_action('cjt_premium_update_checker', array(&self::$instance, 'checkPremiumUpdate'));
317 }
318 }
319
320 /**
321 * Output css/js codes for header.
322 *
323 * Callback for wp_head.
324 */
325 function cjtoolbox_insert_header_code() {
326 $this->insertcode('wp_head');
327 }
328
329 /**
330 * Output css/js codes for footer.
331 *
332 * Callback for wp_footer.
333 */
334 function cjtoolbox_insert_footer_code() {
335 $this->insertcode('wp_footer');
336 }
337
338 /**
339 * Enqueue embedded scripts.
340 * Callback for wp_enquque_scripts
341 */
342 public function cjtoolbox_embedded_scripts() {
343 global $wp_scripts;
344 if (!is_admin() && $wp_scripts) { // wp_enqueue_scripts used by backend too!!!
345 // Register additional script that shipped with the Plugin.
346 $this->registerScripts($wp_scripts);
347 // This is the first hook in out chan (wp_head, wp_footer, wp_enqueue_scripts).
348 // We'll use this hook to set target blocks.
349 $this->setTargetBlocks();
350 // We've to hooklocations wp_head and wp_footer.
351 foreach ($this->blocks as $hookLocation => $blocks) {
352 foreach ($blocks as $key => $block) {
353 // Get block scripts handlers.
354 $scriptsStrList = $this->getScriptsList($block);
355 $scripts = explode(',', $scriptsStrList);
356 if (!empty($scripts) && ($scripts[0] != '')) {
357 foreach ($scripts as $script) {
358 // If previously enqueued, dequeue and then enquque again.
359 // We'll use the latest block hook location.
360 $wp_scripts->dequeue($script);
361 $isFooter = ($hookLocation == 'wp_footer') ? true : false;
362 wp_enqueue_script($script, null, null, null, $isFooter);
363 } // End output scripts.
364 }
365 } // End blocks.
366 } // Enc hooks.
367 }
368 }
369
370 /**
371 * Output code for a specific location.
372 *
373 * @param string Blocks Hook/Location to output.
374 * @return void
375 */
376 function insertcode($hook) {
377 // Make sure there is at least one block for the hook.
378 if (isset($this->blocks[$hook])){
379 // Get blocks code.
380 foreach($this->blocks[$hook] as $blockId => $block) {
381 echo $block['code'] . "\n";
382 }
383 }
384 }
385
386 /**
387 * Set blocks array that should used to output the
388 * css/js codes for the current request.
389 *
390 * @return vod
391 */
392 protected function setTargetBlocks() {
393 global $post;
394 // Reset blocks.
395 $this->blocks = array();
396 // Home page displays a page.
397 $check_for = '';
398 if (is_front_page()) {
399 $check_for = 'frontpage';
400 }
401 else if (is_single() || is_home()) { // The blog page. It will be either same as front page or will be a page.
402 $check_for = 'allposts';
403 }
404 else if (is_page()) {
405 $check_for = $post->ID;
406 }
407
408 $this->getData();
409 $data = $this->cjdata;
410 foreach($data as $key => $block) :
411 // Backward compatibility.
412 // Catogriez blocks by hook location.
413 $hookLocation = $this->getHookLocation($block);
414 $page_list = $data[$key]['page'];
415 if (is_array($page_list)) {
416 if (is_page() && in_array('allpages', $page_list)) {
417 $this->blocks[$hookLocation][$key] = $block;
418 continue;
419 }
420 else if(in_array($check_for, $page_list)) {
421 $this->blocks[$hookLocation][$key] = $block;
422 continue;
423 }
424 }
425 if (is_category()) {
426 $this_category = get_query_var('cat');
427 $category_list = $data[$key]['category'];
428 if (is_array($category_list)) {
429 if(in_array($this_category, $category_list)) {
430 $this->blocks[$hookLocation][$key] = $block;
431 continue;
432 }
433 }
434 }
435
436 $pageURL = 'http';
437 if ($_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
438 $pageURL .= "://";
439 if ($_SERVER["SERVER_PORT"] != "80") {
440 $pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
441 } else {
442 $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
443 }
444 $links = $data[$key]['links'];
445 $link_list = explode("\n", $links);
446 if (in_array($pageURL, $link_list)) {
447 $this->blocks[$hookLocation][$key] = $block;
448 continue;
449 }
450 endforeach;
451 }
452
453 /**
454 * Register additional scripts shipped out with the Plugin.
455 *
456 * @param WP_SCRIPTS
457 * @return void
458 */
459 protected function registerScripts(&$wp_scripts) {
460 // Scripts shipped with Plugin.
461 $scripts = array(
462 'jquery-cycle-all' => array(
463 'file' => 'jquery.cycle.all.min.js',
464 'ver' => '2.65',
465 'dep' => array('jquery'),
466 ),
467 'jquery-easing' => array(
468 'file' => 'jquery.easing.js',
469 'ver' => '1.3',
470 'dep' => array('jquery'),
471 ),
472 );
473 // Register scripts.
474 foreach ($scripts as $handle => $script) {
475 $additionalJSDir = CJTOOLBOX_JS_URL . '/' . self::ADDITIONAL_SCRIPTS_DIR;
476 $source = "{$additionalJSDir}/{$script['file']}";
477 $wp_scripts->add($handle, $source, $script['dep'], $script['ver']);
478 }
479 }
480
481 /**
482 * Add CJT admin page.
483 *
484 * Callback for (admin_menu)
485 */
486 function add_plugin_menu() {
487 $this->hook_manage = add_options_page('CSS & JavaScript Toolbox' ,'CSS & JavaScript Toolbox', '10', 'cjtoolbox', array(&self::$instance, 'admin_display'));
488 // register callback to show styles needed for the admin page
489 add_action('admin_print_styles-' . $this->hook_manage, array(&self::$instance, 'admin_print_styles'));
490 // Load scripts for admin panel working
491 add_action('admin_print_scripts-' . $this->hook_manage, array(&self::$instance, 'admin_print_scripts'));
492 }
493
494 /**
495 * Enqueue admin styles.
496 *
497 * Callback for admin_print_styles-[$hook_manage].
498 */
499 function admin_print_styles() {
500 wp_enqueue_style('thickbox');
501 wp_enqueue_style('cjtoolbox', CJTOOLBOX_CSS_URL . '/admin.css', '', CJTOOLBOX_VERSION, 'all');
502 wp_enqueue_style('jquery');
503 }
504
505 /**
506 * Enqueue admin scripts.
507 *
508 * Callback for admin_print_scripts-[$hook_manage].
509 */
510 function admin_print_scripts() {
511 wp_enqueue_script('jquery');
512 wp_enqueue_script('common');
513 wp_enqueue_script('wp-lists');
514 wp_enqueue_script('postbox');
515 wp_enqueue_script('thickbox');
516 wp_enqueue_script('jquery-ui-tabs');
517 wp_enqueue_script('md5', CJTOOLBOX_JS_URL . '/md5-min.js'); // Md5 used to create from data hashes.
518 wp_enqueue_script('cjt-contenthash', CJTOOLBOX_JS_URL . '/contenthash.js');
519 // Admin Javascript with localization.
520 wp_enqueue_script('cjt-admin', CJTOOLBOX_JS_URL . '/admin.js');
521 $localization = array(
522 'addBlockFailed' => __('Oops, unable to add CSS & JavaScript Block! Please try again!!!'),
523 'UnableToReadCode' => __('Oops, unable to fetch selected {type} template! Please try again!!!'),
524 'confirmDeleteTemplate' => __('Are you sure? Selected template will be deleted permanently!!!'),
525 'cantDeleteTemplate' => __('Oops, unable to delete selected {type} template! Please try again!!!'),
526 'templateDeleted' => __('Selected {type} template deleted successfully!'),
527 'confirmDeleteBlock' => __('Are you sure you want to delete "{block_name}" block?') . "\n\n" . __('The block is not permanently deleted unless "Save Changes" button is clicked'),
528 'titleFieldMissing' => __('Please enter title for code!'),
529 'codeFieldMissing' => __('Please enter code to save!'),
530 'noChangeMadeCouldNotSaveTemplate' => __('Code template was not saved because there were no changes made.') . "\n\n" . __('Do you wish to finish editing anyway?'),
531 'couldNotSaveTemplate' => __('Could not save template, please try again.'),
532 'templateSavedSuccessful' => __('"{title}" {type} code template has been saved successfully.'),
533 'blockNameMissing' => __('Block name cannot be null, please type a name.'),
534 'blockNameIsInUse' => __('Block name is in use. There is another block with the same name!!!') . "\n\n" . __('Please select another name.'),
535 );
536 wp_localize_script('cjt-admin', 'localization', $localization);
537 }
538
539 /**
540 * Blocks management page.
541 *
542 * Callback for menu page
543 */
544 function admin_display() {
545 // Import Wordpress Menu Navigation for displaying posts/pages/categories.
546 require CJTOOLBOX_INCLUDE_PATH . '/wpnavmenuwalker.inc.php';
547 // Load blocks data from database.
548 $this->getData();
549 // The idea behind making the blocks sortable is stop
550 // reseting the array ids.
551 // To avoid block id duplication we need to do not ever use the same Id again.
552 $existsIds = array_keys($this->cjdata);
553 $count = max($existsIds) + 1;
554 // Prepare blocks for display.
555 foreach ($this->cjdata as $i => $block) {
556 $blockName = $this->getBlockName($block, $i);
557 add_meta_box('cjtoolbox-' . ($i + 1), sprintf(__('CSS & JavaScript Block: %s', CJTOOLBOX_TEXT_DOMAIN), $blockName), array(&$this, 'cjtoolbox_unit'), $this->hook_manage, 'normal', 'core', $i);
558 }
559 do_action('cjt_admin_display_start', $this->cjdata);
560 // Output the admin management page.
561 require CJTOOLBOX_VIEWS_PATH . '/manage.html';
562 do_action('cjt_admin_display_end', $this->cjdata);
563 }
564
565 /**
566 * Get block hook location header/footer.
567 *
568 * Backward compatibility for older version that doesn't support hook location.
569 *
570 * @param array Block data.
571 * @param string Value to use if the hook location is not available.
572 * @return string Hook location name.
573 */
574 protected function getHookLocation($block, $default = 'wp_head') {
575 return isset($block['location']) ? $block['location'] : $default;
576 }
577
578 /**
579 * Get block scripts list.
580 *
581 * Backward compatibility for older version that doesn't support embedded scripting.
582 *
583 * @param array Block data.
584 * @return string
585 */
586 protected function getScriptsList($block, $default = '') {
587 // For old version that doesn't support embedded scripts.
588 $scripts = isset($block['scripts']) ? $block['scripts'] : $default;
589 return $scripts;
590 }
591
592 /**
593 * Get block name.
594 *
595 * Backward compatibility for older version that doesn't support block names.
596 *
597 * @param array Block data.
598 * @param integer Block id.
599 * @return string Block name.
600 */
601 protected function getBlockName($block, $blockId, $oldVersionPrefix = '') {
602 $oldNameStyle = ($blockId + 1);
603 if (isset($block['block_name'])) {
604 $blockName = $block['block_name'];
605 }
606 else {
607 $blockName = "{$oldVersionPrefix}{$oldNameStyle}";
608 }
609 return $blockName;
610 }
611
612 /**
613 * Represent single block markup constructor.
614 *
615 * @param null Not used.
616 * @param integer Block Id.
617 * @param boolean Indicate whether the request is Ajax request.
618 * @return void
619 */
620 function cjtoolbox_unit($data = '', $arg = '', $ajax = false) {
621 $boxid = -1; // Because block 1 might have some content...
622 if ($arg != '') {
623 $boxid = $arg['args'];
624 }
625 // E_ALL complain.
626 // We don't want to use $this->cjdata[$boxid] when the $this->cjdata[$boxid] is not set.
627 // Because the previous version do that (views/snippets/block.tmpl) we need to cover.
628 if ($ajax) {
629 // This won't saved to the database.
630 $this->cjdata[$boxid] = array(
631 'block_name' => ($boxid + 1),
632 'location' => 'header',
633 'code' => '',
634 'page' => array(),
635 'category' => array(),
636 'links' => '',
637 'scripts' => '',
638 'meta' => array(),
639 );
640 }
641 $currentBlock = $this->cjdata[$boxid];
642 $blocksCount = count($this->cjdata);
643 $blockName = $this->getBlockName($currentBlock, $boxid);
644 require CJTOOLBOX_VIEWS_SNIPPETS_PATH . '/block.tmpl';
645 }
646
647 /**
648 * Get taxanomy terms checkboxes selection list.
649 *
650 * @param string List Id.
651 * @param array Selected terms list.
652 */
653 function show_taxonomy_with_checkbox($boxid, $taxonomy_selected) {
654 $taxonomy_name = 'category';
655 $args = array(
656 'child_of' => 0,
657 'exclude' => '',
658 'hide_empty' => false,
659 'hierarchical' => 1,
660 'include' => '',
661 'include_last_update_time' => false,
662 'number' => 9999,
663 'order' => 'ASC',
664 'orderby' => 'name',
665 'pad_counts' => false,
666 );
667 $terms = get_terms($taxonomy_name, $args);
668 if (!$terms || is_wp_error($terms)) {
669 // No items
670 return;
671 }
672 $db_fields = false;
673 if (is_taxonomy_hierarchical($taxonomy_name)) {
674 $db_fields = array( 'parent' => 'parent', 'id' => 'term_id' );
675 }
676 $walker = new cj_Walker_Nav_Menu_Checklist($db_fields, $boxid, 'category', $taxonomy_selected);
677 $args['walker'] = $walker;
678 echo walk_nav_menu_tree(array_map('wp_setup_nav_menu_item', $terms), 0, (object) $args);
679 }
680
681 /**
682 * Get pages terms checkboxes selection list.
683 *
684 * @param string List Id.
685 * @param array Selected pages list.
686 */
687 function show_pages_with_checkbox($boxid, $pages_selected) {
688 $post_type_name = 'page';
689 $args = array(
690 'order' => 'ASC',
691 'orderby' => 'title',
692 'posts_per_page' => 9999,
693 'post_type' => $post_type_name,
694 'suppress_filters' => true,
695 'update_post_term_cache' => false,
696 'update_post_meta_cache' => false
697 );
698 // @todo transient caching of these results with proper invalidation on updating of a post of this type
699 $get_posts = new WP_Query;
700 $posts = $get_posts->query($args);
701 if (!$get_posts->post_count) {
702 // No items
703 return;
704 }
705 $db_fields = false;
706 if (is_post_type_hierarchical($post_type_name)) {
707 $db_fields = array( 'parent' => 'post_parent', 'id' => 'ID' );
708 }
709 $walker = new cj_Walker_Nav_Menu_Checklist($db_fields, $boxid, 'page', $pages_selected);
710 $post_type_object = get_post_type_object($post_type_name);
711 $args['walker'] = $walker;
712 $checkbox_items = walk_nav_menu_tree(array_map('wp_setup_nav_menu_item', $posts), 0, (object) $args);
713 echo $checkbox_items;
714 }
715
716 /**
717 * Get add new block dialog.
718 *
719 * @return void
720 */
721 function ajax_add_block() {
722 check_ajax_referer('cjtoolbox-admin', 'security');
723 // We need the security nonce for the new block.
724 $this->security_nonce = $_REQUEST['security'];
725 // Import Wordpress Menu Navigation for displaying posts/pages/categories.
726 require CJTOOLBOX_INCLUDE_PATH . '/wpnavmenuwalker.inc.php';
727
728 $args = array();
729 // Load blocks from database.
730 $this->getData();
731 $count = (int) $_POST['count'];
732 $args['args'] = $count;
733 require CJTOOLBOX_VIEWS_SNIPPETS_PATH . '/newblock.html.tmpl';
734 die();
735 }
736
737 /**
738 * Request forms templates(e.g edit block name popup, etc..)
739 *
740 * @param string Views path. Useful for modules to utilize from the method.
741 * @param array Params to make visible to the template file.
742 * @return void
743 */
744 function ajax_request_template($viewsPath = CJTOOLBOX_VIEWS_SNIPPETS_PATH, $param = array()) {
745 check_ajax_referer('cjtoolbox-admin', 'security');
746 $name = $_GET['name'];
747 if (preg_match('/[a-z\_\-]+/', $name)) {
748 // Make parameters visible to the template.
749 extract($param);
750 // Include the file.
751 $templateName = "{$name}.html.tmpl";
752 $pathToTemplate = "{$viewsPath}/{$templateName}";
753 require $pathToTemplate;
754 }
755 die();
756 }
757
758 /**
759 * Save new code template to database.
760 *
761 * @return void
762 */
763 function ajax_save_newcode() {
764 check_ajax_referer('cjtoolbox-popup', 'security');
765 // Add new row to cjdata table
766 $type = $_POST['type'];
767 $title = $_POST['title'];
768 // Get RAW data indpendent from magic_quote_gpc, let Wordpress $wpdb->update/insert do the rest.
769 $code = filter_input(INPUT_POST, 'code', FILTER_UNSAFE_RAW);
770 $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
771 $response = $this->add_cjdata($id, $type, $title, $code);
772 die($response);
773 }
774
775 /**
776 * Save blocks data.
777 *
778 * @return void
779 */
780 function ajax_save_changes() {
781 check_ajax_referer('cjtoolbox-admin', 'security');
782 $response = array();
783 if($_POST['action'] == 'cjtoolbox_save') {
784 // Save data and return 1 on success.
785 // Get RAW data indpendent from magic_quote_gpc, let Wordpress $wpdb->update/insert do the escaping.
786 $blocks = filter_input(INPUT_POST, 'cjtoolbox', FILTER_UNSAFE_RAW, FILTER_REQUIRE_ARRAY);
787 $blocks = apply_filters('cjt_save_data', $blocks);
788 // Take a copy from the first block.
789 $firstBlock = each($blocks);
790 foreach($blocks as $id => $block) {
791 if ($block['code'] == '') {
792 // Don't store blocks with empty code.
793 unset($blocks[$id]);
794 }
795 else {
796 // Clean up block data.
797 // Prepare for storing.
798 $blocks[$id] = $this->cleanSingleBlock($block);
799 }
800 }
801 // Because we may get all the blocks with empty code and
802 // we need to maintain at least one block.
803 // If all blocks is empty take the first one.
804 if (empty($blocks)) {
805 $blocks[$firstBlock['key']] = $firstBlock['value'];
806 }
807 $this->cjdata = $blocks;
808 $this->saveData();
809 do_action('cjt_data_saved', $blocks);
810 $response['savedIds'] = array_keys($blocks);
811 $response['availableCount'] = count($blocks);
812 }
813 die(json_encode($response)); // Our Response.
814 }
815
816 /**
817 * Delete selected code template.
818 *
819 * @return void
820 */
821 function ajax_delete_code() {
822 check_ajax_referer('cjtoolbox-admin', 'security');
823 $type = $_POST['type'];
824 $id = (int) $_POST['id'];
825 if ($id <=0 || ($type != 'js' && $type != 'css')) {
826 return __('Invalid Request: Unable to process the request!', CJTOOLBOX_TEXT_DOMAIN);
827 }
828 $this->delete_cjdata($type, $id);
829 die('1');
830 }
831
832 /**
833 * Get code for a specific template.
834 *
835 * @return void
836 */
837 function ajax_get_code() {
838 check_ajax_referer('cjtoolbox-admin', 'security');
839 $type = $_POST['type'];
840 $id = (int) $_POST['id'];
841 if($id <=0 || ($type != 'js' && $type != 'css')) {
842 return __('Invalid Request: Unable to process the request!', CJTOOLBOX_TEXT_DOMAIN);
843 }
844 $code = $this->get_cjdata($type, $id);
845 die($code);
846 }
847
848 /**
849 * New code popup constructor.
850 *
851 * @return void
852 */
853 function ajax_show_form() {
854 global $wpdb;
855 check_ajax_referer('cjtoolbox-admin', 'security');
856 $type = '';
857 switch($_GET['type']) {
858 case 'js':
859 $type = 'js';
860 break;
861 case 'css':
862 default:
863 $type = 'css';
864 break;
865 }
866 $editId = (int) $_GET['id'];
867 if ($editId) {
868 $query = "SELECT *
869 FROM {$wpdb->prefix}cjtoolbox_cjdata
870 WHERE id = %d";
871 $query = $wpdb->prepare($query, $editId);
872 $template = $wpdb->get_row($query, ARRAY_A);
873 }
874 else {
875 // Dummy object for filling the form.
876 $template = array(
877 'type' => $type,
878 'title' => '',
879 'code' => '',
880 );
881 }
882 require CJTOOLBOX_VIEWS_SNIPPETS_PATH . "/newcode.html.tmpl";
883 die();
884 }
885
886 /**
887 * Get code template selection list.
888 *
889 * @param string Type of template. It could be 'css' or 'js';
890 * @param string Unique identified for the block list.
891 * @return void
892 */
893 function show_dropdown_box($type, $boxid) {
894 global $wpdb;
895 $query = $wpdb->prepare("SELECT id, title FROM {$wpdb->prefix}cjtoolbox_cjdata WHERE type = '{$type}'");
896 $list = $wpdb->get_results($query);
897 if(count($list)) {
898 echo '<select id="cjtoolbox-'.$type.'-'.$boxid.'" class="cjtoolbox-'.$type.'">';
899 foreach($list as $def) {
900 echo '<option value="' . $def->id . '">'. $def->title . '</option>';
901 }
902 echo '</select>';
903 }
904 }
905
906 /**
907 * Add a new code template to database.
908 *
909 * @param string Template type.
910 * @param string Template title.
911 * @param string Template content.
912 * @return integer|null Template id when success or null if faild.
913 */
914 function add_cjdata($id, $type, $title, $code) {
915 global $wpdb;
916 $result = array('operation' => '', 'id' => '', 'code' => '');
917 // Validate.
918 if($type == '' || $title == '' || $code == '') {
919 return false;
920 }
921 // Update exists record.
922 if ($id) {
923 $data = array(
924 'title' => $title,
925 'code' => $code,
926 );
927 $filter = array(
928 'id' => $id,
929 'type' => $type,
930 );
931 $result['id'] = $id;
932 $result['operation'] = 'update';
933 $result['responseCode'] = $wpdb->update("{$wpdb->prefix}cjtoolbox_cjdata", $data, $filter);
934 }
935 else {
936 $query = $wpdb->prepare("INSERT INTO {$wpdb->prefix}cjtoolbox_cjdata (type,title,code) VALUES ('%s', '%s', '%s')", $type, $title, $code);
937 $wpdb->query($query);
938 // Get inserted id
939 $result['id'] = $wpdb->get_var("SELECT id FROM {$wpdb->prefix}cjtoolbox_cjdata ORDER BY id DESC LIMIT 0,1");
940 $result['operation'] = 'insert';
941 $result['responseCode'] = $result['id'];
942 }
943 return json_encode($result);
944 }
945
946 /**
947 * Delete template.
948 *
949 * @param string Template type css/js.
950 * @param integer Id of the template.
951 * @return true.
952 */
953 function delete_cjdata($type, $id) {
954 global $wpdb;
955 if($type == '' || $id <= 0) return false;
956 $query = $wpdb->prepare("DELETE FROM {$wpdb->prefix}cjtoolbox_cjdata WHERE type = '%s' AND id = '%d' LIMIT 1", $type, $id);
957 $wpdb->query($query);
958 return true;
959 }
960
961 /**
962 * Get code for a specific template.
963 *
964 * @param string Template type.
965 * @param integer Template Id.
966 * @return string|null
967 */
968 function get_cjdata($type, $id) {
969 global $wpdb;
970 if($type == '' || $id <= 0) return false;
971 $query = $wpdb->prepare("SELECT code FROM {$wpdb->prefix}cjtoolbox_cjdata WHERE type = '%s' AND id = '%d' LIMIT 1", $type, $id);
972 $code = $wpdb->get_var($query);
973 return $code;
974 }
975
976 /**
977 * Install/Upgrade CJT Plugin.
978 *
979 * return void.
980 */
981 function checkInstallation() {
982 $installed_db = get_option(self::DATABASE_VERSION_OPTION_NAME);
983 if (!$installed_db) { // New installation.
984 do_action('cjt_install');
985 $this->install();
986 add_option(self::DATABASE_VERSION_OPTION_NAME, CJTOOLBOX_VERSION);
987 do_action('cjt_installed');
988 }
989 else if(version_compare(CJTOOLBOX_VERSION, $installed_db) == 1) { // Upgrade version 0.2.
990 do_action('cjt_upgrade', $installed_db);
991 $this->upgrade();
992 update_option(self::DATABASE_VERSION_OPTION_NAME, CJTOOLBOX_VERSION);
993 do_action('cjt_upgraded', $installed_db);
994 }
995 }
996
997 /**
998 * Activate the Plugin
999 *
1000 * Callback for register_Activation_hook.
1001 */
1002 public function activate_plugin() {
1003 // Schedule Premium Check Update event.
1004 wp_schedule_event(time() + 60, "daily", 'cjt_premium_update_checker');
1005 }
1006
1007 /**
1008 * Call back for register_deactivation_hook.
1009 */
1010 public function deactivate_plugin() {
1011 // Clear previously scheduled event (@see activate_plugin).
1012 wp_clear_scheduled_hook('cjt_premium_update_checker');
1013 }
1014
1015 /**
1016 * Install the Plugin.
1017 *
1018 * @return void
1019 */
1020 public function install() {
1021 global $wpdb;
1022 require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
1023 // Create the table structure
1024 $sql = "CREATE TABLE `{$wpdb->prefix}cjtoolbox_cjdata` (
1025 `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT ,
1026 `type` VARCHAR( 15 ) NOT NULL ,
1027 `title` TINYTEXT NOT NULL ,
1028 `code` MEDIUMTEXT NOT NULL ,
1029 PRIMARY KEY ( `id` , `type` )
1030 )";
1031 dbDelta($sql);
1032
1033 // Add sample code
1034 $count = $wpdb->get_var("SELECT count(*) FROM {$wpdb->prefix}cjtoolbox_cjdata WHERE type='css'");
1035 if($count == 0) {
1036 $wpdb->query("INSERT INTO {$wpdb->prefix}cjtoolbox_cjdata (type,title,code) VALUES ('css','Inline CSS Declaration','<style type=\"text/css\">\n\n</style>')");
1037 $wpdb->query("INSERT INTO {$wpdb->prefix}cjtoolbox_cjdata (type,title,code) VALUES ('css','External Stylesheet','<link rel=\"stylesheet\" type=\"text/css\" href=\"\"/>')");
1038 }
1039
1040 $count = $wpdb->get_var("SELECT count(*) FROM {$wpdb->prefix}cjtoolbox_cjdata WHERE type='js'");
1041 if($count == 0) {
1042 $wpdb->query("INSERT INTO {$wpdb->prefix}cjtoolbox_cjdata (type,title,code) VALUES ('js','Inline JavaScript Declaration','<script type=\"text/javascript\">\n\n</script>')");
1043 $wpdb->query("INSERT INTO {$wpdb->prefix}cjtoolbox_cjdata (type,title,code) VALUES ('js','External JavaScript','<script type=\"text/javascript\" src=\"\"></script>')");
1044 $wpdb->query("INSERT INTO {$wpdb->prefix}cjtoolbox_cjdata (type,title,code) VALUES ('js','jQuery Code Wrapper','<script type=\"text/javascript\">\n(function(\$) {\n\n\t//PUT YOUR CODE HERE...\n\n})(jQuery);\n</script>')");
1045 }
1046 // Add default block.
1047 $sampleCode = '<!-- ' . __('CSS & JAVASCRIPT TOOLBOX - INSTRUCTIONS AND DEMO') . " -->\n";
1048 $sampleCode .= '<!-- ' . __('Feel free to delete all of this text at any time. For more information, please click \'Hints & Tips\'') . " -->\n\n";
1049 $sampleCode .= '<!-- ' . __('Write your CSS and JS code here, then apply it by using one of the tabs (Pages, Categories, URL) from the panel on the right') . " -->\n";
1050 $sampleCode .= '<!-- ' . __('The example JavaScript code shown below will display an alert message box') . " -->\n";
1051 $sampleCode .= '<!-- ' . __('To see this code in action, lets click the "Front Page" checkbox from the panel on the right') . " -->\n";
1052 $sampleCode .= '<!-- ' . __('Click the blue \'Save All Changes\' button, then click the Front Page navigation icon to open the page in a new window') . " -->\n";
1053 $sampleCode .= '<!-- ' . __('Have fun!!!') . " -->\n\n";
1054 $sampleCode .= "<script type='text/javascript'>\n\talert(\"Thank you for installing CSS & JavaScript Toolbox.\\nIf you find this plugin useful, please let us know at www.WipeoutMedia.com\");\n</script>\n";
1055
1056 $defaultBlock = array(
1057 'block_name' => 'Default',
1058 'location' => 'header',
1059 'code' => $sampleCode,
1060 'page' => array(),
1061 'category' => array(),
1062 'links' => '',
1063 'scripts' => '',
1064 'meta' => array(),
1065 );
1066 $this->cjdata = array($defaultBlock);
1067 $this->saveData();
1068 }
1069
1070 /**
1071 * Upgrade the plugin from the last version.
1072 *
1073 * @return void
1074 */
1075 public function upgrade() {
1076 // Add meta array for all blocks.
1077 $blocks = (array) get_option(self::BLOCKS_OPTION_NAME);
1078 foreach ($blocks as $id => $block) {
1079 // Add meta field to the exists blocks.
1080 // This method should called one time but for any reason
1081 // don't overriding exists values.
1082 if (!array_key_exists('meta', $block)) {
1083 $blocks[$id]['meta'] = array();
1084 }
1085 $blocks[$id] = $this->cleanSingleBlock($block);
1086 }
1087 // Save blocks.
1088 update_option(cssJSToolbox::BLOCKS_OPTION_NAME, $blocks);
1089 }
1090
1091 /**
1092 * Print CSSJtoolbox Debug message.
1093 *
1094 * @param mixed $message
1095 */
1096 public static function printDebugMessage($message) {
1097 if (CJTOOLBOX_DEBUG) {
1098 echo "{$message}<br />";
1099 }
1100 }
1101
1102 }// END Class
1103
1104 // Let's start the plugin
1105 cssJSToolbox::getInstance();
1106 }