Simple Custom CSS and JS - Version 3.29

Version Description

  • 01/31/2020
  • Fix: date Published and Modified date wasn't shown in Japanese
  • Feature: indentation in the editor
  • Feature: close brackets in the editor
Download this release

Release Info

Developer diana_burduja
Plugin Icon 128x128 Simple Custom CSS and JS
Version 3.29
Comparing to
See all releases

Code changes from version 3.28 to 3.29

assets/ccj_admin.js CHANGED
@@ -16,6 +16,7 @@ jQuery(document).ready( function($) {
16
  lineNumbers: true,
17
  mode: content_mode,
18
  matchBrackets: true,
 
19
  extraKeys: {
20
  "Ctrl-F": "findPersistent",
21
  },
16
  lineNumbers: true,
17
  mode: content_mode,
18
  matchBrackets: true,
19
+ autoCloseBrackets: true,
20
  extraKeys: {
21
  "Ctrl-F": "findPersistent",
22
  },
assets/codemirror/addon/edit/closebrackets.js ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ var defaults = {
13
+ pairs: "()[]{}''\"\"",
14
+ triples: "",
15
+ explode: "[]{}"
16
+ };
17
+
18
+ var Pos = CodeMirror.Pos;
19
+
20
+ CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
21
+ if (old && old != CodeMirror.Init) {
22
+ cm.removeKeyMap(keyMap);
23
+ cm.state.closeBrackets = null;
24
+ }
25
+ if (val) {
26
+ ensureBound(getOption(val, "pairs"))
27
+ cm.state.closeBrackets = val;
28
+ cm.addKeyMap(keyMap);
29
+ }
30
+ });
31
+
32
+ function getOption(conf, name) {
33
+ if (name == "pairs" && typeof conf == "string") return conf;
34
+ if (typeof conf == "object" && conf[name] != null) return conf[name];
35
+ return defaults[name];
36
+ }
37
+
38
+ var keyMap = {Backspace: handleBackspace, Enter: handleEnter};
39
+ function ensureBound(chars) {
40
+ for (var i = 0; i < chars.length; i++) {
41
+ var ch = chars.charAt(i), key = "'" + ch + "'"
42
+ if (!keyMap[key]) keyMap[key] = handler(ch)
43
+ }
44
+ }
45
+ ensureBound(defaults.pairs + "`")
46
+
47
+ function handler(ch) {
48
+ return function(cm) { return handleChar(cm, ch); };
49
+ }
50
+
51
+ function getConfig(cm) {
52
+ var deflt = cm.state.closeBrackets;
53
+ if (!deflt || deflt.override) return deflt;
54
+ var mode = cm.getModeAt(cm.getCursor());
55
+ return mode.closeBrackets || deflt;
56
+ }
57
+
58
+ function handleBackspace(cm) {
59
+ var conf = getConfig(cm);
60
+ if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
61
+
62
+ var pairs = getOption(conf, "pairs");
63
+ var ranges = cm.listSelections();
64
+ for (var i = 0; i < ranges.length; i++) {
65
+ if (!ranges[i].empty()) return CodeMirror.Pass;
66
+ var around = charsAround(cm, ranges[i].head);
67
+ if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
68
+ }
69
+ for (var i = ranges.length - 1; i >= 0; i--) {
70
+ var cur = ranges[i].head;
71
+ cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1), "+delete");
72
+ }
73
+ }
74
+
75
+ function handleEnter(cm) {
76
+ var conf = getConfig(cm);
77
+ var explode = conf && getOption(conf, "explode");
78
+ if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass;
79
+
80
+ var ranges = cm.listSelections();
81
+ for (var i = 0; i < ranges.length; i++) {
82
+ if (!ranges[i].empty()) return CodeMirror.Pass;
83
+ var around = charsAround(cm, ranges[i].head);
84
+ if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
85
+ }
86
+ cm.operation(function() {
87
+ var linesep = cm.lineSeparator() || "\n";
88
+ cm.replaceSelection(linesep + linesep, null);
89
+ cm.execCommand("goCharLeft");
90
+ ranges = cm.listSelections();
91
+ for (var i = 0; i < ranges.length; i++) {
92
+ var line = ranges[i].head.line;
93
+ cm.indentLine(line, null, true);
94
+ cm.indentLine(line + 1, null, true);
95
+ }
96
+ });
97
+ }
98
+
99
+ function contractSelection(sel) {
100
+ var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0;
101
+ return {anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)),
102
+ head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1))};
103
+ }
104
+
105
+ function handleChar(cm, ch) {
106
+ var conf = getConfig(cm);
107
+ if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
108
+
109
+ var pairs = getOption(conf, "pairs");
110
+ var pos = pairs.indexOf(ch);
111
+ if (pos == -1) return CodeMirror.Pass;
112
+ var triples = getOption(conf, "triples");
113
+
114
+ var identical = pairs.charAt(pos + 1) == ch;
115
+ var ranges = cm.listSelections();
116
+ var opening = pos % 2 == 0;
117
+
118
+ var type;
119
+ for (var i = 0; i < ranges.length; i++) {
120
+ var range = ranges[i], cur = range.head, curType;
121
+ var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
122
+ if (opening && !range.empty()) {
123
+ curType = "surround";
124
+ } else if ((identical || !opening) && next == ch) {
125
+ if (identical && stringStartsAfter(cm, cur))
126
+ curType = "both";
127
+ else if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch)
128
+ curType = "skipThree";
129
+ else
130
+ curType = "skip";
131
+ } else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 &&
132
+ cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch) {
133
+ if (cur.ch > 2 && /\bstring/.test(cm.getTokenTypeAt(Pos(cur.line, cur.ch - 2)))) return CodeMirror.Pass;
134
+ curType = "addFour";
135
+ } else if (identical) {
136
+ var prev = cur.ch == 0 ? " " : cm.getRange(Pos(cur.line, cur.ch - 1), cur)
137
+ if (!CodeMirror.isWordChar(next) && prev != ch && !CodeMirror.isWordChar(prev)) curType = "both";
138
+ else return CodeMirror.Pass;
139
+ } else if (opening && (cm.getLine(cur.line).length == cur.ch ||
140
+ isClosingBracket(next, pairs) ||
141
+ /\s/.test(next))) {
142
+ curType = "both";
143
+ } else {
144
+ return CodeMirror.Pass;
145
+ }
146
+ if (!type) type = curType;
147
+ else if (type != curType) return CodeMirror.Pass;
148
+ }
149
+
150
+ var left = pos % 2 ? pairs.charAt(pos - 1) : ch;
151
+ var right = pos % 2 ? ch : pairs.charAt(pos + 1);
152
+ cm.operation(function() {
153
+ if (type == "skip") {
154
+ cm.execCommand("goCharRight");
155
+ } else if (type == "skipThree") {
156
+ for (var i = 0; i < 3; i++)
157
+ cm.execCommand("goCharRight");
158
+ } else if (type == "surround") {
159
+ var sels = cm.getSelections();
160
+ for (var i = 0; i < sels.length; i++)
161
+ sels[i] = left + sels[i] + right;
162
+ cm.replaceSelections(sels, "around");
163
+ sels = cm.listSelections().slice();
164
+ for (var i = 0; i < sels.length; i++)
165
+ sels[i] = contractSelection(sels[i]);
166
+ cm.setSelections(sels);
167
+ } else if (type == "both") {
168
+ cm.replaceSelection(left + right, null);
169
+ cm.triggerElectric(left + right);
170
+ cm.execCommand("goCharLeft");
171
+ } else if (type == "addFour") {
172
+ cm.replaceSelection(left + left + left + left, "before");
173
+ cm.execCommand("goCharRight");
174
+ }
175
+ });
176
+ }
177
+
178
+ function isClosingBracket(ch, pairs) {
179
+ var pos = pairs.lastIndexOf(ch);
180
+ return pos > -1 && pos % 2 == 1;
181
+ }
182
+
183
+ function charsAround(cm, pos) {
184
+ var str = cm.getRange(Pos(pos.line, pos.ch - 1),
185
+ Pos(pos.line, pos.ch + 1));
186
+ return str.length == 2 ? str : null;
187
+ }
188
+
189
+ function stringStartsAfter(cm, pos) {
190
+ var token = cm.getTokenAt(Pos(pos.line, pos.ch + 1))
191
+ return /\bstring/.test(token.type) && token.start == pos.ch &&
192
+ (pos.ch == 0 || !/\bstring/.test(cm.getTokenTypeAt(pos)))
193
+ }
194
+ });
custom-css-js.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Simple Custom CSS and JS
4
  * Plugin URI: https://wordpress.org/plugins/custom-css-js/
5
  * Description: Easily add Custom CSS or JS to your website with an awesome editor.
6
- * Version: 3.28
7
  * Author: SilkyPress.com
8
  * Author URI: https://www.silkypress.com
9
  * License: GPL2
@@ -12,7 +12,7 @@
12
  * Domain Path: /languages/
13
  *
14
  * WC requires at least: 2.3.0
15
- * WC tested up to: 3.8
16
  */
17
 
18
  if ( ! defined( 'ABSPATH' ) ) {
@@ -218,7 +218,7 @@ final class CustomCSSandJS {
218
  function set_constants() {
219
  $dir = wp_upload_dir();
220
  $constants = array(
221
- 'CCJ_VERSION' => '3.28',
222
  'CCJ_UPLOAD_DIR' => $dir['basedir'] . '/custom-css-js',
223
  'CCJ_UPLOAD_URL' => $dir['baseurl'] . '/custom-css-js',
224
  'CCJ_PLUGIN_FILE' => __FILE__,
3
  * Plugin Name: Simple Custom CSS and JS
4
  * Plugin URI: https://wordpress.org/plugins/custom-css-js/
5
  * Description: Easily add Custom CSS or JS to your website with an awesome editor.
6
+ * Version: 3.29
7
  * Author: SilkyPress.com
8
  * Author URI: https://www.silkypress.com
9
  * License: GPL2
12
  * Domain Path: /languages/
13
  *
14
  * WC requires at least: 2.3.0
15
+ * WC tested up to: 3.9
16
  */
17
 
18
  if ( ! defined( 'ABSPATH' ) ) {
218
  function set_constants() {
219
  $dir = wp_upload_dir();
220
  $constants = array(
221
+ 'CCJ_VERSION' => '3.29',
222
  'CCJ_UPLOAD_DIR' => $dir['basedir'] . '/custom-css-js',
223
  'CCJ_UPLOAD_URL' => $dir['baseurl'] . '/custom-css-js',
224
  'CCJ_PLUGIN_FILE' => __FILE__,
includes/admin-screens.php CHANGED
@@ -1,11 +1,10 @@
1
  <?php
2
  /**
3
  * Custom CSS and JS
4
- *
5
  */
6
 
7
  if ( ! defined( 'ABSPATH' ) ) {
8
- exit; // Exit if accessed directly
9
  }
10
 
11
  /**
@@ -13,590 +12,595 @@ if ( ! defined( 'ABSPATH' ) ) {
13
  */
14
  class CustomCSSandJS_Admin {
15
 
16
- /**
17
- * Default options for a new page
18
- */
19
- private $default_options = array(
20
- 'type' => 'header',
21
- 'linking' => 'internal',
22
- 'side' => 'frontend',
23
- 'priority' => 5,
24
- 'language' => 'css',
25
- );
26
-
27
- /**
28
- * Array with the options for a specific custom-css-js post
29
- */
30
- private $options = array();
31
-
32
- /**
33
- * Constructor
34
- */
35
- public function __construct() {
36
-
37
- $this->add_functions();
38
- }
39
-
40
- /**
41
- * Add actions and filters
42
- */
43
- function add_functions() {
44
-
45
- // Add filters
46
- $filters = array(
47
- 'manage_custom-css-js_posts_columns' => 'manage_custom_posts_columns',
48
- );
49
- foreach( $filters as $_key => $_value ) {
50
- add_filter( $_key, array( $this, $_value ) );
51
- }
52
-
53
- // Add actions
54
- $actions = array(
55
- 'admin_menu' => 'admin_menu',
56
- 'admin_enqueue_scripts' => 'admin_enqueue_scripts',
57
- 'current_screen' => 'current_screen',
58
- 'admin_notices' => 'create_uploads_directory',
59
- 'edit_form_after_title' => 'codemirror_editor',
60
- 'add_meta_boxes' => 'add_meta_boxes',
61
- 'save_post' => 'options_save_meta_box_data',
62
- 'trashed_post' => 'trash_post',
63
- 'untrashed_post' => 'trash_post',
64
- 'wp_ajax_ccj_active_code' => 'wp_ajax_ccj_active_code',
65
- 'wp_ajax_ccj_permalink' => 'wp_ajax_ccj_permalink',
66
- 'post_submitbox_start' => 'post_submitbox_start',
67
- 'restrict_manage_posts' => 'restrict_manage_posts',
68
- 'edit_form_before_permalink' => 'edit_form_before_permalink',
69
- 'before_delete_post' => 'before_delete_post',
70
- );
71
- foreach( $actions as $_key => $_value ) {
72
- add_action( $_key, array( $this, $_value ) );
73
- }
74
-
75
- // Add some custom actions/filters
76
- add_action( 'manage_custom-css-js_posts_custom_column', array( $this, 'manage_posts_columns' ), 10, 2 );
77
- add_filter( 'manage_edit-custom-css-js_sortable_columns', array( $this, 'manage_edit_posts_sortable_columns' ) );
78
- add_filter( 'post_row_actions', array( $this, 'post_row_actions' ), 10, 2 );
79
- add_filter( 'parse_query', array($this, 'parse_query') , 10);
80
-
81
-
82
- add_action('current_screen', array($this, 'current_screen_2'), 100);
83
-
84
- }
85
-
86
-
87
- /**
88
- * Add submenu pages
89
- */
90
- function admin_menu() {
91
- $menu_slug = 'edit.php?post_type=custom-css-js';
92
- $submenu_slug = 'post-new.php?post_type=custom-css-js';
93
-
94
- remove_submenu_page( $menu_slug, $submenu_slug);
95
-
96
- $title = __('Add Custom CSS', 'custom-css-js');
97
- add_submenu_page( $menu_slug, $title, $title, 'publish_custom_csss', $submenu_slug .'&language=css');
98
-
99
- $title = __('Add Custom JS', 'custom-css-js');
100
- add_submenu_page( $menu_slug, $title, $title, 'publish_custom_csss', $submenu_slug . '&language=js');
101
-
102
- $title = __('Add Custom HTML', 'custom-css-js');
103
- add_submenu_page( $menu_slug, $title, $title, 'publish_custom_csss', $submenu_slug . '&language=html');
104
-
105
- }
106
-
107
-
108
- /**
109
- * Enqueue the scripts and styles
110
- */
111
- public function admin_enqueue_scripts( $hook ) {
112
-
113
- $screen = get_current_screen();
114
-
115
- // Only for custom-css-js post type
116
- if ( $screen->post_type != 'custom-css-js' )
117
- return false;
118
-
119
- // Some handy variables
120
- $a = plugins_url( '/', CCJ_PLUGIN_FILE). 'assets';
121
- $cm = $a . '/codemirror';
122
- $v = CCJ_VERSION;
123
-
124
- wp_register_script( 'ccj-admin', $a . '/ccj_admin.js', array('jquery', 'jquery-ui-resizable'), $v, false );
125
- wp_localize_script( 'ccj-admin', 'CCJ', $this->cm_localize() );
126
- wp_enqueue_script( 'ccj-admin' );
127
- wp_enqueue_style( 'ccj-admin', $a . '/ccj_admin.css', array(), $v );
128
-
129
-
130
- // Only for the new/edit Code's page
131
- if ( $hook == 'post-new.php' || $hook == 'post.php' ) {
132
- wp_deregister_script('wp-codemirror');
133
-
134
- wp_enqueue_style( 'jquery-ui', 'https://code.jquery.com/ui/1.12.0/themes/base/jquery-ui.css', array(), $v );
135
- wp_enqueue_script( 'ccj-codemirror', $cm . '/lib/codemirror.js', array( 'jquery' ), $v, false);
136
- wp_enqueue_style( 'ccj-codemirror', $cm . '/lib/codemirror.css', array(), $v );
137
- wp_enqueue_script( 'ccj-admin_url_rules', $a . '/ccj_admin-url_rules.js', array('jquery'), $v, false );
138
-
139
- // Add the language modes
140
- $cmm = $cm . '/mode/';
141
- wp_enqueue_script('cm-xml', $cmm . 'xml/xml.js', array('ccj-codemirror'), $v, false);
142
- wp_enqueue_script('cm-js', $cmm . 'javascript/javascript.js', array('ccj-codemirror'), $v, false);
143
- wp_enqueue_script('cm-css', $cmm . 'css/css.js', array('ccj-codemirror'), $v, false);
144
- wp_enqueue_script('cm-htmlmixed', $cmm . 'htmlmixed/htmlmixed.js', array('ccj-codemirror'), $v, false);
145
-
146
- $cma = $cm . '/addon/';
147
- wp_enqueue_script('cm-dialog', $cma . 'dialog/dialog.js', array('ccj-codemirror'), $v, false);
148
- wp_enqueue_script('cm-search', $cma . 'search/search.js', array('ccj-codemirror'), $v, false);
149
- wp_enqueue_script('cm-searchcursor', $cma . 'search/searchcursor.js',array('ccj-codemirror'), $v, false);
150
- wp_enqueue_script('cm-jump-to-line', $cma . 'search/jump-to-line.js', array('ccj-codemirror'), $v, false);
151
- wp_enqueue_style('cm-dialog', $cma . 'dialog/dialog.css', array(), $v );
152
-
153
- // remove the assets from other plugins so it doesn't interfere with CodeMirror
154
- global $wp_scripts;
155
- if (is_array($wp_scripts->registered) && count($wp_scripts->registered) != 0) {
156
- foreach($wp_scripts->registered as $_key => $_value) {
157
- if (!isset($_value->src)) continue;
158
-
159
- if (strstr($_value->src, 'wp-content/plugins') !== false
160
- && strstr($_value->src, 'plugins/custom-css-js/assets') === false
161
- && strstr($_value->src, 'plugins/advanced-custom-fields/') === false
162
- && strstr($_value->src, 'plugins/advanced-custom-fields-pro/') === false) {
163
- unset($wp_scripts->registered[$_key]);
164
- }
165
- }
166
- }
167
-
168
- }
169
- }
170
 
 
 
 
 
 
171
 
172
- /**
173
- * Send variables to the ccj_admin.js script
174
- */
175
- public function cm_localize() {
176
 
177
- $vars = array(
178
- 'active' => __('Active', 'custom-css-js'),
179
- 'inactive' => __('Inactive', 'custom-css-js'),
180
- 'activate' => __('Activate', 'custom-css-js'),
181
- 'deactivate' => __('Deactivate', 'custom-css-js'),
182
- 'active_title' => __('The code is active. Click to deactivate it', 'custom-css-js'),
183
- 'deactive_title' => __('The code is inactive. Click to activate it', 'custom-css-js'),
184
- );
185
 
186
- return $vars;
187
- }
188
-
189
- public function add_meta_boxes() {
190
- add_meta_box('custom-code-options', __('Options', 'custom-css-js'), array( $this, 'custom_code_options_meta_box_callback'), 'custom-css-js', 'side', 'low');
191
-
192
- remove_meta_box( 'slugdiv', 'custom-css-js', 'normal' );
193
- }
194
-
195
-
196
-
197
- /**
198
- * Get options for a specific custom-css-js post
199
- */
200
- private function get_options( $post_id ) {
201
- if ( isset( $this->options[ $post_id ] ) ) {
202
- return $this->options[ $post_id ];
203
- }
204
-
205
- $options = get_post_meta( $post_id );
206
- if ( empty( $options ) || ! isset ( $options['options'][0] ) ) {
207
- $this->options[ $post_id ] = $this->default_options;
208
- return $this->default_options;
209
- }
210
-
211
- $options = unserialize( $options['options'][0] );
212
- $this->options[ $post_id ] = $options;
213
- return $options;
214
- }
215
-
216
-
217
- /**
218
- * Reformat the `edit` or the `post` screens
219
- */
220
- function current_screen( $current_screen ) {
221
-
222
- if ( $current_screen->post_type != 'custom-css-js' ) {
223
- return false;
224
- }
225
-
226
- if ( $current_screen->base == 'post' ) {
227
- add_action( 'admin_head', array( $this, 'current_screen_post' ) );
228
- }
229
-
230
- if ( $current_screen->base == 'edit' ) {
231
- add_action( 'admin_head', array( $this, 'current_screen_edit' ) );
232
- }
233
-
234
- wp_deregister_script( 'autosave' );
235
- }
236
-
237
-
238
-
239
- /**
240
- * Add the buttons in the `edit` screen
241
- */
242
- function add_new_buttons() {
243
- $current_screen = get_current_screen();
244
-
245
- if ( (isset($current_screen->action ) && $current_screen->action == 'add') || $current_screen->post_type != 'custom-css-js' ) {
246
- return false;
247
- }
248
- ?>
249
- <div class="updated buttons">
250
- <a href="post-new.php?post_type=custom-css-js&language=css" class="custom-btn custom-css-btn"><?php _e('Add CSS code', 'custom-css-js'); ?></a>
251
- <a href="post-new.php?post_type=custom-css-js&language=js" class="custom-btn custom-js-btn"><?php _e('Add JS code', 'custom-css-js'); ?></a>
252
- <a href="post-new.php?post_type=custom-css-js&language=html" class="custom-btn custom-js-btn"><?php _e('Add HTML code', 'custom-css-js'); ?></a>
253
- <!-- a href="post-new.php?post_type=custom-css-js&language=php" class="custom-btn custom-php-btn">Add PHP code</a -->
254
- </div>
255
- <?php
256
- }
257
-
258
-
259
-
260
- /**
261
- * Add new columns in the `edit` screen
262
- */
263
- function manage_custom_posts_columns( $columns ) {
264
- return array(
265
- 'cb' => '<input type="checkbox" />',
266
- 'active' => '<span class="ccj-dashicons dashicons dashicons-star-empty" title="'.__('Active', 'custom-css-js') .'"></span>',
267
- 'type' => __('Type', 'custom-css-js'),
268
- 'title' => __('Title', 'custom-css-js'),
269
- 'author' => __('Author', 'custom-css-js'),
270
- 'published' => __('Published', 'custom-css-js'),
271
- 'modified' => __('Modified', 'custom-css-js'),
272
- );
273
- }
274
-
275
-
276
- /**
277
- * Fill the data for the new added columns in the `edit` screen
278
- */
279
- function manage_posts_columns( $column, $post_id ) {
280
-
281
- if ( $column == 'type' ) {
282
- $options = $this->get_options( $post_id );
283
- echo '<span class="language language-'.$options['language'].'">' . $options['language'] . '</span>';
284
- }
285
-
286
- if ( $column == 'modified' || $column == 'published' ) {
287
- if ( $column == 'modified' ) {
288
- $f_time = get_post_modified_time( __('Y/m/d g:i:s a'), true, $post_id );
289
- $g_time = get_post_modified_time( 'G', true, $post_id );
290
- } else {
291
- $f_time = get_post_time( __('Y/m/d g:i:s a' ), true );
292
- $g_time = get_post_time( 'G', true );
293
- }
294
-
295
- $time_diff = time() - $g_time;
296
-
297
- if ( $time_diff > 0 && $time_diff < DAY_IN_SECONDS ) {
298
- $h_time = sprintf( __( '%s ago', 'custom-css-js' ), human_time_diff( $g_time) );
299
- } else {
300
- $h_time = mysql2date( get_option('date_format'), $f_time );
301
- }
302
-
303
- echo $h_time;
304
- }
305
-
306
- if ( $column == 'active' ) {
307
- $url = wp_nonce_url( admin_url( 'admin-ajax.php?action=ccj_active_code&code_id=' . $post_id ), 'ccj-active-code-' .$post_id );
308
- if ( $this->is_active( $post_id ) ) {
309
- $active_title = __('The code is active. Click to deactivate it', 'custom-css-js');
310
- $active_icon = 'dashicons-star-filled';
311
- } else {
312
- $active_title = __('The code is inactive. Click to activate it', 'custom-css-js');
313
- $active_icon = 'dashicons-star-empty ccj_row';
314
- }
315
- echo '<a href="' . esc_url( $url ) . '" class="ccj_activate_deactivate" data-code-id="'.$post_id.'" title="'.$active_title . '">' .
316
- '<span class="dashicons '.$active_icon.'"></span>'.
317
- '</a>';
318
- }
319
- }
320
-
321
-
322
- /**
323
- * Make the 'Modified' column sortable
324
- */
325
- function manage_edit_posts_sortable_columns( $columns ) {
326
- $columns['modified'] = 'modified';
327
- $columns['published'] = 'published';
328
- return $columns;
329
-
330
- }
331
-
332
-
333
- /**
334
- * List table: Change the query in order to filter by code type
335
- */
336
- function parse_query( $query ){
337
- if ( !is_admin() || !$query->is_main_query() ){
338
- return $query;
339
- }
340
-
341
- if ( !isset($query->query['post_type'])) {
342
- return $query;
343
- }
344
-
345
- if ( 'custom-css-js' !== $query->query['post_type'] ) {
346
- return $query;
347
- }
348
-
349
- $filter = filter_input( INPUT_GET, 'language_filter' );
350
- if ( !is_string($filter) || strlen($filter) == 0 ) {
351
- return $query;
352
- }
353
-
354
- global $wpdb;
355
- $post_id_query = "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value LIKE %s";
356
- $post_ids = $wpdb->get_col( $wpdb->prepare($post_id_query, 'options', '%'.$filter.'%') );
357
- if ( !is_array($post_ids) || count($post_ids) == 0 ) {
358
- $post_ids = array(-1);
359
- }
360
- $query->query_vars['post__in'] = $post_ids;
361
-
362
- return $query;
363
- }
364
-
365
-
366
- /**
367
- * List table: add a filter by code type
368
- */
369
- function restrict_manage_posts( $post_type ) {
370
- if('custom-css-js' !== $post_type){
371
- return;
372
- }
373
-
374
- $languages = array(
375
- 'css' => __('CSS Codes', 'custom-cs-js'),
376
- 'js' => __('JS Codes', 'custom-css-js'),
377
- 'html' => __('HTML Codes', 'custom-css-js'),
378
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
 
380
  echo '<label class="screen-reader-text" for="custom-css-js-filter">' . esc_html__( 'Filter Code Type', 'custom-css-js' ) . '</label>';
381
  echo '<select name="language_filter" id="custom-css-js-filter">';
382
- echo '<option value="">' . __('All Custom Codes', 'custom-css-js'). '</option>';
383
  foreach ( $languages as $_lang => $_label ) {
384
- $selected = selected( filter_input( INPUT_GET, 'language_filter' ), $_lang, false ); ;
385
- echo '<option ' . $selected . ' value="' . $_lang. '">' . $_label . '</option>';
386
  }
387
  echo '</select>';
388
- }
389
 
390
 
391
- /**
392
- * Activate/deactivate a code
393
- *
394
- * @return void
395
- */
396
- function wp_ajax_ccj_active_code() {
397
- if ( ! isset( $_GET['code_id'] ) ) die();
 
 
398
 
399
- $code_id = absint( $_GET['code_id'] );
400
 
401
- $response = 'error';
402
- if ( check_admin_referer( 'ccj-active-code-' . $code_id) ) {
403
 
404
  if ( 'custom-css-js' === get_post_type( $code_id ) ) {
405
- $active = get_post_meta($code_id, '_active', true );
406
- if ( $active === false || $active === '' ) {
407
- $active = 'yes';
408
- }
409
- $response = $active;
410
  update_post_meta( $code_id, '_active', $active === 'yes' ? 'no' : 'yes' );
411
 
412
- $this->build_search_tree();
413
  }
414
  }
415
- echo $response;
416
 
417
  die();
418
- }
419
-
420
- /**
421
- * Check if a code is active
422
- *
423
- * @return bool
424
- */
425
- function is_active( $post_id ) {
426
- return get_post_meta( $post_id, '_active', true ) !== 'no';
427
- }
428
-
429
- /**
430
- * Reformat the `edit` screen
431
- */
432
- function current_screen_edit() {
433
- ?>
434
- <script type="text/javascript">
435
- /* <![CDATA[ */
436
- jQuery(window).ready(function($){
437
- var h1 = '<?php _e('Custom Code', 'custom-css-js'); ?> ';
438
- h1 += '<a href="post-new.php?post_type=custom-css-js&language=css" class="page-title-action"><?php _e('Add CSS Code', 'custom-css-js'); ?></a>';
439
- h1 += '<a href="post-new.php?post_type=custom-css-js&language=js" class="page-title-action"><?php _e('Add JS Code', 'custom-css-js'); ?></a>';
440
- h1 += '<a href="post-new.php?post_type=custom-css-js&language=html" class="page-title-action"><?php _e('Add HTML Code', 'custom-css-js'); ?></a>';
441
- $("#wpbody-content h1").html(h1);
442
- });
443
-
444
- </script>
445
- <?php
446
- }
447
-
448
-
449
- /**
450
- * Reformat the `post` screen
451
- */
452
- function current_screen_post() {
453
-
454
- $this->remove_unallowed_metaboxes();
455
-
456
- $strings = array(
457
- 'Add CSS Code' => __('Add CSS Code', 'custom-css-js'),
458
- 'Add JS Code' => __('Add JS Code', 'custom-css-js'),
459
- 'Add HTML Code' => __('Add HTML Code', 'custom-css-js'),
460
- 'Edit CSS Code' => __('Edit CSS Code', 'custom-css-js'),
461
- 'Edit JS Code' => __('Edit JS Code', 'custom-css-js'),
462
- 'Edit HTML Code' => __('Edit HTML Code', 'custom-css-js'),
463
- );
464
-
465
- if ( isset( $_GET['post'] ) ) {
466
- $action = 'Edit';
467
- $post_id = esc_attr($_GET['post']);
468
- } else {
469
- $action = 'Add';
470
- $post_id = false;
471
- }
472
- $language = $this->get_language($post_id);
473
-
474
- $title = $action . ' ' . strtoupper( $language ) . ' Code';
475
- $title = (isset($strings[$title])) ? $strings[$title] : $strings['Add CSS Code'];
476
-
477
- if ( $action == 'Edit' ) {
478
- $title .= ' <a href="post-new.php?post_type=custom-css-js&language=css" class="page-title-action">'.__('Add CSS Code', 'custom-css-js') .'</a> ';
479
- $title .= '<a href="post-new.php?post_type=custom-css-js&language=js" class="page-title-action">'.__('Add JS Code', 'custom-css-js') .'</a>';
480
- $title .= '<a href="post-new.php?post_type=custom-css-js&language=html" class="page-title-action">'.__('Add HTML Code', 'custom-css-js') .'</a>';
481
- }
482
-
483
- ?>
484
- <style type="text/css">
485
- #post-body-content, .edit-form-section { position: static !important; }
486
- #ed_toolbar { display: none; }
487
- #postdivrich { display: none; }
488
- </style>
489
- <script type="text/javascript">
490
- /* <![CDATA[ */
491
- jQuery(window).ready(function($){
492
- $("#wpbody-content h1").html('<?php echo $title; ?>');
493
- $("#message.updated.notice").html('<p><?php _e('Code updated', 'custom-css-js'); ?></p>');
494
-
495
- var from_top = -$("#normal-sortables").height();
496
- if ( from_top != 0 ) {
497
- $(".ccj_only_premium-first").css('margin-top', from_top.toString() + 'px' );
498
- } else {
499
- $(".ccj_only_premium-first").hide();
500
- }
501
- });
502
- /* ]]> */
503
- </script>
504
- <?php
505
- }
506
-
507
-
508
- /**
509
- * Remove unallowed metaboxes from custom-css-js edit page
510
- *
511
- * Use the custom-css-js-meta-boxes filter to add/remove allowed metaboxdes on the page
512
- */
513
- function remove_unallowed_metaboxes() {
514
- global $wp_meta_boxes;
515
-
516
- // Side boxes
517
- $allowed = array( 'submitdiv', 'custom-code-options' );
518
-
519
- $allowed = apply_filters( 'custom-css-js-meta-boxes', $allowed );
520
-
521
- foreach( $wp_meta_boxes['custom-css-js']['side'] as $_priority => $_boxes ) {
522
- foreach( $_boxes as $_key => $_value ) {
523
- if ( ! in_array( $_key, $allowed ) ) {
524
- unset( $wp_meta_boxes['custom-css-js']['side'][$_priority][$_key] );
525
- }
526
- }
527
- }
528
-
529
- // Normal boxes
530
- $allowed = array( 'slugdiv', 'previewdiv', 'url-rules', 'revisionsdiv' );
531
-
532
- $allowed = apply_filters( 'custom-css-js-meta-boxes-normal', $allowed );
533
-
534
- foreach( $wp_meta_boxes['custom-css-js']['normal'] as $_priority => $_boxes ) {
535
- foreach( $_boxes as $_key => $_value ) {
536
- if ( ! in_array( $_key, $allowed ) ) {
537
- unset( $wp_meta_boxes['custom-css-js']['normal'][$_priority][$_key] );
538
- }
539
- }
540
- }
541
-
542
-
543
- unset($wp_meta_boxes['custom-css-js']['advanced']);
544
- }
545
-
546
-
547
-
548
- /**
549
- * Add the codemirror editor in the `post` screen
550
- */
551
- public function codemirror_editor( $post ) {
552
-
553
-
554
- $current_screen = get_current_screen();
555
-
556
- if ( $current_screen->post_type != 'custom-css-js' ) {
557
- return false;
558
- }
559
-
560
- if ( empty( $post->title ) && empty( $post->post_content ) ) {
561
- $new_post = true;
562
- $post_id = false;
563
- } else {
564
- $new_post = false;
565
- if ( ! isset( $_GET['post'] ) ) $_GET['post'] = $post->id;
566
- $post_id = esc_attr($_GET['post']);
567
- }
568
- $language = $this->get_language($post_id);
569
-
570
- $settings = get_option( 'ccj_settings' );
571
-
572
-
573
- // Replace the htmlentities (https://wordpress.org/support/topic/annoying-bug-in-text-editor/), but only selectively
574
- if ( isset($settings['ccj_htmlentities']) && $settings['ccj_htmlentities'] == 1 && strstr($post->post_content, '&') ) {
575
-
576
- // First the ampresands
577
- $post->post_content = str_replace('&amp', htmlentities('&amp'), $post->post_content );
578
-
579
- // Then the rest of the entities
580
- $html_flags = defined('ENT_HTML5') ? ENT_QUOTES | ENT_HTML5 : ENT_QUOTES;
581
- $entities = get_html_translation_table(HTML_ENTITIES, $html_flags);
582
- unset( $entities[ array_search('&amp;', $entities) ]);
583
- $regular_expression = str_replace(';', '', '/('.implode('|', $entities).')/i');
584
- preg_match_all($regular_expression, $post->post_content, $matches);
585
- if ( isset($matches[0]) && count($matches[0]) > 0 ) {
586
- foreach($matches[0] as $_entity) {
587
- $post->post_content = str_replace($_entity, htmlentities($_entity), $post->post_content);
588
- }
589
- }
590
- }
591
-
592
- if ( isset($settings['ccj_htmlentities2']) && $settings['ccj_htmlentities2'] == 1 ) {
593
- $post->post_content = htmlentities( $post->post_content );
594
- }
595
-
596
- switch ( $language ) {
597
- case 'js' :
598
- if ( $new_post ) {
599
- $post->post_content = __('/* Add your JavaScript code here.
600
 
601
  If you are using the jQuery library, then don\'t forget to wrap your code inside jQuery.ready() as follows:
602
 
@@ -610,15 +614,18 @@ If you want to link a JavaScript file that resides on another server (similar to
610
  <script src="https://example.com/your-js-file.js"></script>), then please use
611
  the "Add HTML Code" page, as this is a HTML code that links a JavaScript file.
612
 
613
- End of comment */ ', 'custom-css-js') . PHP_EOL . PHP_EOL;
614
- }
615
- $code_mirror_mode = 'text/javascript';
616
- $code_mirror_before = '<script type="text/javascript">';
617
- $code_mirror_after = '</script>';
618
- break;
619
- case 'html' :
620
- if ( $new_post ) {
621
- $post->post_content = __('<!-- Add HTML code to the header or the footer.
 
 
 
622
 
623
  For example, you can use the following code for loading the jQuery library from Google CDN:
624
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
@@ -626,25 +633,28 @@ For example, you can use the following code for loading the jQuery library from
626
  or the following one for loading the Bootstrap library from MaxCDN:
627
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
628
 
629
- -- End of the comment --> ', 'custom-css-js') . PHP_EOL . PHP_EOL;
630
- }
631
- $code_mirror_mode = 'html';
632
- $code_mirror_before = '';
633
- $code_mirror_after = '';
634
- break;
635
-
636
- case 'php' :
637
- if ( $new_post ) {
638
- $post->post_content = '/* The following will be executed as if it were written in functions.php. */' . PHP_EOL . PHP_EOL;
639
- }
640
- $code_mirror_mode = 'php';
641
- $code_mirror_before = '<?php';
642
- $code_mirror_after = '?>';
643
-
644
- break;
645
- default :
646
- if ( $new_post ) {
647
- $post->post_content = __('/* Add your CSS code here.
 
 
 
648
 
649
  For example:
650
  .example {
@@ -653,728 +663,757 @@ For example:
653
 
654
  For brushing up on your CSS knowledge, check out http://www.w3schools.com/css/css_syntax.asp
655
 
656
- End of comment */ ', 'custom-css-js') . PHP_EOL . PHP_EOL;
 
 
657
 
658
- }
659
- $code_mirror_mode = 'text/css';
660
- $code_mirror_before = '<style type="text/css">';
661
- $code_mirror_after = '</style>';
662
 
663
- }
664
 
665
- ?>
666
- <form style="position: relative; margin-top: .5em;">
667
 
668
- <div class="code-mirror-before"><div><?php echo htmlentities( $code_mirror_before );?></div></div>
669
- <textarea class="wp-editor-area" id="ccj_content" mode="<?php echo htmlentities($code_mirror_mode); ?>" name="content"><?php echo $post->post_content; ?></textarea>
670
- <div class="code-mirror-after"><div><?php echo htmlentities( $code_mirror_after );?></div></div>
671
 
672
- <table id="post-status-info"><tbody><tr>
673
- <td class="autosave-info">
674
- <span class="autosave-message">&nbsp;</span>
675
- <?php
676
- if ( 'auto-draft' != $post->post_status ) {
677
- echo '<span id="last-edit">';
678
- if ( $last_user = get_userdata( get_post_meta( $post->ID, '_edit_last', true ) ) ) {
679
- printf(__('Last edited by %1$s on %2$s at %3$s', 'custom-css-js-pro'), esc_html( $last_user->display_name ), mysql2date(get_option('date_format'), $post->post_modified), mysql2date(get_option('time_format'), $post->post_modified));
680
- } else {
681
- printf(__('Last edited on %1$s at %2$s', 'custom-css-js-pro'), mysql2date(get_option('date_format'), $post->post_modified), mysql2date(get_option('time_format'), $post->post_modified));
682
- }
683
- echo '</span>';
684
- } ?>
685
- </td>
686
- </tr></tbody></table>
 
687
 
688
 
689
- <input type="hidden" id="update-post_<?php echo $post->ID ?>" value="<?php echo wp_create_nonce('update-post_'. $post->ID ); ?>" />
690
- </form>
691
- <?php
692
 
693
- }
694
 
695
 
696
 
697
- /**
698
- * Show the options form in the `post` screen
699
- */
700
- function custom_code_options_meta_box_callback( $post ) {
701
 
702
- $options = $this->get_options( $post->ID );
703
- if ( ! isset($options['preprocessor'] ) )
704
- $options['preprocessor'] = 'none';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
705
 
706
-
707
- if ( isset( $_GET['language'] ) ) {
708
- $options['language'] = $this->get_language();
709
- }
710
-
711
- $meta = $this->get_options_meta();
712
- if ( $options['language'] == 'html' ) {
713
- $meta = $this->get_options_meta_html();
714
- }
715
-
716
-
717
- wp_nonce_field( 'options_save_meta_box_data', 'custom-css-js_meta_box_nonce' );
718
-
719
- ?>
720
- <div class="options_meta_box">
721
- <?php
722
-
723
- $output = '';
724
-
725
- foreach( $meta as $_key => $a ) {
726
- $close_div = false;
727
-
728
- if ( ($_key == 'preprocessor' && $options['language'] == 'css') ||
729
- ($_key == 'linking' && $options['language'] == 'html') ||
730
- $_key == 'priority' ||
731
- $_key == 'minify' ) {
732
- $close_div = true;
733
- $output .= '<div class="ccj_opaque">';
734
- }
735
-
736
- // Don't show Pre-processors for JavaScript Codes
737
- if ( $options['language'] == 'js' && $_key == 'preprocessor' ) {
738
- continue;
739
- }
740
-
741
- $output .= '<h3>' . $a['title'] . '</h3>' . PHP_EOL;
742
-
743
- $output .= $this->render_input( $_key, $a, $options );
744
-
745
- if ( $close_div ) {
746
- $output .= '</div>';
747
- }
748
-
749
- }
750
-
751
- echo $output;
752
-
753
- ?>
754
-
755
- <input type="hidden" name="custom_code_language" value="<?php echo $options['language']; ?>" />
756
-
757
- <div style="clear: both;"></div>
758
-
759
- </div>
760
-
761
- <div class="ccj_only_premium ccj_only_premium-right">
762
- <div>
763
- <a href="https://www.silkypress.com/simple-custom-css-js-pro/?utm_source=wordpress&utm_campaign=ccj_free&utm_medium=banner" target="_blank"><?php _e('Available only in <br />Simple Custom CSS and JS Pro', 'custom-css-js'); ?></a>
764
- </div>
765
- </div>
766
-
767
-
768
- <?php
769
- }
770
-
771
-
772
- /**
773
- * Get an array with all the information for building the code's options
774
- */
775
- function get_options_meta() {
776
- $options = array(
777
- 'linking' => array(
778
- 'title' => __('Linking type', 'custom-css-js'),
779
- 'type' => 'radio',
780
- 'default' => 'internal',
781
- 'values' => array(
782
- 'external' => array(
783
- 'title' => __('External File', 'custom-css-js'),
784
- 'dashicon' => 'media-code',
785
- ),
786
- 'internal' => array(
787
- 'title' => __('Internal', 'custom-css-js'),
788
- 'dashicon' => 'editor-alignleft',
789
- ),
790
- ),
791
- ),
792
- 'type' => array(
793
- 'title' => __('Where on page', 'custom-css-js'),
794
- 'type' => 'radio',
795
- 'default' => 'header',
796
- 'values' => array(
797
- 'header' => array(
798
- 'title' => __('Header', 'custom-css-js'),
799
- 'dashicon' => 'arrow-up-alt2',
800
- ),
801
- 'footer' => array(
802
- 'title' => __('Footer', 'custom-css-js'),
803
- 'dashicon' => 'arrow-down-alt2',
804
- ),
805
- ),
806
- ),
807
- 'side' => array(
808
- 'title' => __('Where in site', 'custom-css-js'),
809
- 'type' => 'radio',
810
- 'default' => 'frontend',
811
- 'values' => array(
812
- 'frontend' => array(
813
- 'title' => __('In Frontend', 'custom-css-js'),
814
- 'dashicon' => 'tagcloud',
815
- ),
816
- 'admin' => array(
817
- 'title' => __('In Admin', 'custom-css-js'),
818
- 'dashicon' => 'id',
819
- ),
820
- 'login' => array(
821
- 'title' => __('On Login Page', 'custom-css-js'),
822
- 'dashicon' => 'admin-network',
823
- ),
824
- ),
825
- ),
826
- 'preprocessor' => array(
827
- 'title' => __('CSS Preprocessor', 'custom-css-js'),
828
- 'type' => 'radio',
829
- 'default' => 'none',
830
- 'values' => array(
831
- 'none' => array(
832
- 'title' => __('None', 'custom-css-js'),
833
- ),
834
- 'less' => array(
835
- 'title' => __('Less', 'custom-css-js'),
836
- ),
837
- 'sass' => array(
838
- 'title' => __('SASS (only SCSS syntax)', 'custom-css-js'),
839
- ),
840
- ),
841
- 'disabled' => true,
842
- ),
843
- 'minify' => array(
844
- 'title' => __('Minify the code', 'custom-css-js'),
845
- 'type' => 'checkbox',
846
- 'default' => false,
847
- 'dashicon' => 'editor-contract',
848
- 'disabled' => true,
849
- ),
850
- 'priority' => array(
851
- 'title' => __('Priority', 'custom-css-js'),
852
- 'type' => 'select',
853
- 'default' => 5,
854
- 'dashicon' => 'sort',
855
- 'values' => array(
856
- 1 => _x('1 (highest)', '1 is the highest priority', 'custom-css-js'),
857
- 2 => '2',
858
- 3 => '3',
859
- 4 => '4',
860
- 5 => '5',
861
- 6 => '6',
862
- 7 => '7',
863
- 8 => '8',
864
- 9 => '9',
865
- 10 => _x('10 (lowest)', '10 is the lowest priority', 'custom-css-js'),
866
- ),
867
- 'disabled' => true,
868
- ),
869
- );
870
-
871
- return $options;
872
- }
873
-
874
-
875
- /**
876
- * Get an array with all the information for building the code's options
877
- */
878
- function get_options_meta_html() {
879
- $options = array(
880
- 'type' => array(
881
- 'title' => __('Where on page', 'custom-css-js'),
882
- 'type' => 'radio',
883
- 'default' => 'header',
884
- 'values' => array(
885
- 'header' => array(
886
- 'title' => __('Header', 'custom-css-js'),
887
- 'dashicon' => 'arrow-up-alt2',
888
- ),
889
- 'footer' => array(
890
- 'title' => __('Footer', 'custom-css-js'),
891
- 'dashicon' => 'arrow-down-alt2',
892
- ),
893
- ),
894
- ),
895
- 'side' => array(
896
- 'title' => __('Where in site', 'custom-css-js'),
897
- 'type' => 'radio',
898
- 'default' => 'frontend',
899
- 'values' => array(
900
- 'frontend' => array(
901
- 'title' => __('In Frontend', 'custom-css-js'),
902
- 'dashicon' => 'tagcloud',
903
- ),
904
- 'admin' => array(
905
- 'title' => __('In Admin', 'custom-css-js'),
906
- 'dashicon' => 'id',
907
- ),
908
- ),
909
- ),
910
- 'linking' => array(
911
- 'title' => __('On which device', 'custom-css-js'),
912
- 'type' => 'radio',
913
- 'default' => 'both',
914
- 'dashicon' => '',
915
- 'values' => array(
916
- 'desktop' => array(
917
- 'title' => __('Desktop', 'custom-css-js'),
918
- 'dashicon' => 'desktop',
919
- ),
920
- 'mobile' => array(
921
- 'title' => __('Mobile', 'custom-css-js'),
922
- 'dashicon' => 'smartphone',
923
- ),
924
- 'both' => array(
925
- 'title' => __('Both', 'custom-css-js'),
926
- 'dashicon' => 'tablet',
927
- ),
928
- ),
929
- 'disabled' => true,
930
- ),
931
- 'priority' => array(
932
- 'title' => __('Priority', 'custom-css-js'),
933
- 'type' => 'select',
934
- 'default' => 5,
935
- 'dashicon' => 'sort',
936
- 'values' => array(
937
- 1 => _x('1 (highest)', '1 is the highest priority', 'custom-css-js'),
938
- 2 => '2',
939
- 3 => '3',
940
- 4 => '4',
941
- 5 => '5',
942
- 6 => '6',
943
- 7 => '7',
944
- 8 => '8',
945
- 9 => '9',
946
- 10 => _x('10 (lowest)', '10 is the lowest priority', 'custom-css-js'),
947
- ),
948
- 'disabled' => true,
949
- ),
950
-
951
- );
952
-
953
- return $options;
954
- }
955
-
956
-
957
- /**
958
- * Save the post and the metadata
959
- */
960
- function options_save_meta_box_data( $post_id ) {
961
-
962
- // The usual checks
963
- if ( ! isset( $_POST['custom-css-js_meta_box_nonce'] ) ) {
964
- return;
965
- }
966
-
967
- if ( ! wp_verify_nonce( $_POST['custom-css-js_meta_box_nonce'], 'options_save_meta_box_data' ) ) {
968
- return;
969
- }
970
-
971
- if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
972
- return;
973
- }
974
-
975
- if ( isset( $_POST['post_type'] ) && 'custom-css-js' != $_POST['post_type'] ) {
976
- return;
977
- }
978
-
979
- // Update the post's meta
980
- $defaults = array(
981
- 'type' => 'header',
982
- 'linking' => 'internal',
983
- 'priority' => 5,
984
- 'side' => 'frontend',
985
- 'language' => 'css',
986
- );
987
-
988
- if ( $_POST['custom_code_language'] == 'html' ) {
989
- $defaults = array(
990
- 'type' => 'header',
991
- 'linking' => 'both',
992
- 'side' => 'frontend',
993
- 'language' => 'html',
994
- 'priority' => 5,
995
- );
996
- }
997
-
998
- foreach( $defaults as $_field => $_default ) {
999
- $options[ $_field ] = isset( $_POST['custom_code_'.$_field] ) ? esc_attr($_POST['custom_code_'.$_field]) : $_default;
1000
- }
1001
-
1002
- update_post_meta( $post_id, 'options', $options );
1003
-
1004
- if ( $options['language'] == 'html' ) {
1005
- $this->build_search_tree();
1006
- return;
1007
- }
1008
-
1009
- if ( $options['language'] == 'js' ) {
1010
- // Replace the default comment
1011
- if ( preg_match('@/\* Add your JavaScript code here[\s\S]*?End of comment \*/@im', $_POST['content'] ) ) {
1012
- $_POST['content'] = preg_replace('@/\* Add your JavaScript code here[\s\S]*?End of comment \*/@im', '/* Default comment here */', $_POST['content']);
1013
- }
1014
-
1015
- // For other locales remove all the comments
1016
- if ( substr( get_locale(), 0, 3) !== 'en_' ) {
1017
- $_POST['content'] = preg_replace('@/\*[\s\S]*?\*/@', '', $_POST['content']);
1018
- }
1019
- }
1020
-
1021
-
1022
- // Save the Custom Code in a file in `wp-content/uploads/custom-css-js`
1023
- if ( $options['linking'] == 'internal' ) {
1024
-
1025
- $before = '<!-- start Simple Custom CSS and JS -->' . PHP_EOL;
1026
- $after = '<!-- end Simple Custom CSS and JS -->' . PHP_EOL;
1027
- if ( $options['language'] == 'css' ) {
1028
- $before .= '<style type="text/css">' . PHP_EOL;
1029
- $after = '</style>' . PHP_EOL . $after;
1030
- }
1031
- if ( $options['language'] == 'js' ) {
1032
- if ( ! preg_match( '/<script\b[^>]*>([\s\S]*?)<\/script>/im', $_POST['content'] ) ) {
1033
- $before .= '<script type="text/javascript">' . PHP_EOL;
1034
- $after = '</script>' . PHP_EOL . $after;
1035
- } else {
1036
- // the content has a <script> tag, then remove the comments so they don't show up on the frontend
1037
- $_POST['content'] = preg_replace('@/\*[\s\S]*?\*/@', '', $_POST['content']);
1038
- }
1039
- }
1040
- }
1041
-
1042
- if ( $options['linking'] == 'external' ) {
1043
- $before = '/******* Do not edit this file *******' . PHP_EOL .
1044
- 'Simple Custom CSS and JS - by Silkypress.com' . PHP_EOL .
1045
- 'Saved: '.date('M d Y | H:i:s').' */' . PHP_EOL;
1046
- }
1047
-
1048
- if ( wp_is_writable( CCJ_UPLOAD_DIR ) ) {
1049
- $file_name = $post_id . '.' . $options['language'];
1050
- $file_content = $before . stripslashes($_POST['content']) . $after;
1051
- @file_put_contents( CCJ_UPLOAD_DIR . '/' . $file_name , $file_content );
1052
-
1053
- // save the file as the Permalink slug
1054
- $slug = get_post_meta( $post_id, '_slug', true );
1055
- if ( $slug ) {
1056
- @file_put_contents( CCJ_UPLOAD_DIR . '/' . $slug . '.' . $options['language'], $file_content );
1057
- }
1058
- }
1059
-
1060
-
1061
- $this->build_search_tree();
1062
- }
1063
-
1064
- /**
1065
- * Create the custom-css-js dir in uploads directory
1066
- *
1067
- * Show a message if the directory is not writable
1068
- *
1069
- * Create an empty index.php file inside
1070
- */
1071
- function create_uploads_directory() {
1072
- $current_screen = get_current_screen();
1073
-
1074
- // Check if we are editing a custom-css-js post
1075
- if ( $current_screen->base != 'post' || $current_screen->post_type != 'custom-css-js' ) {
1076
- return false;
1077
- }
1078
-
1079
- $dir = CCJ_UPLOAD_DIR;
1080
-
1081
- // Create the dir if it doesn't exist
1082
- if ( ! file_exists( $dir ) ) {
1083
- wp_mkdir_p( $dir );
1084
- }
1085
-
1086
- // Show a message if it couldn't create the dir
1087
- if ( ! file_exists( $dir ) ) : ?>
1088
- <div class="notice notice-error is-dismissible">
1089
- <p><?php printf(__('The %s directory could not be created', 'custom-css-js'), '<b>custom-css-js</b>'); ?></p>
1090
- <p><?php _e('Please run the following commands in order to make the directory', 'custom-css-js'); ?>: <br /><strong>mkdir <?php echo $dir; ?>; </strong><br /><strong>chmod 777 <?php echo $dir; ?>;</strong></p>
1091
- </div>
1092
- <?php return; endif;
1093
-
1094
-
1095
- // Show a message if the dir is not writable
1096
- if ( ! wp_is_writable( $dir ) ) : ?>
1097
- <div class="notice notice-error is-dismissible">
1098
- <p><?php printf(__('The %s directory is not writable, therefore the CSS and JS files cannot be saved.', 'custom-css-js'), '<b>'.$dir.'</b>'); ?></p>
1099
- <p><?php _e('Please run the following command to make the directory writable', 'custom-css-js'); ?>:<br /><strong>chmod 777 <?php echo $dir; ?> </strong></p>
1100
- </div>
1101
- <?php return; endif;
1102
-
1103
-
1104
- // Write a blank index.php
1105
- if ( ! file_exists( $dir. '/index.php' ) ) {
1106
- $content = '<?php' . PHP_EOL . '// Silence is golden.';
1107
- @file_put_contents( $dir. '/index.php', $content );
1108
- }
1109
- }
1110
-
1111
-
1112
- /**
1113
- * Build a tree where you can quickly find the needed custom-css-js posts
1114
- *
1115
- * @return void
1116
- */
1117
- private function build_search_tree() {
1118
-
1119
- // Retrieve all the custom-css-js codes
1120
- $posts = query_posts( 'post_type=custom-css-js&post_status=publish&nopaging=true' );
1121
-
1122
- $tree = array();
1123
- foreach ( $posts as $_post ) {
1124
- if ( ! $this->is_active( $_post->ID ) ) {
1125
- continue;
1126
- }
1127
-
1128
- $options = $this->get_options( $_post->ID );
1129
-
1130
- // Get the branch name, example: frontend-css-header-external
1131
- $tree_branch = $options['side'] . '-' .$options['language'] . '-' . $options['type'] . '-' . $options['linking'];
1132
-
1133
- $filename = $_post->ID . '.' . $options['language'];
1134
-
1135
- if ( $options['linking'] == 'external' ) {
1136
- $filename .= '?v=' . rand(1, 10000);
1137
- }
1138
-
1139
- // Add the code file to the tree branch
1140
- $tree[ $tree_branch ][] = $filename;
1141
-
1142
- }
1143
-
1144
- // Save the tree in the database
1145
- update_option( 'custom-css-js-tree', $tree );
1146
- }
1147
-
1148
- /**
1149
- * Rebuilt the tree when you trash or restore a custom code
1150
- */
1151
- function trash_post( $post_id ) {
1152
- $this->build_search_tree( );
1153
- }
1154
-
1155
-
1156
- /**
1157
- * Render the checkboxes, radios, selects and inputs
1158
- */
1159
- function render_input( $_key, $a, $options ) {
1160
- $name = 'custom_code_' . $_key;
1161
- $output = '';
1162
-
1163
- // Show radio type options
1164
- if ( $a['type'] === 'radio' ) {
1165
- $output .= '<div class="radio-group">' . PHP_EOL;
1166
- foreach( $a['values'] as $__key => $__value ) {
1167
- $selected = '';
1168
- $id = $name . '-' . $__key;
1169
- $dashicons = isset($__value['dashicon'] ) ? 'dashicons-before dashicons-' . $__value['dashicon'] : '';
1170
- if ( isset( $a['disabled'] ) && $a['disabled'] ) {
1171
- $selected = ' disabled="disabled"';
1172
- }
1173
- $selected .= ( $__key == $options[$_key] ) ? ' checked="checked" ' : '';
1174
- $output .= '<input type="radio" '. $selected.'value="'.$__key.'" name="'.$name.'" id="'.$id.'">' . PHP_EOL;
1175
- $output .= '<label class="'.$dashicons.'" for="'.$id.'"> '.$__value['title'].'</label><br />' . PHP_EOL;
1176
- }
1177
- $output .= '</div>' . PHP_EOL;
1178
- }
1179
-
1180
- // Show checkbox type options
1181
- if ( $a['type'] == 'checkbox' ) {
1182
- $dashicons = isset($a['dashicon'] ) ? 'dashicons-before dashicons-' . $a['dashicon'] : '';
1183
- $selected = ( isset($options[$_key]) && $options[$_key] == '1') ? ' checked="checked" ' : '';
1184
- if ( isset( $a['disabled'] ) && $a['disabled'] ) {
1185
- $selected .= ' disabled="disabled"';
1186
- }
1187
- $output .= '<div class="radio-group">' . PHP_EOL;
1188
- $output .= '<input type="checkbox" '.$selected.' value="1" name="'.$name.'" id="'.$name.'">' . PHP_EOL;
1189
- $output .= '<label class="'.$dashicons.'" for="'.$name.'"> '.$a['title'].'</label>';
1190
- $output .= '</div>' . PHP_EOL;
1191
- }
1192
-
1193
-
1194
- // Show select type options
1195
- if ( $a['type'] == 'select' ) {
1196
- $output .= '<div class="radio-group">' . PHP_EOL;
1197
- $output .= '<select name="'.$name.'" id="'.$name.'">' . PHP_EOL;
1198
- foreach( $a['values'] as $__key => $__value ) {
1199
- $selected = ( isset($options[$_key]) && $options[$_key] == $__key) ? ' selected="selected"' : '';
1200
- $output .= '<option value="'.$__key.'"'.$selected.'>' . $__value . '</option>' . PHP_EOL;
1201
- }
1202
- $output .= '</select>' . PHP_EOL;
1203
- $output .= '</div>' . PHP_EOL;
1204
- }
1205
-
1206
-
1207
- return $output;
1208
-
1209
- }
1210
-
1211
-
1212
- /**
1213
- * Get the language for the current post
1214
- */
1215
- function get_language( $post_id = false ) {
1216
- if( $post_id !== false ) {
1217
- $options = $this->get_options( $post_id );
1218
- $language = $options['language'];
1219
- } else {
1220
- $language = isset( $_GET['language'] ) ? esc_attr(strtolower($_GET['language'])) : 'css';
1221
- }
1222
- if ( !in_array($language, array('css', 'js', 'html'))) $language = 'css';
1223
-
1224
- return $language;
1225
- }
1226
-
1227
-
1228
- /**
1229
- * Show the activate/deactivate link in the row's action area
1230
- */
1231
- function post_row_actions($actions, $post) {
1232
- if ( 'custom-css-js' !== $post->post_type ) {
1233
- return $actions;
1234
- }
1235
-
1236
- $url = wp_nonce_url( admin_url( 'admin-ajax.php?action=ccj_active_code&code_id=' . $post->ID), 'ccj-active-code-'. $post->ID );
1237
- if ( $this->is_active( $post->ID) ) {
1238
- $active_title = __('The code is active. Click to deactivate it', 'custom-css-js');
1239
- $active_text = __('Deactivate', 'custom-css-js');
1240
- } else {
1241
- $active_title = __('The code is inactive. Click to activate it', 'custom-css-js');
1242
- $active_text = __('Activate', 'custom-css-js');
1243
- }
1244
- $actions['activate'] = '<a href="' . esc_url( $url ) . '" title="'. $active_title . '" class="ccj_activate_deactivate" data-code-id="'.$post->ID.'">' . $active_text . '</a>';
1245
-
1246
- return $actions;
1247
- }
1248
-
1249
-
1250
- /**
1251
- * Show the activate/deactivate link in admin.
1252
- */
1253
- public function post_submitbox_start() {
1254
- global $post;
1255
-
1256
- if ( ! is_object( $post ) ) return;
1257
-
1258
- if ( 'custom-css-js' !== $post->post_type ) return;
1259
-
1260
- if ( !isset( $_GET['post'] ) ) return;
1261
-
1262
- $url = wp_nonce_url( admin_url( 'admin-ajax.php?action=ccj_active_code&code_id=' . $post->ID), 'ccj-active-code-'. $post->ID );
1263
-
1264
-
1265
- if ( $this->is_active( $post->ID) ) {
1266
- $text = __('Active', 'custom-css-js');
1267
- $action = __('Deactivate', 'custom-css-js');
1268
- } else {
1269
- $text = __('Inactive', 'custom-css-js');
1270
- $action = __('Activate', 'custom-css-js');
1271
- }
1272
- ?>
1273
- <div id="activate-action"><span style="font-weight: bold;"><?php echo $text; ?></span>
1274
- (<a class="ccj_activate_deactivate" data-code-id="<?php echo $post->ID; ?>" href="<?php echo esc_url( $url ); ?>"><?php echo $action ?></a>)
1275
- </div>
1276
- <?php
1277
- }
1278
-
1279
-
1280
- /**
1281
- * Show the Permalink edit form
1282
- */
1283
- function edit_form_before_permalink($filename = '', $permalink = '', $filetype = 'css') {
1284
- if ( isset($_GET['language'] ) ) $filetype = $_GET['language'];
1285
-
1286
- if ( !is_string($filename) ) {
1287
- global $post;
1288
- if ( ! is_object( $post ) ) return;
1289
- if ( 'custom-css-js' !== $post->post_type ) return;
1290
-
1291
- $post = $filename;
1292
- $slug = get_post_meta( $post->ID, '_slug', true );
1293
- $options = get_post_meta( $post->ID, 'options', true );
1294
- if ( isset($options['language'] ) ) $filetype = $options['language'];
1295
- if ( ! @file_exists( CCJ_UPLOAD_DIR . '/' . $slug . '.' . $options['language'] ) ) {
1296
- $slug = false;
1297
- }
1298
- $filename = ( $slug ) ? $slug : $post->ID;
1299
- }
1300
-
1301
- if ( ! in_array( $filetype, array( 'css', 'js' ) ) ) return;
1302
- if ( empty( $permalink ) ) {
1303
- $permalink = CCJ_UPLOAD_URL. '/' . $filename . '.' . $filetype;
1304
- }
1305
-
1306
- ?>
1307
- <div class="inside">
1308
- <div id="edit-slug-box" class="hide-if-no-js">
1309
- <strong>Permalink:</strong>
1310
- <span id="sample-permalink"><a href="<?php echo esc_url($permalink); ?>"><?php echo esc_html(CCJ_UPLOAD_URL ) . '/'; ?><span id="editable-post-name"><?php echo esc_html( $filename ); ?></span>.<?php echo esc_html($filetype); ?></a></span>
1311
- &lrm;<span id="ccj-edit-slug-buttons"><button type="button" class="ccj-edit-slug button button-small hide-if-no-js" aria-label="Edit permalink">Edit</button></span>
1312
- <span id="editable-post-name-full"><?php echo esc_html($filename); ?></span>
1313
- </div>
1314
- <?php wp_nonce_field( 'ccj-permalink', 'ccj-permalink-nonce' ); ?>
1315
- </div>
1316
- <?php
1317
- }
1318
-
1319
-
1320
- /**
1321
- * AJAX save the Permalink slug
1322
- */
1323
- function wp_ajax_ccj_permalink() {
1324
-
1325
- if ( ! isset( $_POST['ccj_permalink_nonce'] ) ) return;
1326
-
1327
- if ( ! wp_verify_nonce( $_POST['ccj_permalink_nonce'], 'ccj-permalink') ) return;
1328
-
1329
- $code_id = isset($_POST['code_id'])? intval($_POST['code_id']) : 0;
1330
- $permalink = isset($_POST['permalink'])? $_POST['permalink'] : null;
1331
- $slug = isset($_POST['new_slug'])? trim(sanitize_file_name($_POST['new_slug'])) : null;
1332
- $filetype = isset($_POST['filetype'])? $_POST['filetype'] : 'css';
1333
- if ( empty($slug ) ) {
1334
- $slug = (string)$code_id;
1335
- } else {
1336
- update_post_meta( $code_id, '_slug', $slug);
1337
- }
1338
- $this->edit_form_before_permalink( $slug, $permalink, $filetype );
1339
-
1340
- wp_die();
1341
- }
1342
-
1343
-
1344
- /**
1345
- * Remove the JS/CSS file from the disk when deleting the post
1346
- */
1347
- function before_delete_post( $postid ) {
1348
- global $post;
1349
- if ( ! is_object( $post ) ) return;
1350
- if ( 'custom-css-js' !== $post->post_type ) return;
1351
- if ( ! wp_is_writable( CCJ_UPLOAD_DIR ) ) return;
1352
-
1353
- $options = get_post_meta( $postid, 'options', true );
1354
- $slug = get_post_meta( $postid, '_slug', true );
1355
- $file_name = $postid . '.' . $options['language'];
1356
-
1357
- @unlink( CCJ_UPLOAD_DIR . '/' . $file_name );
1358
-
1359
- if ( !empty( $slug ) ) {
1360
- @unlink( CCJ_UPLOAD_DIR . '/' . $slug . '.' . $options['language'] );
1361
- }
1362
- }
1363
-
1364
-
1365
- /**
1366
- * Fix for bug: white page Edit Custom Code for WordPress 5.0 with Classic Editor
1367
- */
1368
- function current_screen_2() {
1369
- $screen = get_current_screen();
1370
-
1371
- if ( $screen->post_type != 'custom-css-js' )
1372
- return false;
1373
-
1374
- remove_filter( 'use_block_editor_for_post', array( 'Classic_Editor', 'choose_editor' ), 100, 2 );
1375
- add_filter( 'use_block_editor_for_post', '__return_false', 100 );
1376
- add_filter( 'use_block_editor_for_post_type', '__return_false', 100 );
1377
- }
1378
  }
1379
 
1380
  return new CustomCSSandJS_Admin();
1
  <?php
2
  /**
3
  * Custom CSS and JS
 
4
  */
5
 
6
  if ( ! defined( 'ABSPATH' ) ) {
7
+ exit; // Exit if accessed directly
8
  }
9
 
10
  /**
12
  */
13
  class CustomCSSandJS_Admin {
14
 
15
+ /**
16
+ * Default options for a new page
17
+ */
18
+ private $default_options = array(
19
+ 'type' => 'header',
20
+ 'linking' => 'internal',
21
+ 'side' => 'frontend',
22
+ 'priority' => 5,
23
+ 'language' => 'css',
24
+ );
25
+
26
+ /**
27
+ * Array with the options for a specific custom-css-js post
28
+ */
29
+ private $options = array();
30
+
31
+ /**
32
+ * Constructor
33
+ */
34
+ public function __construct() {
35
+
36
+ $this->add_functions();
37
+ }
38
+
39
+ /**
40
+ * Add actions and filters
41
+ */
42
+ function add_functions() {
43
+
44
+ // Add filters
45
+ $filters = array(
46
+ 'manage_custom-css-js_posts_columns' => 'manage_custom_posts_columns',
47
+ );
48
+ foreach ( $filters as $_key => $_value ) {
49
+ add_filter( $_key, array( $this, $_value ) );
50
+ }
51
+
52
+ // Add actions
53
+ $actions = array(
54
+ 'admin_menu' => 'admin_menu',
55
+ 'admin_enqueue_scripts' => 'admin_enqueue_scripts',
56
+ 'current_screen' => 'current_screen',
57
+ 'admin_notices' => 'create_uploads_directory',
58
+ 'edit_form_after_title' => 'codemirror_editor',
59
+ 'add_meta_boxes' => 'add_meta_boxes',
60
+ 'save_post' => 'options_save_meta_box_data',
61
+ 'trashed_post' => 'trash_post',
62
+ 'untrashed_post' => 'trash_post',
63
+ 'wp_ajax_ccj_active_code' => 'wp_ajax_ccj_active_code',
64
+ 'wp_ajax_ccj_permalink' => 'wp_ajax_ccj_permalink',
65
+ 'post_submitbox_start' => 'post_submitbox_start',
66
+ 'restrict_manage_posts' => 'restrict_manage_posts',
67
+ 'edit_form_before_permalink' => 'edit_form_before_permalink',
68
+ 'before_delete_post' => 'before_delete_post',
69
+ );
70
+ foreach ( $actions as $_key => $_value ) {
71
+ add_action( $_key, array( $this, $_value ) );
72
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
+ // Add some custom actions/filters
75
+ add_action( 'manage_custom-css-js_posts_custom_column', array( $this, 'manage_posts_columns' ), 10, 2 );
76
+ add_filter( 'manage_edit-custom-css-js_sortable_columns', array( $this, 'manage_edit_posts_sortable_columns' ) );
77
+ add_filter( 'post_row_actions', array( $this, 'post_row_actions' ), 10, 2 );
78
+ add_filter( 'parse_query', array( $this, 'parse_query' ), 10 );
79
 
80
+ add_action( 'current_screen', array( $this, 'current_screen_2' ), 100 );
 
 
 
81
 
82
+ }
 
 
 
 
 
 
 
83
 
84
+
85
+ /**
86
+ * Add submenu pages
87
+ */
88
+ function admin_menu() {
89
+ $menu_slug = 'edit.php?post_type=custom-css-js';
90
+ $submenu_slug = 'post-new.php?post_type=custom-css-js';
91
+
92
+ remove_submenu_page( $menu_slug, $submenu_slug );
93
+
94
+ $title = __( 'Add Custom CSS', 'custom-css-js' );
95
+ add_submenu_page( $menu_slug, $title, $title, 'publish_custom_csss', $submenu_slug . '&language=css' );
96
+
97
+ $title = __( 'Add Custom JS', 'custom-css-js' );
98
+ add_submenu_page( $menu_slug, $title, $title, 'publish_custom_csss', $submenu_slug . '&language=js' );
99
+
100
+ $title = __( 'Add Custom HTML', 'custom-css-js' );
101
+ add_submenu_page( $menu_slug, $title, $title, 'publish_custom_csss', $submenu_slug . '&language=html' );
102
+
103
+ }
104
+
105
+
106
+ /**
107
+ * Enqueue the scripts and styles
108
+ */
109
+ public function admin_enqueue_scripts( $hook ) {
110
+
111
+ $screen = get_current_screen();
112
+
113
+ // Only for custom-css-js post type
114
+ if ( $screen->post_type != 'custom-css-js' ) {
115
+ return false;
116
+ }
117
+
118
+ // Some handy variables
119
+ $a = plugins_url( '/', CCJ_PLUGIN_FILE ) . 'assets';
120
+ $cm = $a . '/codemirror';
121
+ $v = CCJ_VERSION;
122
+
123
+ wp_register_script( 'ccj-admin', $a . '/ccj_admin.js', array( 'jquery', 'jquery-ui-resizable' ), $v, false );
124
+ wp_localize_script( 'ccj-admin', 'CCJ', $this->cm_localize() );
125
+ wp_enqueue_script( 'ccj-admin' );
126
+ wp_enqueue_style( 'ccj-admin', $a . '/ccj_admin.css', array(), $v );
127
+
128
+ // Only for the new/edit Code's page
129
+ if ( $hook == 'post-new.php' || $hook == 'post.php' ) {
130
+ wp_deregister_script( 'wp-codemirror' );
131
+
132
+ wp_enqueue_style( 'jquery-ui', 'https://code.jquery.com/ui/1.12.0/themes/base/jquery-ui.css', array(), $v );
133
+ wp_enqueue_script( 'ccj-codemirror', $cm . '/lib/codemirror.js', array( 'jquery' ), $v, false );
134
+ wp_enqueue_style( 'ccj-codemirror', $cm . '/lib/codemirror.css', array(), $v );
135
+ wp_enqueue_script( 'ccj-admin_url_rules', $a . '/ccj_admin-url_rules.js', array( 'jquery' ), $v, false );
136
+
137
+ // Add the language modes
138
+ $cmm = $cm . '/mode/';
139
+ wp_enqueue_script( 'cm-xml', $cmm . 'xml/xml.js', array( 'ccj-codemirror' ), $v, false );
140
+ wp_enqueue_script( 'cm-js', $cmm . 'javascript/javascript.js', array( 'ccj-codemirror' ), $v, false );
141
+ wp_enqueue_script( 'cm-css', $cmm . 'css/css.js', array( 'ccj-codemirror' ), $v, false );
142
+ wp_enqueue_script( 'cm-htmlmixed', $cmm . 'htmlmixed/htmlmixed.js', array( 'ccj-codemirror' ), $v, false );
143
+
144
+ $cma = $cm . '/addon/';
145
+ wp_enqueue_script( 'ccj-closebrackets', $cma . 'edit/closebrackets.js', array( 'ccj-codemirror' ), $v, false );
146
+ wp_enqueue_script( 'cm-dialog', $cma . 'dialog/dialog.js', array( 'ccj-codemirror' ), $v, false );
147
+ wp_enqueue_script( 'cm-search', $cma . 'search/search.js', array( 'ccj-codemirror' ), $v, false );
148
+ wp_enqueue_script( 'cm-searchcursor', $cma . 'search/searchcursor.js', array( 'ccj-codemirror' ), $v, false );
149
+ wp_enqueue_script( 'cm-jump-to-line', $cma . 'search/jump-to-line.js', array( 'ccj-codemirror' ), $v, false );
150
+ wp_enqueue_style( 'cm-dialog', $cma . 'dialog/dialog.css', array(), $v );
151
+
152
+ // remove the assets from other plugins so it doesn't interfere with CodeMirror
153
+ global $wp_scripts;
154
+ if ( is_array( $wp_scripts->registered ) && count( $wp_scripts->registered ) != 0 ) {
155
+ foreach ( $wp_scripts->registered as $_key => $_value ) {
156
+ if ( ! isset( $_value->src ) ) {
157
+ continue;
158
+ }
159
+
160
+ if ( strstr( $_value->src, 'wp-content/plugins' ) !== false
161
+ && strstr( $_value->src, 'plugins/custom-css-js/assets' ) === false
162
+ && strstr( $_value->src, 'plugins/advanced-custom-fields/' ) === false
163
+ && strstr( $_value->src, 'plugins/advanced-custom-fields-pro/' ) === false ) {
164
+ unset( $wp_scripts->registered[ $_key ] );
165
+ }
166
+ }
167
+ }
168
+ }
169
+ }
170
+
171
+
172
+ /**
173
+ * Send variables to the ccj_admin.js script
174
+ */
175
+ public function cm_localize() {
176
+
177
+ $vars = array(
178
+ 'active' => __( 'Active', 'custom-css-js' ),
179
+ 'inactive' => __( 'Inactive', 'custom-css-js' ),
180
+ 'activate' => __( 'Activate', 'custom-css-js' ),
181
+ 'deactivate' => __( 'Deactivate', 'custom-css-js' ),
182
+ 'active_title' => __( 'The code is active. Click to deactivate it', 'custom-css-js' ),
183
+ 'deactive_title' => __( 'The code is inactive. Click to activate it', 'custom-css-js' ),
184
+ );
185
+
186
+ return $vars;
187
+ }
188
+
189
+ public function add_meta_boxes() {
190
+ add_meta_box( 'custom-code-options', __( 'Options', 'custom-css-js' ), array( $this, 'custom_code_options_meta_box_callback' ), 'custom-css-js', 'side', 'low' );
191
+
192
+ remove_meta_box( 'slugdiv', 'custom-css-js', 'normal' );
193
+ }
194
+
195
+
196
+
197
+ /**
198
+ * Get options for a specific custom-css-js post
199
+ */
200
+ private function get_options( $post_id ) {
201
+ if ( isset( $this->options[ $post_id ] ) ) {
202
+ return $this->options[ $post_id ];
203
+ }
204
+
205
+ $options = get_post_meta( $post_id );
206
+ if ( empty( $options ) || ! isset( $options['options'][0] ) ) {
207
+ $this->options[ $post_id ] = $this->default_options;
208
+ return $this->default_options;
209
+ }
210
+
211
+ $options = unserialize( $options['options'][0] );
212
+ $this->options[ $post_id ] = $options;
213
+ return $options;
214
+ }
215
+
216
+
217
+ /**
218
+ * Reformat the `edit` or the `post` screens
219
+ */
220
+ function current_screen( $current_screen ) {
221
+
222
+ if ( $current_screen->post_type != 'custom-css-js' ) {
223
+ return false;
224
+ }
225
+
226
+ if ( $current_screen->base == 'post' ) {
227
+ add_action( 'admin_head', array( $this, 'current_screen_post' ) );
228
+ }
229
+
230
+ if ( $current_screen->base == 'edit' ) {
231
+ add_action( 'admin_head', array( $this, 'current_screen_edit' ) );
232
+ }
233
+
234
+ wp_deregister_script( 'autosave' );
235
+ }
236
+
237
+
238
+
239
+ /**
240
+ * Add the buttons in the `edit` screen
241
+ */
242
+ function add_new_buttons() {
243
+ $current_screen = get_current_screen();
244
+
245
+ if ( ( isset( $current_screen->action ) && $current_screen->action == 'add' ) || $current_screen->post_type != 'custom-css-js' ) {
246
+ return false;
247
+ }
248
+ ?>
249
+ <div class="updated buttons">
250
+ <a href="post-new.php?post_type=custom-css-js&language=css" class="custom-btn custom-css-btn"><?php _e( 'Add CSS code', 'custom-css-js' ); ?></a>
251
+ <a href="post-new.php?post_type=custom-css-js&language=js" class="custom-btn custom-js-btn"><?php _e( 'Add JS code', 'custom-css-js' ); ?></a>
252
+ <a href="post-new.php?post_type=custom-css-js&language=html" class="custom-btn custom-js-btn"><?php _e( 'Add HTML code', 'custom-css-js' ); ?></a>
253
+ <!-- a href="post-new.php?post_type=custom-css-js&language=php" class="custom-btn custom-php-btn">Add PHP code</a -->
254
+ </div>
255
+ <?php
256
+ }
257
+
258
+
259
+
260
+ /**
261
+ * Add new columns in the `edit` screen
262
+ */
263
+ function manage_custom_posts_columns( $columns ) {
264
+ return array(
265
+ 'cb' => '<input type="checkbox" />',
266
+ 'active' => '<span class="ccj-dashicons dashicons dashicons-star-empty" title="' . __( 'Active', 'custom-css-js' ) . '"></span>',
267
+ 'type' => __( 'Type', 'custom-css-js' ),
268
+ 'title' => __( 'Title' ),
269
+ 'author' => __( 'Author' ),
270
+ 'published' => __( 'Published' ),
271
+ 'modified' => __( 'Modified', 'custom-css-js' ),
272
+ );
273
+ }
274
+
275
+
276
+ /**
277
+ * Fill the data for the new added columns in the `edit` screen
278
+ */
279
+ function manage_posts_columns( $column, $post_id ) {
280
+
281
+ if ( 'type' === $column ) {
282
+ $options = $this->get_options( $post_id );
283
+ echo '<span class="language language-' . $options['language'] . '">' . $options['language'] . '</span>';
284
+ }
285
+
286
+ if ( 'modified' === $column || 'published' === $column ) {
287
+ $post = get_post( $post_id );
288
+
289
+ if ( '0000-00-00 00:00:00' === $post->post_date ) {
290
+ $t_time = __( 'Unpublished' );
291
+ $h_time = $t_time;
292
+ $time_diff = 0;
293
+ } else {
294
+ $time = ( 'published' === $column ) ? get_post_time( 'U', false, $post ) : get_post_modified_time( 'U', false, $post );
295
+ $time_diff = time() - $time;
296
+
297
+ if ( $time && $time_diff > 0 && $time_diff < DAY_IN_SECONDS ) {
298
+ /* translators: %s: Human-readable time difference. */
299
+ $h_time = sprintf( __( '%s ago' ), human_time_diff( $time ) );
300
+ } else {
301
+ $h_time = ( 'published' === $column ) ? get_the_time( __( 'Y/m/d' ), $post ) : get_the_modified_time( __( 'Y/m/d' ), $post );
302
+ }
303
+ }
304
+
305
+ echo $h_time;
306
+ }
307
+
308
+ if ( 'active' === $column ) {
309
+ $url = wp_nonce_url( admin_url( 'admin-ajax.php?action=ccj_active_code&code_id=' . $post_id ), 'ccj-active-code-' . $post_id );
310
+ if ( $this->is_active( $post_id ) ) {
311
+ $active_title = __( 'The code is active. Click to deactivate it', 'custom-css-js' );
312
+ $active_icon = 'dashicons-star-filled';
313
+ } else {
314
+ $active_title = __( 'The code is inactive. Click to activate it', 'custom-css-js' );
315
+ $active_icon = 'dashicons-star-empty ccj_row';
316
+ }
317
+ echo '<a href="' . esc_url( $url ) . '" class="ccj_activate_deactivate" data-code-id="' . $post_id . '" title="' . $active_title . '">' .
318
+ '<span class="dashicons ' . $active_icon . '"></span>' .
319
+ '</a>';
320
+ }
321
+ }
322
+
323
+
324
+ /**
325
+ * Make the 'Modified' column sortable
326
+ */
327
+ function manage_edit_posts_sortable_columns( $columns ) {
328
+ $columns['modified'] = 'modified';
329
+ $columns['published'] = 'published';
330
+ return $columns;
331
+
332
+ }
333
+
334
+
335
+ /**
336
+ * List table: Change the query in order to filter by code type
337
+ */
338
+ function parse_query( $query ) {
339
+ if ( ! is_admin() || ! $query->is_main_query() ) {
340
+ return $query;
341
+ }
342
+
343
+ if ( ! isset( $query->query['post_type'] ) ) {
344
+ return $query;
345
+ }
346
+
347
+ if ( 'custom-css-js' !== $query->query['post_type'] ) {
348
+ return $query;
349
+ }
350
+
351
+ $filter = filter_input( INPUT_GET, 'language_filter' );
352
+ if ( ! is_string( $filter ) || strlen( $filter ) == 0 ) {
353
+ return $query;
354
+ }
355
+
356
+ global $wpdb;
357
+ $post_id_query = "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value LIKE %s";
358
+ $post_ids = $wpdb->get_col( $wpdb->prepare( $post_id_query, 'options', '%' . $filter . '%' ) );
359
+ if ( ! is_array( $post_ids ) || count( $post_ids ) == 0 ) {
360
+ $post_ids = array( -1 );
361
+ }
362
+ $query->query_vars['post__in'] = $post_ids;
363
+
364
+ return $query;
365
+ }
366
+
367
+
368
+ /**
369
+ * List table: add a filter by code type
370
+ */
371
+ function restrict_manage_posts( $post_type ) {
372
+ if ( 'custom-css-js' !== $post_type ) {
373
+ return;
374
+ }
375
+
376
+ $languages = array(
377
+ 'css' => __( 'CSS Codes', 'custom-cs-js' ),
378
+ 'js' => __( 'JS Codes', 'custom-css-js' ),
379
+ 'html' => __( 'HTML Codes', 'custom-css-js' ),
380
+ );
381
 
382
  echo '<label class="screen-reader-text" for="custom-css-js-filter">' . esc_html__( 'Filter Code Type', 'custom-css-js' ) . '</label>';
383
  echo '<select name="language_filter" id="custom-css-js-filter">';
384
+ echo '<option value="">' . __( 'All Custom Codes', 'custom-css-js' ) . '</option>';
385
  foreach ( $languages as $_lang => $_label ) {
386
+ $selected = selected( filter_input( INPUT_GET, 'language_filter' ), $_lang, false );
387
+ echo '<option ' . $selected . ' value="' . $_lang . '">' . $_label . '</option>';
388
  }
389
  echo '</select>';
390
+ }
391
 
392
 
393
+ /**
394
+ * Activate/deactivate a code
395
+ *
396
+ * @return void
397
+ */
398
+ function wp_ajax_ccj_active_code() {
399
+ if ( ! isset( $_GET['code_id'] ) ) {
400
+ die();
401
+ }
402
 
403
+ $code_id = absint( $_GET['code_id'] );
404
 
405
+ $response = 'error';
406
+ if ( check_admin_referer( 'ccj-active-code-' . $code_id ) ) {
407
 
408
  if ( 'custom-css-js' === get_post_type( $code_id ) ) {
409
+ $active = get_post_meta( $code_id, '_active', true );
410
+ if ( $active === false || $active === '' ) {
411
+ $active = 'yes';
412
+ }
413
+ $response = $active;
414
  update_post_meta( $code_id, '_active', $active === 'yes' ? 'no' : 'yes' );
415
 
416
+ $this->build_search_tree();
417
  }
418
  }
419
+ echo $response;
420
 
421
  die();
422
+ }
423
+
424
+ /**
425
+ * Check if a code is active
426
+ *
427
+ * @return bool
428
+ */
429
+ function is_active( $post_id ) {
430
+ return get_post_meta( $post_id, '_active', true ) !== 'no';
431
+ }
432
+
433
+ /**
434
+ * Reformat the `edit` screen
435
+ */
436
+ function current_screen_edit() {
437
+ ?>
438
+ <script type="text/javascript">
439
+ /* <![CDATA[ */
440
+ jQuery(window).ready(function($){
441
+ var h1 = '<?php _e( 'Custom Code', 'custom-css-js' ); ?> ';
442
+ h1 += '<a href="post-new.php?post_type=custom-css-js&language=css" class="page-title-action"><?php _e( 'Add CSS Code', 'custom-css-js' ); ?></a>';
443
+ h1 += '<a href="post-new.php?post_type=custom-css-js&language=js" class="page-title-action"><?php _e( 'Add JS Code', 'custom-css-js' ); ?></a>';
444
+ h1 += '<a href="post-new.php?post_type=custom-css-js&language=html" class="page-title-action"><?php _e( 'Add HTML Code', 'custom-css-js' ); ?></a>';
445
+ $("#wpbody-content h1").html(h1);
446
+ });
447
+
448
+ </script>
449
+ <?php
450
+ }
451
+
452
+
453
+ /**
454
+ * Reformat the `post` screen
455
+ */
456
+ function current_screen_post() {
457
+
458
+ $this->remove_unallowed_metaboxes();
459
+
460
+ $strings = array(
461
+ 'Add CSS Code' => __( 'Add CSS Code', 'custom-css-js' ),
462
+ 'Add JS Code' => __( 'Add JS Code', 'custom-css-js' ),
463
+ 'Add HTML Code' => __( 'Add HTML Code', 'custom-css-js' ),
464
+ 'Edit CSS Code' => __( 'Edit CSS Code', 'custom-css-js' ),
465
+ 'Edit JS Code' => __( 'Edit JS Code', 'custom-css-js' ),
466
+ 'Edit HTML Code' => __( 'Edit HTML Code', 'custom-css-js' ),
467
+ );
468
+
469
+ if ( isset( $_GET['post'] ) ) {
470
+ $action = 'Edit';
471
+ $post_id = esc_attr( $_GET['post'] );
472
+ } else {
473
+ $action = 'Add';
474
+ $post_id = false;
475
+ }
476
+ $language = $this->get_language( $post_id );
477
+
478
+ $title = $action . ' ' . strtoupper( $language ) . ' Code';
479
+ $title = ( isset( $strings[ $title ] ) ) ? $strings[ $title ] : $strings['Add CSS Code'];
480
+
481
+ if ( $action == 'Edit' ) {
482
+ $title .= ' <a href="post-new.php?post_type=custom-css-js&language=css" class="page-title-action">' . __( 'Add CSS Code', 'custom-css-js' ) . '</a> ';
483
+ $title .= '<a href="post-new.php?post_type=custom-css-js&language=js" class="page-title-action">' . __( 'Add JS Code', 'custom-css-js' ) . '</a>';
484
+ $title .= '<a href="post-new.php?post_type=custom-css-js&language=html" class="page-title-action">' . __( 'Add HTML Code', 'custom-css-js' ) . '</a>';
485
+ }
486
+
487
+ ?>
488
+ <style type="text/css">
489
+ #post-body-content, .edit-form-section { position: static !important; }
490
+ #ed_toolbar { display: none; }
491
+ #postdivrich { display: none; }
492
+ </style>
493
+ <script type="text/javascript">
494
+ /* <![CDATA[ */
495
+ jQuery(window).ready(function($){
496
+ $("#wpbody-content h1").html('<?php echo $title; ?>');
497
+ $("#message.updated.notice").html('<p><?php _e( 'Code updated', 'custom-css-js' ); ?></p>');
498
+
499
+ var from_top = -$("#normal-sortables").height();
500
+ if ( from_top != 0 ) {
501
+ $(".ccj_only_premium-first").css('margin-top', from_top.toString() + 'px' );
502
+ } else {
503
+ $(".ccj_only_premium-first").hide();
504
+ }
505
+ });
506
+ /* ]]> */
507
+ </script>
508
+ <?php
509
+ }
510
+
511
+
512
+ /**
513
+ * Remove unallowed metaboxes from custom-css-js edit page
514
+ *
515
+ * Use the custom-css-js-meta-boxes filter to add/remove allowed metaboxdes on the page
516
+ */
517
+ function remove_unallowed_metaboxes() {
518
+ global $wp_meta_boxes;
519
+
520
+ // Side boxes
521
+ $allowed = array( 'submitdiv', 'custom-code-options' );
522
+
523
+ $allowed = apply_filters( 'custom-css-js-meta-boxes', $allowed );
524
+
525
+ foreach ( $wp_meta_boxes['custom-css-js']['side'] as $_priority => $_boxes ) {
526
+ foreach ( $_boxes as $_key => $_value ) {
527
+ if ( ! in_array( $_key, $allowed ) ) {
528
+ unset( $wp_meta_boxes['custom-css-js']['side'][ $_priority ][ $_key ] );
529
+ }
530
+ }
531
+ }
532
+
533
+ // Normal boxes
534
+ $allowed = array( 'slugdiv', 'previewdiv', 'url-rules', 'revisionsdiv' );
535
+
536
+ $allowed = apply_filters( 'custom-css-js-meta-boxes-normal', $allowed );
537
+
538
+ foreach ( $wp_meta_boxes['custom-css-js']['normal'] as $_priority => $_boxes ) {
539
+ foreach ( $_boxes as $_key => $_value ) {
540
+ if ( ! in_array( $_key, $allowed ) ) {
541
+ unset( $wp_meta_boxes['custom-css-js']['normal'][ $_priority ][ $_key ] );
542
+ }
543
+ }
544
+ }
545
+
546
+ unset( $wp_meta_boxes['custom-css-js']['advanced'] );
547
+ }
548
+
549
+
550
+
551
+ /**
552
+ * Add the codemirror editor in the `post` screen
553
+ */
554
+ public function codemirror_editor( $post ) {
555
+
556
+ $current_screen = get_current_screen();
557
+
558
+ if ( $current_screen->post_type != 'custom-css-js' ) {
559
+ return false;
560
+ }
561
+
562
+ if ( empty( $post->title ) && empty( $post->post_content ) ) {
563
+ $new_post = true;
564
+ $post_id = false;
565
+ } else {
566
+ $new_post = false;
567
+ if ( ! isset( $_GET['post'] ) ) {
568
+ $_GET['post'] = $post->id;
569
+ }
570
+ $post_id = esc_attr( $_GET['post'] );
571
+ }
572
+ $language = $this->get_language( $post_id );
573
+
574
+ $settings = get_option( 'ccj_settings' );
575
+
576
+ // Replace the htmlentities (https://wordpress.org/support/topic/annoying-bug-in-text-editor/), but only selectively
577
+ if ( isset( $settings['ccj_htmlentities'] ) && $settings['ccj_htmlentities'] == 1 && strstr( $post->post_content, '&' ) ) {
578
+
579
+ // First the ampresands
580
+ $post->post_content = str_replace( '&amp', htmlentities( '&amp' ), $post->post_content );
581
+
582
+ // Then the rest of the entities
583
+ $html_flags = defined( 'ENT_HTML5' ) ? ENT_QUOTES | ENT_HTML5 : ENT_QUOTES;
584
+ $entities = get_html_translation_table( HTML_ENTITIES, $html_flags );
585
+ unset( $entities[ array_search( '&amp;', $entities ) ] );
586
+ $regular_expression = str_replace( ';', '', '/(' . implode( '|', $entities ) . ')/i' );
587
+ preg_match_all( $regular_expression, $post->post_content, $matches );
588
+ if ( isset( $matches[0] ) && count( $matches[0] ) > 0 ) {
589
+ foreach ( $matches[0] as $_entity ) {
590
+ $post->post_content = str_replace( $_entity, htmlentities( $_entity ), $post->post_content );
591
+ }
592
+ }
593
+ }
594
+
595
+ if ( isset( $settings['ccj_htmlentities2'] ) && $settings['ccj_htmlentities2'] == 1 ) {
596
+ $post->post_content = htmlentities( $post->post_content );
597
+ }
598
+
599
+ switch ( $language ) {
600
+ case 'js':
601
+ if ( $new_post ) {
602
+ $post->post_content = __(
603
+ '/* Add your JavaScript code here.
604
 
605
  If you are using the jQuery library, then don\'t forget to wrap your code inside jQuery.ready() as follows:
606
 
614
  <script src="https://example.com/your-js-file.js"></script>), then please use
615
  the "Add HTML Code" page, as this is a HTML code that links a JavaScript file.
616
 
617
+ End of comment */ ',
618
+ 'custom-css-js'
619
+ ) . PHP_EOL . PHP_EOL;
620
+ }
621
+ $code_mirror_mode = 'text/javascript';
622
+ $code_mirror_before = '<script type="text/javascript">';
623
+ $code_mirror_after = '</script>';
624
+ break;
625
+ case 'html':
626
+ if ( $new_post ) {
627
+ $post->post_content = __(
628
+ '<!-- Add HTML code to the header or the footer.
629
 
630
  For example, you can use the following code for loading the jQuery library from Google CDN:
631
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
633
  or the following one for loading the Bootstrap library from MaxCDN:
634
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
635
 
636
+ -- End of the comment --> ',
637
+ 'custom-css-js'
638
+ ) . PHP_EOL . PHP_EOL;
639
+ }
640
+ $code_mirror_mode = 'html';
641
+ $code_mirror_before = '';
642
+ $code_mirror_after = '';
643
+ break;
644
+
645
+ case 'php':
646
+ if ( $new_post ) {
647
+ $post->post_content = '/* The following will be executed as if it were written in functions.php. */' . PHP_EOL . PHP_EOL;
648
+ }
649
+ $code_mirror_mode = 'php';
650
+ $code_mirror_before = '<?php';
651
+ $code_mirror_after = '?>';
652
+
653
+ break;
654
+ default:
655
+ if ( $new_post ) {
656
+ $post->post_content = __(
657
+ '/* Add your CSS code here.
658
 
659
  For example:
660
  .example {
663
 
664
  For brushing up on your CSS knowledge, check out http://www.w3schools.com/css/css_syntax.asp
665
 
666
+ End of comment */ ',
667
+ 'custom-css-js'
668
+ ) . PHP_EOL . PHP_EOL;
669
 
670
+ }
671
+ $code_mirror_mode = 'text/css';
672
+ $code_mirror_before = '<style type="text/css">';
673
+ $code_mirror_after = '</style>';
674
 
675
+ }
676
 
677
+ ?>
678
+ <form style="position: relative; margin-top: .5em;">
679
 
680
+ <div class="code-mirror-before"><div><?php echo htmlentities( $code_mirror_before ); ?></div></div>
681
+ <textarea class="wp-editor-area" id="ccj_content" mode="<?php echo htmlentities( $code_mirror_mode ); ?>" name="content"><?php echo $post->post_content; ?></textarea>
682
+ <div class="code-mirror-after"><div><?php echo htmlentities( $code_mirror_after ); ?></div></div>
683
 
684
+ <table id="post-status-info"><tbody><tr>
685
+ <td class="autosave-info">
686
+ <span class="autosave-message">&nbsp;</span>
687
+ <?php
688
+ if ( 'auto-draft' != $post->post_status ) {
689
+ echo '<span id="last-edit">';
690
+ if ( $last_user = get_userdata( get_post_meta( $post->ID, '_edit_last', true ) ) ) {
691
+ printf( __( 'Last edited by %1$s on %2$s at %3$s', 'custom-css-js-pro' ), esc_html( $last_user->display_name ), mysql2date( get_option( 'date_format' ), $post->post_modified ), mysql2date( get_option( 'time_format' ), $post->post_modified ) );
692
+ } else {
693
+ printf( __( 'Last edited on %1$s at %2$s', 'custom-css-js-pro' ), mysql2date( get_option( 'date_format' ), $post->post_modified ), mysql2date( get_option( 'time_format' ), $post->post_modified ) );
694
+ }
695
+ echo '</span>';
696
+ }
697
+ ?>
698
+ </td>
699
+ </tr></tbody></table>
700
 
701
 
702
+ <input type="hidden" id="update-post_<?php echo $post->ID; ?>" value="<?php echo wp_create_nonce( 'update-post_' . $post->ID ); ?>" />
703
+ </form>
704
+ <?php
705
 
706
+ }
707
 
708
 
709
 
710
+ /**
711
+ * Show the options form in the `post` screen
712
+ */
713
+ function custom_code_options_meta_box_callback( $post ) {
714
 
715
+ $options = $this->get_options( $post->ID );
716
+ if ( ! isset( $options['preprocessor'] ) ) {
717
+ $options['preprocessor'] = 'none';
718
+ }
719
+
720
+ if ( isset( $_GET['language'] ) ) {
721
+ $options['language'] = $this->get_language();
722
+ }
723
+
724
+ $meta = $this->get_options_meta();
725
+ if ( $options['language'] == 'html' ) {
726
+ $meta = $this->get_options_meta_html();
727
+ }
728
+
729
+ wp_nonce_field( 'options_save_meta_box_data', 'custom-css-js_meta_box_nonce' );
730
+
731
+ ?>
732
+ <div class="options_meta_box">
733
+ <?php
734
+
735
+ $output = '';
736
+
737
+ foreach ( $meta as $_key => $a ) {
738
+ $close_div = false;
739
+
740
+ if ( ( $_key == 'preprocessor' && $options['language'] == 'css' ) ||
741
+ ( $_key == 'linking' && $options['language'] == 'html' ) ||
742
+ $_key == 'priority' ||
743
+ $_key == 'minify' ) {
744
+ $close_div = true;
745
+ $output .= '<div class="ccj_opaque">';
746
+ }
747
+
748
+ // Don't show Pre-processors for JavaScript Codes
749
+ if ( $options['language'] == 'js' && $_key == 'preprocessor' ) {
750
+ continue;
751
+ }
752
+
753
+ $output .= '<h3>' . $a['title'] . '</h3>' . PHP_EOL;
754
+
755
+ $output .= $this->render_input( $_key, $a, $options );
756
+
757
+ if ( $close_div ) {
758
+ $output .= '</div>';
759
+ }
760
+ }
761
+
762
+ echo $output;
763
+
764
+ ?>
765
+
766
+ <input type="hidden" name="custom_code_language" value="<?php echo $options['language']; ?>" />
767
+
768
+ <div style="clear: both;"></div>
769
+
770
+ </div>
771
+
772
+ <div class="ccj_only_premium ccj_only_premium-right">
773
+ <div>
774
+ <a href="https://www.silkypress.com/simple-custom-css-js-pro/?utm_source=wordpress&utm_campaign=ccj_free&utm_medium=banner" target="_blank"><?php _e( 'Available only in <br />Simple Custom CSS and JS Pro', 'custom-css-js' ); ?></a>
775
+ </div>
776
+ </div>
777
+
778
+
779
+ <?php
780
+ }
781
+
782
+
783
+ /**
784
+ * Get an array with all the information for building the code's options
785
+ */
786
+ function get_options_meta() {
787
+ $options = array(
788
+ 'linking' => array(
789
+ 'title' => __( 'Linking type', 'custom-css-js' ),
790
+ 'type' => 'radio',
791
+ 'default' => 'internal',
792
+ 'values' => array(
793
+ 'external' => array(
794
+ 'title' => __( 'External File', 'custom-css-js' ),
795
+ 'dashicon' => 'media-code',
796
+ ),
797
+ 'internal' => array(
798
+ 'title' => __( 'Internal', 'custom-css-js' ),
799
+ 'dashicon' => 'editor-alignleft',
800
+ ),
801
+ ),
802
+ ),
803
+ 'type' => array(
804
+ 'title' => __( 'Where on page', 'custom-css-js' ),
805
+ 'type' => 'radio',
806
+ 'default' => 'header',
807
+ 'values' => array(
808
+ 'header' => array(
809
+ 'title' => __( 'Header', 'custom-css-js' ),
810
+ 'dashicon' => 'arrow-up-alt2',
811
+ ),
812
+ 'footer' => array(
813
+ 'title' => __( 'Footer', 'custom-css-js' ),
814
+ 'dashicon' => 'arrow-down-alt2',
815
+ ),
816
+ ),
817
+ ),
818
+ 'side' => array(
819
+ 'title' => __( 'Where in site', 'custom-css-js' ),
820
+ 'type' => 'radio',
821
+ 'default' => 'frontend',
822
+ 'values' => array(
823
+ 'frontend' => array(
824
+ 'title' => __( 'In Frontend', 'custom-css-js' ),
825
+ 'dashicon' => 'tagcloud',
826
+ ),
827
+ 'admin' => array(
828
+ 'title' => __( 'In Admin', 'custom-css-js' ),
829
+ 'dashicon' => 'id',
830
+ ),
831
+ 'login' => array(
832
+ 'title' => __( 'On Login Page', 'custom-css-js' ),
833
+ 'dashicon' => 'admin-network',
834
+ ),
835
+ ),
836
+ ),
837
+ 'preprocessor' => array(
838
+ 'title' => __( 'CSS Preprocessor', 'custom-css-js' ),
839
+ 'type' => 'radio',
840
+ 'default' => 'none',
841
+ 'values' => array(
842
+ 'none' => array(
843
+ 'title' => __( 'None', 'custom-css-js' ),
844
+ ),
845
+ 'less' => array(
846
+ 'title' => __( 'Less', 'custom-css-js' ),
847
+ ),
848
+ 'sass' => array(
849
+ 'title' => __( 'SASS (only SCSS syntax)', 'custom-css-js' ),
850
+ ),
851
+ ),
852
+ 'disabled' => true,
853
+ ),
854
+ 'minify' => array(
855
+ 'title' => __( 'Minify the code', 'custom-css-js' ),
856
+ 'type' => 'checkbox',
857
+ 'default' => false,
858
+ 'dashicon' => 'editor-contract',
859
+ 'disabled' => true,
860
+ ),
861
+ 'priority' => array(
862
+ 'title' => __( 'Priority', 'custom-css-js' ),
863
+ 'type' => 'select',
864
+ 'default' => 5,
865
+ 'dashicon' => 'sort',
866
+ 'values' => array(
867
+ 1 => _x( '1 (highest)', '1 is the highest priority', 'custom-css-js' ),
868
+ 2 => '2',
869
+ 3 => '3',
870
+ 4 => '4',
871
+ 5 => '5',
872
+ 6 => '6',
873
+ 7 => '7',
874
+ 8 => '8',
875
+ 9 => '9',
876
+ 10 => _x( '10 (lowest)', '10 is the lowest priority', 'custom-css-js' ),
877
+ ),
878
+ 'disabled' => true,
879
+ ),
880
+ );
881
+
882
+ return $options;
883
+ }
884
+
885
+
886
+ /**
887
+ * Get an array with all the information for building the code's options
888
+ */
889
+ function get_options_meta_html() {
890
+ $options = array(
891
+ 'type' => array(
892
+ 'title' => __( 'Where on page', 'custom-css-js' ),
893
+ 'type' => 'radio',
894
+ 'default' => 'header',
895
+ 'values' => array(
896
+ 'header' => array(
897
+ 'title' => __( 'Header', 'custom-css-js' ),
898
+ 'dashicon' => 'arrow-up-alt2',
899
+ ),
900
+ 'footer' => array(
901
+ 'title' => __( 'Footer', 'custom-css-js' ),
902
+ 'dashicon' => 'arrow-down-alt2',
903
+ ),
904
+ ),
905
+ ),
906
+ 'side' => array(
907
+ 'title' => __( 'Where in site', 'custom-css-js' ),
908
+ 'type' => 'radio',
909
+ 'default' => 'frontend',
910
+ 'values' => array(
911
+ 'frontend' => array(
912
+ 'title' => __( 'In Frontend', 'custom-css-js' ),
913
+ 'dashicon' => 'tagcloud',
914
+ ),
915
+ 'admin' => array(
916
+ 'title' => __( 'In Admin', 'custom-css-js' ),
917
+ 'dashicon' => 'id',
918
+ ),
919
+ ),
920
+ ),
921
+ 'linking' => array(
922
+ 'title' => __( 'On which device', 'custom-css-js' ),
923
+ 'type' => 'radio',
924
+ 'default' => 'both',
925
+ 'dashicon' => '',
926
+ 'values' => array(
927
+ 'desktop' => array(
928
+ 'title' => __( 'Desktop', 'custom-css-js' ),
929
+ 'dashicon' => 'desktop',
930
+ ),
931
+ 'mobile' => array(
932
+ 'title' => __( 'Mobile', 'custom-css-js' ),
933
+ 'dashicon' => 'smartphone',
934
+ ),
935
+ 'both' => array(
936
+ 'title' => __( 'Both', 'custom-css-js' ),
937
+ 'dashicon' => 'tablet',
938
+ ),
939
+ ),
940
+ 'disabled' => true,
941
+ ),
942
+ 'priority' => array(
943
+ 'title' => __( 'Priority', 'custom-css-js' ),
944
+ 'type' => 'select',
945
+ 'default' => 5,
946
+ 'dashicon' => 'sort',
947
+ 'values' => array(
948
+ 1 => _x( '1 (highest)', '1 is the highest priority', 'custom-css-js' ),
949
+ 2 => '2',
950
+ 3 => '3',
951
+ 4 => '4',
952
+ 5 => '5',
953
+ 6 => '6',
954
+ 7 => '7',
955
+ 8 => '8',
956
+ 9 => '9',
957
+ 10 => _x( '10 (lowest)', '10 is the lowest priority', 'custom-css-js' ),
958
+ ),
959
+ 'disabled' => true,
960
+ ),
961
+
962
+ );
963
+
964
+ return $options;
965
+ }
966
+
967
+
968
+ /**
969
+ * Save the post and the metadata
970
+ */
971
+ function options_save_meta_box_data( $post_id ) {
972
+
973
+ // The usual checks
974
+ if ( ! isset( $_POST['custom-css-js_meta_box_nonce'] ) ) {
975
+ return;
976
+ }
977
+
978
+ if ( ! wp_verify_nonce( $_POST['custom-css-js_meta_box_nonce'], 'options_save_meta_box_data' ) ) {
979
+ return;
980
+ }
981
+
982
+ if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
983
+ return;
984
+ }
985
+
986
+ if ( isset( $_POST['post_type'] ) && 'custom-css-js' != $_POST['post_type'] ) {
987
+ return;
988
+ }
989
+
990
+ // Update the post's meta
991
+ $defaults = array(
992
+ 'type' => 'header',
993
+ 'linking' => 'internal',
994
+ 'priority' => 5,
995
+ 'side' => 'frontend',
996
+ 'language' => 'css',
997
+ );
998
+
999
+ if ( $_POST['custom_code_language'] == 'html' ) {
1000
+ $defaults = array(
1001
+ 'type' => 'header',
1002
+ 'linking' => 'both',
1003
+ 'side' => 'frontend',
1004
+ 'language' => 'html',
1005
+ 'priority' => 5,
1006
+ );
1007
+ }
1008
+
1009
+ foreach ( $defaults as $_field => $_default ) {
1010
+ $options[ $_field ] = isset( $_POST[ 'custom_code_' . $_field ] ) ? esc_attr( $_POST[ 'custom_code_' . $_field ] ) : $_default;
1011
+ }
1012
+
1013
+ update_post_meta( $post_id, 'options', $options );
1014
+
1015
+ if ( $options['language'] == 'html' ) {
1016
+ $this->build_search_tree();
1017
+ return;
1018
+ }
1019
+
1020
+ if ( $options['language'] == 'js' ) {
1021
+ // Replace the default comment
1022
+ if ( preg_match( '@/\* Add your JavaScript code here[\s\S]*?End of comment \*/@im', $_POST['content'] ) ) {
1023
+ $_POST['content'] = preg_replace( '@/\* Add your JavaScript code here[\s\S]*?End of comment \*/@im', '/* Default comment here */', $_POST['content'] );
1024
+ }
1025
+
1026
+ // For other locales remove all the comments
1027
+ if ( substr( get_locale(), 0, 3 ) !== 'en_' ) {
1028
+ $_POST['content'] = preg_replace( '@/\*[\s\S]*?\*/@', '', $_POST['content'] );
1029
+ }
1030
+ }
1031
+
1032
+ // Save the Custom Code in a file in `wp-content/uploads/custom-css-js`
1033
+ if ( $options['linking'] == 'internal' ) {
1034
+
1035
+ $before = '<!-- start Simple Custom CSS and JS -->' . PHP_EOL;
1036
+ $after = '<!-- end Simple Custom CSS and JS -->' . PHP_EOL;
1037
+ if ( $options['language'] == 'css' ) {
1038
+ $before .= '<style type="text/css">' . PHP_EOL;
1039
+ $after = '</style>' . PHP_EOL . $after;
1040
+ }
1041
+ if ( $options['language'] == 'js' ) {
1042
+ if ( ! preg_match( '/<script\b[^>]*>([\s\S]*?)<\/script>/im', $_POST['content'] ) ) {
1043
+ $before .= '<script type="text/javascript">' . PHP_EOL;
1044
+ $after = '</script>' . PHP_EOL . $after;
1045
+ } else {
1046
+ // the content has a <script> tag, then remove the comments so they don't show up on the frontend
1047
+ $_POST['content'] = preg_replace( '@/\*[\s\S]*?\*/@', '', $_POST['content'] );
1048
+ }
1049
+ }
1050
+ }
1051
+
1052
+ if ( $options['linking'] == 'external' ) {
1053
+ $before = '/******* Do not edit this file *******' . PHP_EOL .
1054
+ 'Simple Custom CSS and JS - by Silkypress.com' . PHP_EOL .
1055
+ 'Saved: ' . date( 'M d Y | H:i:s' ) . ' */' . PHP_EOL;
1056
+ }
1057
+
1058
+ if ( wp_is_writable( CCJ_UPLOAD_DIR ) ) {
1059
+ $file_name = $post_id . '.' . $options['language'];
1060
+ $file_content = $before . stripslashes( $_POST['content'] ) . $after;
1061
+ @file_put_contents( CCJ_UPLOAD_DIR . '/' . $file_name, $file_content );
1062
+
1063
+ // save the file as the Permalink slug
1064
+ $slug = get_post_meta( $post_id, '_slug', true );
1065
+ if ( $slug ) {
1066
+ @file_put_contents( CCJ_UPLOAD_DIR . '/' . $slug . '.' . $options['language'], $file_content );
1067
+ }
1068
+ }
1069
+
1070
+ $this->build_search_tree();
1071
+ }
1072
+
1073
+ /**
1074
+ * Create the custom-css-js dir in uploads directory
1075
+ *
1076
+ * Show a message if the directory is not writable
1077
+ *
1078
+ * Create an empty index.php file inside
1079
+ */
1080
+ function create_uploads_directory() {
1081
+ $current_screen = get_current_screen();
1082
+
1083
+ // Check if we are editing a custom-css-js post
1084
+ if ( $current_screen->base != 'post' || $current_screen->post_type != 'custom-css-js' ) {
1085
+ return false;
1086
+ }
1087
+
1088
+ $dir = CCJ_UPLOAD_DIR;
1089
+
1090
+ // Create the dir if it doesn't exist
1091
+ if ( ! file_exists( $dir ) ) {
1092
+ wp_mkdir_p( $dir );
1093
+ }
1094
+
1095
+ // Show a message if it couldn't create the dir
1096
+ if ( ! file_exists( $dir ) ) :
1097
+ ?>
1098
+ <div class="notice notice-error is-dismissible">
1099
+ <p><?php printf( __( 'The %s directory could not be created', 'custom-css-js' ), '<b>custom-css-js</b>' ); ?></p>
1100
+ <p><?php _e( 'Please run the following commands in order to make the directory', 'custom-css-js' ); ?>: <br /><strong>mkdir <?php echo $dir; ?>; </strong><br /><strong>chmod 777 <?php echo $dir; ?>;</strong></p>
1101
+ </div>
1102
+ <?php
1103
+ return;
1104
+ endif;
1105
+
1106
+ // Show a message if the dir is not writable
1107
+ if ( ! wp_is_writable( $dir ) ) :
1108
+ ?>
1109
+ <div class="notice notice-error is-dismissible">
1110
+ <p><?php printf( __( 'The %s directory is not writable, therefore the CSS and JS files cannot be saved.', 'custom-css-js' ), '<b>' . $dir . '</b>' ); ?></p>
1111
+ <p><?php _e( 'Please run the following command to make the directory writable', 'custom-css-js' ); ?>:<br /><strong>chmod 777 <?php echo $dir; ?> </strong></p>
1112
+ </div>
1113
+ <?php
1114
+ return;
1115
+ endif;
1116
+
1117
+ // Write a blank index.php
1118
+ if ( ! file_exists( $dir . '/index.php' ) ) {
1119
+ $content = '<?php' . PHP_EOL . '// Silence is golden.';
1120
+ @file_put_contents( $dir . '/index.php', $content );
1121
+ }
1122
+ }
1123
+
1124
+
1125
+ /**
1126
+ * Build a tree where you can quickly find the needed custom-css-js posts
1127
+ *
1128
+ * @return void
1129
+ */
1130
+ private function build_search_tree() {
1131
+
1132
+ // Retrieve all the custom-css-js codes
1133
+ $posts = query_posts( 'post_type=custom-css-js&post_status=publish&nopaging=true' );
1134
+
1135
+ $tree = array();
1136
+ foreach ( $posts as $_post ) {
1137
+ if ( ! $this->is_active( $_post->ID ) ) {
1138
+ continue;
1139
+ }
1140
+
1141
+ $options = $this->get_options( $_post->ID );
1142
+
1143
+ // Get the branch name, example: frontend-css-header-external
1144
+ $tree_branch = $options['side'] . '-' . $options['language'] . '-' . $options['type'] . '-' . $options['linking'];
1145
+
1146
+ $filename = $_post->ID . '.' . $options['language'];
1147
+
1148
+ if ( $options['linking'] == 'external' ) {
1149
+ $filename .= '?v=' . rand( 1, 10000 );
1150
+ }
1151
+
1152
+ // Add the code file to the tree branch
1153
+ $tree[ $tree_branch ][] = $filename;
1154
+
1155
+ }
1156
+
1157
+ // Save the tree in the database
1158
+ update_option( 'custom-css-js-tree', $tree );
1159
+ }
1160
+
1161
+ /**
1162
+ * Rebuilt the tree when you trash or restore a custom code
1163
+ */
1164
+ function trash_post( $post_id ) {
1165
+ $this->build_search_tree();
1166
+ }
1167
+
1168
+
1169
+ /**
1170
+ * Render the checkboxes, radios, selects and inputs
1171
+ */
1172
+ function render_input( $_key, $a, $options ) {
1173
+ $name = 'custom_code_' . $_key;
1174
+ $output = '';
1175
+
1176
+ // Show radio type options
1177
+ if ( $a['type'] === 'radio' ) {
1178
+ $output .= '<div class="radio-group">' . PHP_EOL;
1179
+ foreach ( $a['values'] as $__key => $__value ) {
1180
+ $selected = '';
1181
+ $id = $name . '-' . $__key;
1182
+ $dashicons = isset( $__value['dashicon'] ) ? 'dashicons-before dashicons-' . $__value['dashicon'] : '';
1183
+ if ( isset( $a['disabled'] ) && $a['disabled'] ) {
1184
+ $selected = ' disabled="disabled"';
1185
+ }
1186
+ $selected .= ( $__key == $options[ $_key ] ) ? ' checked="checked" ' : '';
1187
+ $output .= '<input type="radio" ' . $selected . 'value="' . $__key . '" name="' . $name . '" id="' . $id . '">' . PHP_EOL;
1188
+ $output .= '<label class="' . $dashicons . '" for="' . $id . '"> ' . $__value['title'] . '</label><br />' . PHP_EOL;
1189
+ }
1190
+ $output .= '</div>' . PHP_EOL;
1191
+ }
1192
+
1193
+ // Show checkbox type options
1194
+ if ( $a['type'] == 'checkbox' ) {
1195
+ $dashicons = isset( $a['dashicon'] ) ? 'dashicons-before dashicons-' . $a['dashicon'] : '';
1196
+ $selected = ( isset( $options[ $_key ] ) && $options[ $_key ] == '1' ) ? ' checked="checked" ' : '';
1197
+ if ( isset( $a['disabled'] ) && $a['disabled'] ) {
1198
+ $selected .= ' disabled="disabled"';
1199
+ }
1200
+ $output .= '<div class="radio-group">' . PHP_EOL;
1201
+ $output .= '<input type="checkbox" ' . $selected . ' value="1" name="' . $name . '" id="' . $name . '">' . PHP_EOL;
1202
+ $output .= '<label class="' . $dashicons . '" for="' . $name . '"> ' . $a['title'] . '</label>';
1203
+ $output .= '</div>' . PHP_EOL;
1204
+ }
1205
+
1206
+ // Show select type options
1207
+ if ( $a['type'] == 'select' ) {
1208
+ $output .= '<div class="radio-group">' . PHP_EOL;
1209
+ $output .= '<select name="' . $name . '" id="' . $name . '">' . PHP_EOL;
1210
+ foreach ( $a['values'] as $__key => $__value ) {
1211
+ $selected = ( isset( $options[ $_key ] ) && $options[ $_key ] == $__key ) ? ' selected="selected"' : '';
1212
+ $output .= '<option value="' . $__key . '"' . $selected . '>' . $__value . '</option>' . PHP_EOL;
1213
+ }
1214
+ $output .= '</select>' . PHP_EOL;
1215
+ $output .= '</div>' . PHP_EOL;
1216
+ }
1217
+
1218
+ return $output;
1219
+
1220
+ }
1221
+
1222
+
1223
+ /**
1224
+ * Get the language for the current post
1225
+ */
1226
+ function get_language( $post_id = false ) {
1227
+ if ( $post_id !== false ) {
1228
+ $options = $this->get_options( $post_id );
1229
+ $language = $options['language'];
1230
+ } else {
1231
+ $language = isset( $_GET['language'] ) ? esc_attr( strtolower( $_GET['language'] ) ) : 'css';
1232
+ }
1233
+ if ( ! in_array( $language, array( 'css', 'js', 'html' ) ) ) {
1234
+ $language = 'css';
1235
+ }
1236
+
1237
+ return $language;
1238
+ }
1239
+
1240
+
1241
+ /**
1242
+ * Show the activate/deactivate link in the row's action area
1243
+ */
1244
+ function post_row_actions( $actions, $post ) {
1245
+ if ( 'custom-css-js' !== $post->post_type ) {
1246
+ return $actions;
1247
+ }
1248
+
1249
+ $url = wp_nonce_url( admin_url( 'admin-ajax.php?action=ccj_active_code&code_id=' . $post->ID ), 'ccj-active-code-' . $post->ID );
1250
+ if ( $this->is_active( $post->ID ) ) {
1251
+ $active_title = __( 'The code is active. Click to deactivate it', 'custom-css-js' );
1252
+ $active_text = __( 'Deactivate', 'custom-css-js' );
1253
+ } else {
1254
+ $active_title = __( 'The code is inactive. Click to activate it', 'custom-css-js' );
1255
+ $active_text = __( 'Activate', 'custom-css-js' );
1256
+ }
1257
+ $actions['activate'] = '<a href="' . esc_url( $url ) . '" title="' . $active_title . '" class="ccj_activate_deactivate" data-code-id="' . $post->ID . '">' . $active_text . '</a>';
1258
+
1259
+ return $actions;
1260
+ }
1261
+
1262
+
1263
+ /**
1264
+ * Show the activate/deactivate link in admin.
1265
+ */
1266
+ public function post_submitbox_start() {
1267
+ global $post;
1268
+
1269
+ if ( ! is_object( $post ) ) {
1270
+ return;
1271
+ }
1272
+
1273
+ if ( 'custom-css-js' !== $post->post_type ) {
1274
+ return;
1275
+ }
1276
+
1277
+ if ( ! isset( $_GET['post'] ) ) {
1278
+ return;
1279
+ }
1280
+
1281
+ $url = wp_nonce_url( admin_url( 'admin-ajax.php?action=ccj_active_code&code_id=' . $post->ID ), 'ccj-active-code-' . $post->ID );
1282
+
1283
+ if ( $this->is_active( $post->ID ) ) {
1284
+ $text = __( 'Active', 'custom-css-js' );
1285
+ $action = __( 'Deactivate', 'custom-css-js' );
1286
+ } else {
1287
+ $text = __( 'Inactive', 'custom-css-js' );
1288
+ $action = __( 'Activate', 'custom-css-js' );
1289
+ }
1290
+ ?>
1291
+ <div id="activate-action"><span style="font-weight: bold;"><?php echo $text; ?></span>
1292
+ (<a class="ccj_activate_deactivate" data-code-id="<?php echo $post->ID; ?>" href="<?php echo esc_url( $url ); ?>"><?php echo $action; ?></a>)
1293
+ </div>
1294
+ <?php
1295
+ }
1296
+
1297
+
1298
+ /**
1299
+ * Show the Permalink edit form
1300
+ */
1301
+ function edit_form_before_permalink( $filename = '', $permalink = '', $filetype = 'css' ) {
1302
+ if ( isset( $_GET['language'] ) ) {
1303
+ $filetype = $_GET['language'];
1304
+ }
1305
+
1306
+ if ( ! is_string( $filename ) ) {
1307
+ global $post;
1308
+ if ( ! is_object( $post ) ) {
1309
+ return;
1310
+ }
1311
+ if ( 'custom-css-js' !== $post->post_type ) {
1312
+ return;
1313
+ }
1314
+
1315
+ $post = $filename;
1316
+ $slug = get_post_meta( $post->ID, '_slug', true );
1317
+ $options = get_post_meta( $post->ID, 'options', true );
1318
+ if ( isset( $options['language'] ) ) {
1319
+ $filetype = $options['language'];
1320
+ }
1321
+ if ( ! @file_exists( CCJ_UPLOAD_DIR . '/' . $slug . '.' . $options['language'] ) ) {
1322
+ $slug = false;
1323
+ }
1324
+ $filename = ( $slug ) ? $slug : $post->ID;
1325
+ }
1326
+
1327
+ if ( ! in_array( $filetype, array( 'css', 'js' ) ) ) {
1328
+ return;
1329
+ }
1330
+ if ( empty( $permalink ) ) {
1331
+ $permalink = CCJ_UPLOAD_URL . '/' . $filename . '.' . $filetype;
1332
+ }
1333
+
1334
+ ?>
1335
+ <div class="inside">
1336
+ <div id="edit-slug-box" class="hide-if-no-js">
1337
+ <strong>Permalink:</strong>
1338
+ <span id="sample-permalink"><a href="<?php echo esc_url( $permalink ); ?>"><?php echo esc_html( CCJ_UPLOAD_URL ) . '/'; ?><span id="editable-post-name"><?php echo esc_html( $filename ); ?></span>.<?php echo esc_html( $filetype ); ?></a></span>
1339
+ &lrm;<span id="ccj-edit-slug-buttons"><button type="button" class="ccj-edit-slug button button-small hide-if-no-js" aria-label="Edit permalink">Edit</button></span>
1340
+ <span id="editable-post-name-full"><?php echo esc_html( $filename ); ?></span>
1341
+ </div>
1342
+ <?php wp_nonce_field( 'ccj-permalink', 'ccj-permalink-nonce' ); ?>
1343
+ </div>
1344
+ <?php
1345
+ }
1346
+
1347
+
1348
+ /**
1349
+ * AJAX save the Permalink slug
1350
+ */
1351
+ function wp_ajax_ccj_permalink() {
1352
+
1353
+ if ( ! isset( $_POST['ccj_permalink_nonce'] ) ) {
1354
+ return;
1355
+ }
1356
+
1357
+ if ( ! wp_verify_nonce( $_POST['ccj_permalink_nonce'], 'ccj-permalink' ) ) {
1358
+ return;
1359
+ }
1360
+
1361
+ $code_id = isset( $_POST['code_id'] ) ? intval( $_POST['code_id'] ) : 0;
1362
+ $permalink = isset( $_POST['permalink'] ) ? $_POST['permalink'] : null;
1363
+ $slug = isset( $_POST['new_slug'] ) ? trim( sanitize_file_name( $_POST['new_slug'] ) ) : null;
1364
+ $filetype = isset( $_POST['filetype'] ) ? $_POST['filetype'] : 'css';
1365
+ if ( empty( $slug ) ) {
1366
+ $slug = (string) $code_id;
1367
+ } else {
1368
+ update_post_meta( $code_id, '_slug', $slug );
1369
+ }
1370
+ $this->edit_form_before_permalink( $slug, $permalink, $filetype );
1371
+
1372
+ wp_die();
1373
+ }
1374
+
1375
+
1376
+ /**
1377
+ * Remove the JS/CSS file from the disk when deleting the post
1378
+ */
1379
+ function before_delete_post( $postid ) {
1380
+ global $post;
1381
+ if ( ! is_object( $post ) ) {
1382
+ return;
1383
+ }
1384
+ if ( 'custom-css-js' !== $post->post_type ) {
1385
+ return;
1386
+ }
1387
+ if ( ! wp_is_writable( CCJ_UPLOAD_DIR ) ) {
1388
+ return;
1389
+ }
1390
+
1391
+ $options = get_post_meta( $postid, 'options', true );
1392
+ $slug = get_post_meta( $postid, '_slug', true );
1393
+ $file_name = $postid . '.' . $options['language'];
1394
+
1395
+ @unlink( CCJ_UPLOAD_DIR . '/' . $file_name );
1396
+
1397
+ if ( ! empty( $slug ) ) {
1398
+ @unlink( CCJ_UPLOAD_DIR . '/' . $slug . '.' . $options['language'] );
1399
+ }
1400
+ }
1401
+
1402
+
1403
+ /**
1404
+ * Fix for bug: white page Edit Custom Code for WordPress 5.0 with Classic Editor
1405
+ */
1406
+ function current_screen_2() {
1407
+ $screen = get_current_screen();
1408
+
1409
+ if ( $screen->post_type != 'custom-css-js' ) {
1410
+ return false;
1411
+ }
1412
 
1413
+ remove_filter( 'use_block_editor_for_post', array( 'Classic_Editor', 'choose_editor' ), 100, 2 );
1414
+ add_filter( 'use_block_editor_for_post', '__return_false', 100 );
1415
+ add_filter( 'use_block_editor_for_post_type', '__return_false', 100 );
1416
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1417
  }
1418
 
1419
  return new CustomCSSandJS_Admin();
readme.txt CHANGED
@@ -5,7 +5,7 @@ Email: diana@burduja.eu
5
  Tags: CSS, JS, javascript, custom CSS, custom JS, custom style, site css, add style, customize theme, custom code, external css, css3, style, styles, stylesheet, theme, editor, design, admin
6
  Requires at least: 3.0.1
7
  Tested up to: 5.3
8
- Stable tag: 3.28
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
  Requires PHP: 5.2.4
@@ -105,6 +105,12 @@ $. Add/Edit HTML
105
 
106
  == Changelog ==
107
 
 
 
 
 
 
 
108
  = 3.28 =
109
  * 11/05/2019
110
  * Tweak: update the Bootstrap and jQuery library links
5
  Tags: CSS, JS, javascript, custom CSS, custom JS, custom style, site css, add style, customize theme, custom code, external css, css3, style, styles, stylesheet, theme, editor, design, admin
6
  Requires at least: 3.0.1
7
  Tested up to: 5.3
8
+ Stable tag: 3.29
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
  Requires PHP: 5.2.4
105
 
106
  == Changelog ==
107
 
108
+ = 3.29 =
109
+ * 01/31/2020
110
+ * Fix: date Published and Modified date wasn't shown in Japanese
111
+ * Feature: indentation in the editor
112
+ * Feature: close brackets in the editor
113
+
114
  = 3.28 =
115
  * 11/05/2019
116
  * Tweak: update the Bootstrap and jQuery library links