PluginProbe
UpdraftCentral Dashboard / 0.8.32
UpdraftCentral Dashboard v0.8.32
0.8.33 0.7.2 0.7.3 0.7.4 0.8.0 0.8.1 0.8.10 0.8.11 0.8.12 0.8.13 0.8.14 0.8.15 0.8.16 0.8.17 0.8.18 0.8.19 0.8.2 0.8.20 0.8.21 0.8.22 0.8.23 0.8.24 0.8.25 0.8.26 0.8.27 All 51 releases
updraftcentral / classes / class-editor.php

class-editor.php in UpdraftCentral Dashboard 0.8.32, at classes/class-editor.php

1,354 lines 48.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH')) die('Access denied.');
3
4 if (!class_exists('UpdraftCentral_Editor')) :
5
6 /**
7 * UpdraftCentral_Editor class.
8 *
9 * Primarily used for loading the classic and block editor resources and handles UpdraftCentral's REST
10 * requests using the block editor to edit remote pages or posts.
11 */
12 class UpdraftCentral_Editor {
13
14 public $type = '';
15
16 protected static $_instance = null;
17
18 /**
19 * Initialize prechecks and hooks for this editor class
20 *
21 * @return void
22 */
23 public function load() {
24 if (!class_exists('UpdraftCentral_REST_Posts_Controller')) include_once UD_CENTRAL_DIR.'/classes/class-rest-posts-controller.php';
25 if (!class_exists('UpdraftCentral_REST_Users_Controller')) include_once UD_CENTRAL_DIR.'/classes/class-rest-users-controller.php';
26 if (!class_exists('UpdraftCentral_REST_Taxonomies_Controller')) include_once UD_CENTRAL_DIR.'/classes/class-rest-taxonomies-controller.php';
27 if (!class_exists('UpdraftCentral_REST_Terms_Controller')) include_once UD_CENTRAL_DIR.'/classes/class-rest-terms-controller.php';
28
29 add_filter('rest_pre_dispatch', array($this, 'intercept_request_data'), 0, 3);
30 add_action('updraftcentral_load_dashboard_js', array($this, 'enqueue_editor_scripts'));
31 }
32
33 /**
34 * Creates an instance of this class. Singleton Pattern
35 *
36 * @return object Instance of this class
37 */
38 public static function instance() {
39 if (empty(self::$_instance)) {
40 self::$_instance = new self();
41 }
42
43 return self::$_instance;
44 }
45
46 /**
47 * Saves placeholder details for later use and enqueus needed resources
48 *
49 * @return void
50 */
51 public function enqueue_editor_scripts() {
52 global $post, $post_type, $post_type_object;
53
54 // We'll create a dummy post or page with status draft (if not yet created) and return its ID.
55 // We will used this post or page object to preload any scripts needed by the editor later on, since
56 // ajax-based calls will no longer have that opporturnity to load resources (which is only done during page load).
57 $post_id = $this->get_placeholder_id($this->type);
58 if (!empty($post_id)) {
59 $post = get_post($post_id);
60
61 $post_type = get_post_type($post);
62 $post_type_object = get_post_type_object($post_type);
63
64 if (!function_exists('get_current_screen')) {
65 include_once(ABSPATH . 'wp-admin/includes/screen.php');
66 include_once(ABSPATH . 'wp-admin/includes/class-wp-screen.php');
67 include_once ABSPATH . 'wp-admin/includes/template.php';
68 }
69
70 if (!function_exists('get_page_templates')) {
71 include_once ABSPATH . 'wp-admin/includes/theme.php';
72 }
73
74 $block_patterns_file = ABSPATH.WPINC.'/block-patterns.php';
75 if (file_exists($block_patterns_file)) {
76 if (!function_exists('_register_core_block_patterns_and_categories')) {
77 include_once($block_patterns_file);
78 }
79 _register_core_block_patterns_and_categories();
80 }
81
82 $this->load_block_editor_resources();
83 }
84
85 $min_or_not = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '.min';
86 wp_enqueue_script('postbox', admin_url("js/postbox".$min_or_not.".js"), array('jquery-ui-sortable'), UpdraftCentral()->version, 1);
87 }
88
89 /**
90 * Loads block editor resources. Copied from wp-admin/edit-form-blocks.php (WP 5.0) and made
91 * some adjustments (remove and alter lines) to prevent loading the editor prematurely, as we need it to load
92 * on demand basing on the current page/post selected. Updated to support WP 5.4 changes.
93 *
94 * N.B. Applies to WP 5.0 and later only (that is for the core-integrated version).
95 *
96 * @return void
97 */
98 private function load_block_editor_resources() {
99 global $post_type_object, $post, $wp_meta_boxes;
100
101 // Load block patterns from w.org.
102 if (function_exists('_load_remote_block_patterns')) _load_remote_block_patterns();
103 if (function_exists('_load_remote_featured_patterns')) _load_remote_featured_patterns();
104
105 /*
106 * Emoji replacement is disabled for now, until it plays nicely with React.
107 */
108 remove_action('admin_print_scripts', 'print_emoji_detection_script');
109
110 /*
111 * Block editor implements its own Options menu for toggling Document Panels.
112 */
113 add_filter('screen_options_show_screen', '__return_false');
114
115 wp_enqueue_script('heartbeat');
116 wp_enqueue_script('wp-edit-post');
117 wp_enqueue_script('wp-format-library');
118
119 // Get admin url for handling meta boxes.
120 $meta_box_nonce = wp_create_nonce('meta-box-loader');
121
122 $meta_box_url = admin_url('post.php');
123 $meta_box_url = add_query_arg(
124 array(
125 'post' => $post->ID,
126 'action' => 'edit',
127 'meta-box-loader' => true,
128 'meta-box-loader-nonce' => $meta_box_nonce,
129 '_wpnonce' => $meta_box_nonce, // Supports legacy code prior to 5.4
130 ),
131 $meta_box_url
132 );
133 wp_add_inline_script(
134 'wp-editor',
135 sprintf('var _wpMetaBoxUrl = %s;', wp_json_encode($meta_box_url)),
136 'before'
137 );
138
139 /*
140 * Initialize the editor.
141 */
142
143 $align_wide = get_theme_support('align-wide');
144 $color_palette = current((array) get_theme_support('editor-color-palette'));
145 $font_sizes = current((array) get_theme_support('editor-font-sizes'));
146 $gradient_presets = current((array) get_theme_support('editor-gradient-presets'));
147 $custom_line_height = get_theme_support('custom-line-height');
148 $custom_units = get_theme_support('custom-units');
149
150 /**
151 * Filters the allowed block types for the editor, defaulting to true (all
152 * block types supported).
153 *
154 * @since 5.0.0
155 *
156 * @param bool|array $allowed_block_types Array of block type slugs, or
157 * boolean to enable/disable all.
158 * @param WP_Post $post The post resource data.
159 */
160 $allowed_block_types = apply_filters('allowed_block_types', true, $post);
161
162 /*
163 * Get all available templates for the post/page attributes meta-box.
164 * The "Default template" array element should only be added if the array is
165 * not empty so we do not trigger the template select element without any options
166 * besides the default value.
167 */
168 $available_templates = wp_get_theme()->get_page_templates(get_post($post->ID));
169 $available_templates = !empty($available_templates) ? array_merge(array('' => apply_filters('default_page_template_title', __('Default template'), 'rest-api')), $available_templates) : $available_templates;
170
171 // Media settings.
172 $max_upload_size = wp_max_upload_size();
173 if (!$max_upload_size) {
174 $max_upload_size = 0;
175 }
176
177 // Image sizes.
178
179 /** This filter is documented in wp-admin/includes/media.php */
180 $image_size_names = apply_filters(
181 'image_size_names_choose',
182 array(
183 'thumbnail' => __('Thumbnail'),
184 'medium' => __('Medium'),
185 'large' => __('Large'),
186 'full' => __('Full Size'),
187 )
188 );
189
190 $available_image_sizes = array();
191 foreach ($image_size_names as $image_size_slug => $image_size_name) {
192 $available_image_sizes[] = array(
193 'slug' => $image_size_slug,
194 'name' => $image_size_name,
195 );
196 }
197
198 $image_dimensions = array();
199 if (function_exists('wp_get_registered_image_subsizes')) {
200 $all_sizes = wp_get_registered_image_subsizes();
201 foreach ($available_image_sizes as $size) {
202 $key = $size['slug'];
203 if (isset($all_sizes[$key])) {
204 $image_dimensions[$key] = $all_sizes[$key];
205 }
206 }
207 }
208
209 if (!function_exists('wp_check_post_lock')) {
210 include_once ABSPATH.'wp-admin/includes/post.php';
211 }
212
213 $placeholder_editor_id = wp_check_post_lock($post->ID);
214 if ($placeholder_editor_id) {
215 // Release any lock set at the editor's placeholder. It wasn't suppose
216 // to be edited anyway because it wasn't created manually by any user.
217 delete_post_meta($post->ID, '_edit_lock');
218 }
219
220 // Lock settings.
221 $user_id = wp_check_post_lock($post->ID);
222 if ($user_id) {
223 $locked = false;
224
225 /** This filter is documented in wp-admin/includes/post.php */
226 if (apply_filters('show_post_locked_dialog', true, $post, $user_id)) {
227 $locked = true;
228 }
229
230 $user_details = null;
231 if ($locked) {
232 $user = get_userdata($user_id);
233 $user_details = array(
234 'name' => $user->display_name,
235 );
236 }
237
238 $lock_details = array(
239 'isLocked' => $locked,
240 'user' => $user_details,
241 );
242 } else {
243 // Lock the post.
244 $active_post_lock = wp_set_post_lock($post->ID);
245 if ($active_post_lock) {
246 $active_post_lock = esc_attr(implode(':', $active_post_lock));
247 }
248
249 $lock_details = array(
250 'isLocked' => false,
251 'activePostLock' => $active_post_lock,
252 );
253 }
254
255 // These styles are used if the "no theme styles" options is triggered or on
256 // themes without their own editor styles.
257 $default_editor_styles_file = ABSPATH.WPINC.'/css/dist/block-editor/default-editor-styles.css';
258 if (file_exists($default_editor_styles_file)) {
259 $default_editor_styles = array(
260 array('css' => file_get_contents($default_editor_styles_file )),
261 );
262 } else {
263 $default_editor_styles = array();
264 }
265
266 /**
267 * Filters the body placeholder text.
268 *
269 * @since 5.0.0
270 *
271 * @param string $text Placeholder text. Default 'Start writing or type / to choose a block'.
272 * @param WP_Post $post Post object.
273 */
274 $body_placeholder = apply_filters('write_your_story', __('Type / to choose a block'), $post);
275
276 $editor_settings = array(
277 'alignWide' => $align_wide,
278 'availableTemplates' => $available_templates,
279 'allowedBlockTypes' => $allowed_block_types,
280 'disableCustomColors' => get_theme_support('disable-custom-colors'),
281 'disableCustomFontSizes' => get_theme_support('disable-custom-font-sizes'),
282 'disableCustomGradients' => get_theme_support('disable-custom-gradients'),
283 'disablePostFormats' => ! current_theme_supports('post-formats'),
284 /** This filter is documented in wp-admin/edit-form-advanced.php */
285 'titlePlaceholder' => apply_filters('enter_title_here', __('Add title'), $post),
286 'bodyPlaceholder' => $body_placeholder,
287 'isRTL' => is_rtl(),
288 'autosaveInterval' => defined('AUTOSAVE_INTERVAL') ? AUTOSAVE_INTERVAL : 10,
289 'maxUploadFileSize' => $max_upload_size,
290 'allowedMimeTypes' => get_allowed_mime_types(),
291 'defaultEditorStyles' => $default_editor_styles,
292 'styles' => array(),
293 'imageSizes' => $available_image_sizes,
294 'imageDimensions' => $image_dimensions,
295 'richEditingEnabled' => user_can_richedit(),
296 'postLock' => $lock_details,
297 'postLockUtils' => array(
298 'nonce' => wp_create_nonce('lock-post_' . $post->ID),
299 'unlockNonce' => wp_create_nonce('update-post_' . $post->ID),
300 'ajaxUrl' => admin_url('admin-ajax.php'),
301 ),
302 'supportsTemplateMode' => current_theme_supports('block-templates'),
303 // N.B. We will not support custom fields for now as this will complicate things even further. Perhaps
304 // in the near future we will as the need and demand arises.
305 'enableCustomFields' => false,
306 'enableCustomLineHeight' => $custom_line_height,
307 'enableCustomUnits' => $custom_units,
308 );
309
310 if (function_exists('wp_theme_has_theme_json')) {
311 $editor_settings['supportsLayout'] = wp_theme_has_theme_json();
312 } else {
313 if (class_exists('WP_Theme_JSON_Resolver')) {
314 $editor_settings['supportsLayout'] = WP_Theme_JSON_Resolver::theme_has_support();
315 }
316 }
317
318 if (class_exists('WP_Block_Patterns_Registry')) {
319 $editor_settings['__experimentalBlockPatterns'] = WP_Block_Patterns_Registry::get_instance()->get_all_registered();
320 }
321
322 if (class_exists('WP_Block_Pattern_Categories_Registry')) {
323 $editor_settings['__experimentalBlockPatternCategories'] = WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered();
324 }
325
326 $autosave = wp_get_post_autosave($post->ID);
327 if ($autosave) {
328 if (mysql2date('U', $autosave->post_modified_gmt, false) > mysql2date('U', $post->post_modified_gmt, false)) {
329 $editor_settings['autosave'] = array(
330 'editLink' => get_edit_post_link($autosave->ID),
331 );
332 } else {
333 wp_delete_post_revision($autosave->ID);
334 }
335 }
336
337 if (false !== $color_palette) {
338 $editor_settings['colors'] = $color_palette;
339 }
340
341 if (false !== $font_sizes) {
342 $editor_settings['fontSizes'] = $font_sizes;
343 }
344
345 if (false !== $gradient_presets) {
346 $editor_settings['gradients'] = $gradient_presets;
347 }
348
349 if (!empty($post_type_object->template)) {
350 $editor_settings['template'] = $post_type_object->template;
351 $editor_settings['templateLock'] = !empty($post_type_object->template_lock) ? $post_type_object->template_lock : false;
352 }
353
354 $is_new_post = false;
355 if ('auto-draft' === $post->post_status) {
356 $is_new_post = true;
357 }
358
359 // If there's no template set on a new post, use the post format, instead.
360 if ($is_new_post && !isset($editor_settings['template']) && 'post' === $post->post_type) {
361 $post_format = get_post_format($post);
362 if (in_array($post_format, array('audio', 'gallery', 'image', 'quote', 'video'), true)) {
363 $editor_settings['template'] = array(array("core/$post_format"));
364 }
365 }
366
367 if (function_exists('wp_is_block_theme') && wp_is_block_theme() && $editor_settings['supportsTemplateMode']) {
368 if (function_exists('get_allowed_block_template_part_areas')) {
369 $editor_settings['defaultTemplatePartAreas'] = get_allowed_block_template_part_areas();
370 }
371 }
372
373 /**
374 * Scripts
375 */
376 wp_enqueue_media(
377 array(
378 'post' => $post->ID,
379 )
380 );
381 wp_tinymce_inline_scripts();
382 wp_enqueue_editor();
383
384 /**
385 * Styles
386 */
387 wp_enqueue_style('wp-edit-post');
388 wp_enqueue_style('wp-format-library');
389
390 do_action('enqueue_block_assets');
391
392 /**
393 * Fires after block assets have been enqueued for the editing interface.
394 *
395 * Call `add_action` on any hook before 'admin_enqueue_scripts'.
396 *
397 * In the function call you supply, simply use `wp_enqueue_script` and
398 * `wp_enqueue_style` to add your functionality to the block editor.
399 *
400 * @since 5.0.0
401 */
402 do_action('enqueue_block_editor_assets');
403
404 // In order to duplicate classic meta box behaviour, we need to run the classic meta box actions.
405 require_once(ABSPATH . 'wp-admin/includes/meta-boxes.php');
406 register_and_do_post_meta_boxes($post);
407
408 // Check if the Custom Fields meta box has been removed at some point.
409 if (isset($wp_meta_boxes[$post->post_type]) && isset($wp_meta_boxes[$post->post_type]['normal']) && isset($wp_meta_boxes[$post->post_type]['normal']['core'])) {
410 $core_meta_boxes = $wp_meta_boxes[$post->post_type]['normal']['core'];
411 if (!isset($core_meta_boxes['postcustom']) || !$core_meta_boxes['postcustom']) {
412 unset($editor_settings['enableCustomFields']);
413 }
414 }
415
416 if (class_exists('WP_Block_Editor_Context')) {
417 $block_editor_context = new WP_Block_Editor_Context(array('post' => $post));
418 $editor_settings = get_block_editor_settings( $editor_settings, $block_editor_context );
419 } else {
420 /**
421 * Filters the settings to pass to the block editor.
422 *
423 * @since 5.0.0
424 *
425 * @param array $editor_settings Default editor settings.
426 * @param WP_Post $post Post being edited.
427 */
428 $editor_settings = apply_filters('block_editor_settings', $editor_settings, $post);
429 }
430
431 update_user_meta(get_current_user_id(), 'updraftcentral_editor_settings', $editor_settings);
432 }
433
434 /**
435 * Retrieves the placeholder id created for the current type (e.g. 'post' or 'page')
436 *
437 * @param string $type Determines which type of ID to return (either 'post' or 'page')
438 * @return int|boolean
439 */
440 public function get_placeholder_id($type) {
441 if (in_array($type, array('page', 'post'))) {
442 $post_id = $this->maybe_create_post_and_return_id(array(
443 'post_title' => __('UpdraftCentral Editor Placeholder', 'updraftcentral'),
444 'post_name' => 'uc-editor-placeholder-'.$type,
445 'post_content' => sprintf(__('UpdraftCentral plugin uses this %s as a placeholder when loading the %s editor.', 'updraftcentral').' '.__('You should leave it with "Draft" status.', 'updraftcentral'), $type, $type),
446 'post_status' => 'draft',
447 'post_type' => $type
448 ));
449 return $post_id;
450 }
451
452 return false;
453 }
454
455 /**
456 * Sends the command to the remote website
457 *
458 * @param int $user_id The current user ID
459 * @param string $command The command to process
460 * @param array $params The parameters that goes along with the current request
461 * @return array
462 */
463 private function send_remote_command($user_id, $command, $params) {
464 $user = UpdraftCentral()->get_user_object($user_id);
465 if (!empty($user) && !empty($params['site_id'])) {
466 $remote_params = array(
467 'site_id' => $params['site_id'],
468 'data' => array(
469 'command' => $command,
470 'data' => $params,
471 )
472 );
473
474 $remote_response = $user->send_remote_command($remote_params);
475 if (!empty($remote_response) && 'ok' == $remote_response['responsetype']) {
476 if ('rpcok' == $remote_response['rpc_response']['response']) {
477 $data = $remote_response['rpc_response']['data'];
478 return $data;
479 } elseif ('rpcerror' == $remote_response['rpc_response']['response']) {
480 return new WP_Error('updraftcentral_rpcerror', __('The remote website responded with an error.', 'updraftcentral'), $remote_response['rpc_response']['data']);
481 }
482 } else {
483 return new WP_Error('updraftcentral_communication_error', __('An error has occurred while communicating to the remote website.', 'updraftcentral'));
484 }
485 } else {
486 return new WP_Error('updraftcentral_missing_fields', __('The required object has not been found.', 'updraftcentral'));
487 }
488 }
489
490 /**
491 * Returns an instance of an UpdraftCentral_Site_Meta class that is used to manage
492 * our site meta entries
493 *
494 * @return UpdraftCentral_Site_Meta
495 */
496 private function get_site_meta_instance() {
497 $site_meta = UpdraftCentral()->site_meta;
498 if (empty($site_meta)) {
499 if (!class_exists('UpdraftCentral_Site_Meta')) include_once UD_CENTRAL_DIR.'/classes/site-meta.php';
500
501 return new UpdraftCentral_Site_Meta(UpdraftCentral()->table_prefix);
502 }
503
504 return $site_meta;
505 }
506
507 /**
508 * Intercepts request params/data and bypass default (local) processing
509 *
510 * @param mixed $response Current response, either response or `null` to indicate pass-through.
511 * @param WP_REST_Server $handler ResponseHandler instance (usually WP_REST_Server).
512 * @param WP_REST_Request $request The request that was used to make current response.
513 * @return WP_REST_Response
514 */
515 public function intercept_request_data($response, $handler, $request) {
516
517 // Check whether we received an updraftcentral "uc_nonce", "uc_refIds" and "site_id" and "post_type" data. This also helps in preventing any overlap
518 // or overwrites when the user is using the Block editor in the WP admin area. Thus, we're only
519 // executing the processes below if the current request is made through UpdraftCentral.
520 $params = $request->get_params();
521 if (empty($params['uc_nonce']) || empty($params['uc_refIds']) || empty($params['site_id']) || empty($params['post_type'])) return $response;
522
523 $uc_nonce = is_array($params['uc_nonce']) ? $params['uc_nonce'][0] : $params['uc_nonce'];
524 $uc_refIds = is_array($params['uc_refIds']) ? $params['uc_refIds'][0] : $params['uc_refIds'];
525 $site_id = is_array($params['site_id']) ? $params['site_id'][0] : $params['site_id'];
526 $post_type = is_array($params['post_type']) ? $params['post_type'][0] : $params['post_type'];
527
528 list($user_id, $post_id) = explode('|', base64_decode($uc_refIds));
529 if (empty($user_id) || empty($post_id)) return $response;
530
531 // Verify the nonce submitted
532 if (!wp_verify_nonce($uc_nonce, 'updraftcentral-editpost-'.$post_id)) {
533 return $response;
534 }
535
536 // Pull the (stored) preloaded information from the remote website to be use for the REST request
537 // initiated by the UpdraftCentral editor.
538 $site_meta = $this->get_site_meta_instance();
539
540 $preloaded_data = $site_meta->get_site_meta($site_id, 'updraftcentral_editor_preloaded_data_'.$post_type, true);
541 if (!empty($preloaded_data)) {
542 if (isset($preloaded_data['post_data'])) {
543 $post_data = $preloaded_data['post_data'];
544 $post = $this->setup_remotepost_data($post_data['post'], true);
545 }
546 }
547
548 $match_result = preg_match('#^/wp/v2/(pages|posts)/([0-9]+)#', $request->get_route(), $matches);
549 if (!empty($match_result) && $post) {
550 $params = $request->get_params();
551 $post_id = $matches[2];
552
553 switch ($request->get_method()) {
554 case 'GET':
555 $controller = new UpdraftCentral_REST_Posts_Controller($post->post_type);
556 $misc = $this->attach_media_to_post($post_data['misc'], $post);
557
558 $response = $controller->prepare_remote_item_for_response($post, $request, $misc);
559 break;
560 case 'PUT':
561 if (!empty($params['featured_media'])) {
562 $params['featured_media_url'] = wp_get_attachment_url($params['featured_media']);
563 $dir = wp_upload_dir();
564
565 $image_info = wp_get_attachment_metadata($params['featured_media'], true);
566 if (is_array($image_info) && !empty($image_info['file'])) {
567 $image_file = trailingslashit($dir['basedir']).$image_info['file'];
568 if (file_exists($image_file)) {
569 $params['featured_media_data'] = base64_encode(file_get_contents($image_file, false, null));
570 }
571 }
572 }
573
574 $command = ('pages' == $matches[1]) ? 'pages.save' : 'posts.save';
575 if (!isset($request['context'])) $request['context'] = 'edit';
576
577 // On latest WP (e.g. 5.6) 'menu_order' is passed by the block editor instead of 'order', thus, we need
578 // to make sure that it is compatible with our service handler.
579 if (isset($params['menu_order'])) $params['order'] = $params['menu_order'];
580
581 // On latest WP (e.g. 5.6) a NULL value is passed instead of zero, thus, we'll make some
582 // adjustment before sending it to our service handler for compatibility.
583 //
584 // N.B. Running the check directly with "isset" and "empty" won't work since we need to make
585 // sure that we will only process if the fields were actually edited and the block editor will
586 // only send the fields of those edited post or page properties. Thus, we used the "array_key_exists"
587 // method here before checking if the value is NULL.
588 if (array_key_exists('parent', $params) && is_null($params['parent'])) $params['parent'] = 0;
589
590 $data = $this->send_remote_command($user_id, $command, $params);
591 if (!is_wp_error($data) && !empty($data)) {
592 $post = json_decode($data['post']);
593 $misc = $this->attach_media_to_post($data['misc'], $post);
594
595 // Update/replace existing preloaded post data with the recent
596 // changes so that it gets reflected all throughout UpdraftCentral.
597 $post_data = array(
598 'post' => $post,
599 'misc' => $misc
600 );
601
602 $preloaded_data['post_data'] = $post_data;
603 $site_meta->update_site_meta($site_id, 'updraftcentral_editor_preloaded_data_'.$post_type, $preloaded_data);
604
605 if (!empty($data['options'])) {
606 $post_data['options'] = $data['options'];
607 }
608
609 // Generate the response
610 $controller = new UpdraftCentral_REST_Posts_Controller($post->post_type);
611 $response = $controller->prepare_remote_item_for_response($post, $request, $misc);
612
613 $response_data = $response->get_data();
614 if (!empty($response_data)) {
615 // We need to add the post_data field to the response in order
616 // to update the current list item's information
617 $response_data['post_data'] = $post_data;
618 $response->set_data($response_data);
619 }
620 } else {
621 if (is_wp_error($data)) {
622 // Default message if we can't pull any relevant error messages from $data
623 $error_message = __('An unknown error has occurred while processing your request.', 'updraftcentral').' '.__('Please contact our support on updraftplus.com so that we can properly escalate the issue.', 'updraftcentral');
624
625 $messages = $data->get_error_messages();
626 if (!empty($messages)) {
627 $error_message = $messages[0];
628 }
629
630 // More specific error information - will override any previous one
631 $error_data = $data->get_error_data();
632 if (isset($error_data['data']) && isset($error_data['data']['message'])) {
633 $error_message = $error_data['data']['message'];
634 }
635
636 return new WP_Error('rest_remote_save_failed', $error_message);
637 } else {
638 return new WP_Error('rest_remote_save_failed', __('An unknown error has occurred while processing your request.', 'updraftcentral').' '.__('Please contact our support on updraftplus.com so that we can properly escalate the issue.', 'updraftcentral'));
639 }
640 }
641 break;
642 }
643 }
644
645 if ('/wp/v2/users' == $request->get_route() && 'GET' == $request->get_method()) {
646 $data = $preloaded_data['authors'];
647
648 $items = array();
649 foreach ($data as $item) {
650 $remote_item = json_decode($item['user']);
651
652 $controller = new UpdraftCentral_REST_Users_Controller;
653 $response = $controller->prepare_remote_item_for_response($remote_item, $request, $item['misc']);
654
655 $merged_data = array_merge($response->get_data(), array('_links' => $response->get_links()));
656 array_push($items, $merged_data);
657 }
658
659 $response = new WP_REST_Response($items);
660 }
661
662 if ('/wp/v2/pages' == $request->get_route() && 'GET' == $request->get_method()) {
663 $data = $preloaded_data['parent_pages'];
664
665 $items = array();
666 foreach ($data as $item) {
667 $remote_item = json_decode($item['post']);
668 if ($post && $remote_item && $post->ID != $remote_item->ID) {
669 $controller = new UpdraftCentral_REST_Posts_Controller($remote_item->post_type);
670 $response = $controller->prepare_remote_item_for_response($remote_item, $request, $item['misc']);
671
672 $merged_data = array_merge($response->get_data(), array('_links' => $response->get_links()));
673 array_push($items, $merged_data);
674 }
675 }
676
677 $response = new WP_REST_Response($items);
678 }
679
680 if ('/wp/v2/taxonomies' == $request->get_route() && 'GET' == $request->get_method()) {
681 $controller = new UpdraftCentral_REST_Taxonomies_Controller;
682 if (isset($preloaded_data['taxonomies'])) {
683 $data = $preloaded_data['taxonomies'];
684
685 $taxonomies = isset($data['taxonomies']) ? $data['taxonomies'] : array();
686 if (!empty($taxonomies) && is_array($taxonomies)) {
687 foreach ($taxonomies as $key => $value) {
688 $tax = $controller->prepare_remote_item_for_response($value, $request);
689 $taxonomies[$key] = $controller->prepare_response_for_collection($tax);
690 }
691 }
692
693 $response = new WP_REST_Response($taxonomies);
694 }
695 }
696
697 $match_result = preg_match('#^/wp/v2/taxonomies/(.*)#', $request->get_route(), $matches);
698 if (!empty($match_result) && 'GET' == $request->get_method()) {
699 $taxonomy = $matches[1];
700
701 $controller = new UpdraftCentral_REST_Taxonomies_Controller;
702 if (isset($preloaded_data['taxonomies'])) {
703 $data = $preloaded_data['taxonomies'];
704
705 $result = array();
706 $taxonomies = isset($data['taxonomies']) ? $data['taxonomies'] : array();
707 if (!empty($taxonomies) && is_array($taxonomies)) {
708 foreach ($taxonomies as $key => $value) {
709 $tax = $controller->prepare_remote_item_for_response($value, $request);
710 $taxonomies[$key] = $controller->prepare_response_for_collection($tax);
711 }
712
713 if (!empty($taxonomy) && isset($taxonomies[$taxonomy])) {
714 // For individual taxonomy retrieval
715 $result = $taxonomies[$taxonomy];
716 if (!empty($params['context']) && 'edit' === $params['context']) {
717 if (isset($result['_links'])) unset($result['_links']);
718 }
719 }
720 }
721
722 $response = new WP_REST_Response($result);
723 }
724 }
725
726 if ('/wp/v2/categories' == $request->get_route() && 'GET' == $request->get_method()) {
727 $controller = new UpdraftCentral_REST_Terms_Controller('category');
728 $taxonomies = $preloaded_data['taxonomies']['taxonomies'];
729
730 $terms = array();
731 $categories = isset($preloaded_data['categories']) ? $preloaded_data['categories'] : array();
732 if (!empty($categories) && is_array($categories)) {
733 $terms = $categories['terms'];
734 foreach ($terms as $key => $value) {
735 if (isset($value['term'])) {
736 $term = json_decode($value['term']);
737
738 $misc = $value['misc'];
739 $misc['taxonomy_obj'] = $taxonomies[$misc['taxonomy']];
740
741 $item = $controller->prepare_remote_item_for_response($term, $request, $misc);
742 $terms[$key] = $controller->prepare_response_for_collection($item);
743 }
744 }
745 }
746
747 $response = new WP_REST_Response($terms);
748 }
749
750 if ('/wp/v2/tags' == $request->get_route() && 'GET' == $request->get_method()) {
751 $controller = new UpdraftCentral_REST_Terms_Controller('post_tag');
752 $taxonomies = $preloaded_data['taxonomies']['taxonomies'];
753
754 $terms = array();
755 $tags = isset($preloaded_data['tags']) ? $preloaded_data['tags'] : array();
756 if (!empty($tags) && is_array($tags)) {
757 $terms = $tags['terms'];
758
759 foreach ($terms as $key => $value) {
760 if (isset($value['term'])) {
761 $term = json_decode($value['term']);
762 $misc = $value['misc'];
763 $misc['taxonomy_obj'] = $taxonomies[$misc['taxonomy']];
764
765 $item = $controller->prepare_remote_item_for_response($term, $request, $misc);
766 $terms[$key] = $controller->prepare_response_for_collection($item);
767 }
768 }
769 }
770
771 $response = new WP_REST_Response($terms);
772 }
773
774 if ('/wp/v2/categories' == $request->get_route() && 'POST' === $request->get_method()) {
775 $data = $this->send_remote_command($user_id, 'posts.add_category', $params);
776 if (!is_wp_error($data) && !empty($data)) {
777 $categories = json_decode($data['categories'], true);
778
779 // Update preloaded data:
780 $preloaded_data['categories'] = $categories;
781 $site_meta->update_site_meta($site_id, 'updraftcentral_editor_preloaded_data_'.$post_type, $preloaded_data);
782
783 unset($data['categories']);
784 $response = new WP_REST_Response($data);
785 }
786 }
787
788 if ('/wp/v2/tags' == $request->get_route() && 'POST' === $request->get_method()) {
789 $data = $this->send_remote_command($user_id, 'posts.add_tag', $params);
790 if (!is_wp_error($data) && !empty($data)) {
791 $tags = json_decode($data['tags'], true);
792
793 // Update preloaded data:
794 $preloaded_data['tags'] = $tags;
795 $site_meta->update_site_meta($site_id, 'updraftcentral_editor_preloaded_data_'.$post_type, $preloaded_data);
796
797 unset($data['tags']);
798 $response = new WP_REST_Response($data);
799 }
800 }
801
802 return $response;
803 }
804
805 /**
806 * Creates a new post or return the ID of the existing post
807 *
808 * @param array $data An array of information needed to create a new post if applicable
809 * @return int|bool
810 */
811 private function maybe_create_post_and_return_id($data) {
812 global $wpdb;
813 $query = $wpdb->prepare('SELECT ID FROM '.$wpdb->posts.' WHERE post_name = %s', $data['post_name']);
814 $wpdb->query($query);
815
816 if ($wpdb->num_rows) {
817 $post_id = intval($wpdb->get_var($query));
818 } else {
819 $post_id = wp_insert_post($data);
820 }
821
822 if (is_wp_error($post_id) || empty($post_id)) return false;
823 return $post_id;
824 }
825
826 /**
827 * Loads metaboxees for the classic editor
828 *
829 * @param string $post_type Type of the post submitted
830 * @param WP_Post $post A WP_Post object
831 * @return void
832 */
833 public function load_metaboxes($post_type, $post) {
834 global $post_type_object;
835
836 add_meta_box('submitdiv', __('Publish', 'updraftcentral'), 'post_submit_meta_box', $post->post_type, 'side', 'core', null);
837
838 if ('page' == $post->post_type) {
839 if (post_type_supports($post->post_type, 'page-attributes') || count(get_page_templates($post)) > 0) {
840 add_meta_box('pageparentdiv', $post_type_object->labels->attributes, 'page_attributes_meta_box', $post->post_type, 'side', 'core');
841 }
842 } else {
843 add_meta_box('categorydiv', __('Categories', 'updraftcentral'), array($this, 'post_categories_meta_box'), $post->post_type, 'side', 'core', null);
844
845 add_meta_box('tagsdiv-post_tag', __('Tags', 'updraftcentral'), array($this, 'post_tags_meta_box'), $post->post_type, 'side', 'core', null);
846 }
847
848 if (post_type_supports($post->post_type, 'thumbnail') && current_user_can('upload_files')) {
849 add_meta_box('postimagediv', esc_html($post_type_object->labels->featured_image), 'post_thumbnail_meta_box', $post->post_type, 'side', 'low');
850 }
851 }
852
853 /**
854 * Fetch parent pages for the particular post object (applicable to 'page' post type)
855 *
856 * @return array
857 */
858 public function load_remote_pages() {
859 global $post, $site_id;
860
861 $user = UpdraftCentral()->get_user_object(get_current_user_id());
862 $remote_params = array(
863 'site_id' => $site_id,
864 'data' => array(
865 'command' => 'pages.get_parent_pages',
866 'data' => array(
867 'page' => 1,
868 'per_page' => 100,
869 'exclude' => array($post->ID),
870 'order' => 'ASC',
871 'orderby' => 'menu_order',
872 'status' => 'publish'
873 ),
874 )
875 );
876
877 $remote_response = $user->send_remote_command($remote_params);
878 if (!empty($remote_response) && 'ok' == $remote_response['responsetype']) {
879 if ('rpcok' == $remote_response['rpc_response']['response']) {
880 $data = $remote_response['rpc_response']['data'];
881 return $data['pages'];
882 }
883 }
884
885 return array();
886 }
887
888 /**
889 * Setup the global post data so that any underlying processes will
890 * get to see and acknowledge the remote post as the current object
891 *
892 * @param array $post_data The current post data to edit
893 * @param bool $disable_screen Whether to disable setting the screen or not
894 * @return WP_Post
895 */
896 private function setup_remotepost_data($post_data, $disable_screen = false) {
897 global $post;
898
899 // We need to setup and cache this edited post data so that other processes
900 // or hooks that will eventually rely on this information will succeed.
901 $post = new WP_Post((object) $post_data);
902 if ($post) {
903 setup_postdata($post);
904 if (!$disable_screen) {
905 set_current_screen($post->post_type);
906 }
907
908 // Make sure that this new object gets inserted into the cache
909 // otherwise, WP won't be able to see this information as these are
910 // coming from the remote website and not a local WP_Post object.
911 //
912 // N.B. This will bypass checking the post information from the database
913 // which in reality doesn't actually exists locally since it is coming from
914 // the remote website.
915 wp_cache_set($post->ID, $post, 'posts');
916 }
917
918 return $post;
919 }
920
921 /**
922 * Extracts preloaded information (styles) by key
923 *
924 * @param array $editor_styles The preloaded editor styles array
925 * @param string $key The key or name of the data to extract
926 *
927 * @return mixed|false
928 */
929 private function filter_preloaded_styles($editor_styles, $key) {
930 $result = array_values(array_filter($editor_styles, function($item) use ($key) {
931 return isset($item[$key]);
932 }));
933
934 if (!empty($result)) {
935 return $result[0][$key];
936 }
937 return false;
938 }
939
940 /**
941 * Store preloaded data from remote which will be accessed later, making succeeding
942 * access to these information much more faster the next time around.
943 *
944 * @param array $params The parameters that goes along with the current request
945 * @return void
946 */
947 public function maybe_store_preloaded_data($params) {
948
949 $data = array();
950 // Preloaded data such as remote taxonomies, categories and tags are stored here if
951 // they exists as not to redo the whole request when a new REST request is executed.
952 if (!empty($params['preloaded_data'])) {
953 $data = json_decode($params['preloaded_data'], true);
954 }
955
956 if (!empty($params['post_data'])) {
957 global $post, $post_data;
958
959 // We might as well store the currently edited post here so that any succeeding REST
960 // request for this particular `post` information will no longer require us to initiate another request
961 // just for getting the same information from the remote website (which is kind of redundant
962 // since we've already got those data loaded in the first place).
963 $post_data = json_decode($params['post_data'], true);
964 $data['post_data'] = $post_data;
965
966 // Setup remote post for local access
967 $post = $this->setup_remotepost_data($post_data['post']);
968 }
969
970 // Store preloaded data as user meta, thus, making them unique for every user wanting
971 // to edit their own remote posts or pages.
972 if (!empty($data) && !empty($params['site_id'])) {
973 global $site_id;
974
975 $site_id = $params['site_id'];
976 $site_meta = $this->get_site_meta_instance();
977 $site_meta->update_site_meta($site_id, 'updraftcentral_editor_preloaded_data_'.$post->post_type, $data);
978 }
979 }
980
981 /**
982 * Loads the Gutenberg needed information to successfully load the block
983 * editor in the client.
984 *
985 * @param array $params A collection of information needed when loading the editor
986 * @return array
987 */
988 public function load_gutenberg_editor($params) {
989 global $post, $post_data;
990
991 // Store preloaded data if not yet been stored.
992 $this->maybe_store_preloaded_data($params);
993
994 ob_start();
995 the_block_editor_meta_boxes();
996 $metaboxes = ob_get_contents();
997 ob_end_clean();
998
999 $nonce = wp_create_nonce('updraftcentral-editpost-'.$post->ID);
1000 $info = array(
1001 'uc_nonce' => $nonce,
1002 'uc_refIds' => base64_encode(get_current_user_id().'|'.$post->ID)
1003 );
1004
1005 $settings = get_user_meta(get_current_user_id(), 'updraftcentral_editor_settings', true);
1006
1007 if (isset($params['preloaded_data'])) {
1008 $preloaded_data = json_decode($params['preloaded_data'], true);
1009 $editor_styles = $preloaded_data['editor_styles'];
1010
1011 $filter_map = array(
1012 'styles' => 'editor_css',
1013 'fonts' => 'font_css',
1014 'theme_fonts' => 'theme_json_fonts',
1015 'defaultEditorStyles' => 'default_editor_css',
1016 'editor_assets' => 'editor_assets',
1017 );
1018
1019 foreach ($filter_map as $key => $value) {
1020 $filtered_data = $this->filter_preloaded_styles($editor_styles, $value);
1021 if (!empty($filtered_data)) $settings[$key] = $filtered_data;
1022 }
1023 }
1024
1025 $settings['availableTemplates'] = array();
1026 if (isset($settings['availableTemplates']) && !empty($params['template_options'])) {
1027 $templates = array();
1028 $options = $params['template_options'];
1029
1030 if (!empty($options)) {
1031 foreach ($options as $value) {
1032 $templates[$value['filename']] = $value['template'];
1033 }
1034 }
1035
1036 $settings['availableTemplates'] = array_merge(array('' => __('Default template', 'updraftcentral')), $templates);
1037 }
1038
1039 $misc = $this->attach_media_to_post($post_data['misc'], $post);
1040
1041 $preloaded = json_decode($params['preloaded_data'], true);
1042 $block_categories = get_block_categories($post);
1043 $block_definitions = get_block_editor_server_block_settings();
1044
1045 if (!empty($preloaded)) {
1046 if (isset($preloaded['block_patterns']) && isset($preloaded['block_pattern_categories'])) {
1047 $settings['__experimentalBlockPatterns'] = $preloaded['block_patterns'];
1048 $settings['__experimentalBlockPatternCategories'] = $preloaded['block_pattern_categories'];
1049 }
1050
1051 $block_categories = $preloaded['block_categories'];
1052 $block_definitions = $preloaded['block_definitions'];
1053 }
1054
1055 return array(
1056 'post' => $post,
1057 'misc' => $misc,
1058 'logo' => trailingslashit(UD_CENTRAL_URL).'images/updraftcentral-logo-landscape.png',
1059 'metaboxes' => $metaboxes,
1060 'settings' => $settings,
1061 'info' => $info,
1062 'has_upload_permissions' => current_user_can('upload_files'), // N.B. We're using the local media library interface when uploading/editing the featured image, so we need to check whether the UpdraftCentral user have the "upload_files" permission. Otherwise, the user won't be able to edit the featured image of a post or page or upload a new one for that matter.
1063 'block_categories' => $block_categories,
1064 'block_definitions' => $block_definitions,
1065 );
1066 }
1067
1068 /**
1069 * Loads the Classic Editor
1070 *
1071 * @param array $params A collection of information needed when loading the editor
1072 * @return array
1073 */
1074 public function load_classic_editor($params) {
1075 global $post_type_object, $post, $site_id, $uc_categories_meta_box, $uc_tags_meta_box, $post_data;
1076
1077 // Store preloaded data if not yet been stored.
1078 $this->maybe_store_preloaded_data($params);
1079
1080 $item = $post_data['misc'];
1081 $site_id = $params['site_id'];
1082 $data = array();
1083
1084 if (!empty($item)) {
1085 if ($post) {
1086 include_once ABSPATH . 'wp-admin/includes/meta-boxes.php';
1087 include_once ABSPATH . 'wp-admin/includes/template.php';
1088
1089 $item = $this->attach_media_to_post($item, $post);
1090 $post_type_object = get_post_type_object($post->post_type);
1091 set_current_screen($post->post_type);
1092
1093 // Make sure that we add the necessary metaboxes for our current post_type (e.g. page or post)
1094 // before actually rendering them.
1095 add_action('add_meta_boxes', array($this, 'load_metaboxes'), 10, 2);
1096 do_action('add_meta_boxes', $post->post_type, $post);
1097
1098 // Grab editor content to put inside a variable
1099 ob_start();
1100 wp_editor($post->post_content, 'uc_classic_editor');
1101 $editor = ob_get_contents();
1102 ob_end_clean();
1103
1104 // Now grab the metaboxes content
1105 ob_start();
1106 do_meta_boxes($post->post_type, 'side', $post);
1107 $metaboxes = ob_get_contents();
1108 ob_end_clean();
1109
1110 $data = array(
1111 'post' => $post,
1112 'misc' => $item,
1113 'logo' => trailingslashit(UD_CENTRAL_URL).'images/updraftcentral-logo-landscape.png',
1114 'editor' => $editor,
1115 'metaboxes' => $metaboxes,
1116 'tags_metabox_content' => $uc_tags_meta_box,
1117 'categories_metabox_content' => $uc_categories_meta_box
1118 );
1119 }
1120 }
1121
1122 return $data;
1123 }
1124
1125 /**
1126 * Searches for the media ID of a given attachment/image
1127 *
1128 * @param string $filename The filename of the image/media
1129 * @return int|bool
1130 */
1131 private function get_media_id_by_name($filename) {
1132 global $wpdb;
1133 $media_id = $wpdb->get_var($wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE guid LIKE '%s'", '%'.$filename));
1134
1135 return $media_id ?: false;
1136 }
1137
1138 /**
1139 * Prepares the image for attachment and attaches it to the post object
1140 *
1141 * @param array $item A data array containing the featured image information
1142 * @param WP_Post $post The WP_Post object to where the featured image is to be attached
1143 *
1144 * @return array
1145 */
1146 private function attach_media_to_post($item, $post) {
1147
1148 // Nothing to do if "featured_media" and "featured_media_url" are both empty, thus, we bail.
1149 $featured_media = (int) $item['featured_media'];
1150 if (empty($featured_media) && empty($item['featured_media_url'])) return $item;
1151
1152 // Attach remote media if non-existing. If 'featured_media' is empty or zero
1153 // and the 'feature_media_url' is non-empty meaning we haven't gotten any local media reference just yet.
1154 // Thus, we're going to attach the remote media to this current post so that the editors can consume
1155 // and display the image to the users.
1156 if (empty($featured_media) && !empty($item['featured_media_url'])) {
1157 $media_id = $this->maybe_download_remote_image($item['featured_media_url']);
1158 if (!empty($media_id)) {
1159 $item['featured_media'] = (int) $media_id;
1160 }
1161 } else {
1162 // Check if featured media (image) still exists, meaning, not deleted/removed.
1163 if (!empty($featured_media)) {
1164 $attachment = wp_get_attachment_image_src($featured_media);
1165 if (empty($attachment)) {
1166 $item['featured_media'] = 0;
1167
1168 // Try downloading the image, if the remote page/post currently has
1169 // a featured_media_url set.
1170 if (!empty($item['featured_media_url'])) {
1171 $media_id = $this->maybe_download_remote_image($item['featured_media_url']);
1172 if (!empty($media_id)) {
1173 $item['featured_media'] = (int) $media_id;
1174 }
1175 }
1176 }
1177 }
1178 }
1179
1180 if (!empty($item['featured_media']) && $post) {
1181 set_post_thumbnail($post, (int) $item['featured_media']);
1182 }
1183
1184 return $item;
1185 }
1186
1187 /**
1188 * Saves or downloads the media (attachment/image) from UpdraftCentral
1189 *
1190 * @param string $image_url The URL of the image to download (if needed)
1191 * @param string $image_data The image data to save. If empty, image_url will be used to download the image
1192 * @return int
1193 */
1194 private function maybe_download_remote_image($image_url, $image_data = '') {
1195 if (empty($image_url)) return false;
1196
1197 $image = pathinfo($image_url);
1198 $image_name = $image['basename'];
1199
1200 $media_id = $this->get_media_id_by_name($image_name);
1201 if (!empty($media_id)) {
1202 return $media_id;
1203 }
1204
1205 $upload_dir = wp_upload_dir();
1206 if (empty($image_data)) {
1207 $response = wp_remote_get($image_url);
1208 if (!is_wp_error($response)) {
1209 $image_data = wp_remote_retrieve_body($response);
1210 }
1211 } else {
1212 $image_data = base64_decode($image_data);
1213 }
1214
1215 $media_id = 0;
1216 if (!empty($image_data)) {
1217 $filename = $image_name;
1218
1219 if (wp_mkdir_p($upload_dir['path'])) {
1220 $file = trailingslashit($upload_dir['path']).$filename;
1221 $guid = trailingslashit($upload_dir['url']).$filename;
1222 } else {
1223 $file = trailingslashit($upload_dir['basedir']).$filename;
1224 $guid = trailingslashit($upload_dir['baseurl']).$filename;
1225 }
1226
1227 file_put_contents($file, $image_data);
1228 $wp_filetype = wp_check_filetype($filename, null);
1229
1230 $attachment = array(
1231 'guid' => $guid,
1232 'post_mime_type' => $wp_filetype['type'],
1233 'post_title' => sanitize_file_name($filename),
1234 'post_content' => '',
1235 'post_status' => 'inherit'
1236 );
1237
1238 $media_id = wp_insert_attachment($attachment, $file);
1239 include_once(ABSPATH . 'wp-admin/includes/image.php');
1240
1241 $attach_data = wp_generate_attachment_metadata($media_id, $file);
1242 wp_update_attachment_metadata($media_id, $attach_data);
1243 }
1244
1245 return $media_id;
1246 }
1247
1248 /**
1249 * Gathers post categories metabox information to be rendered
1250 * in the client later on using the Handlerbarsjs templating system
1251 *
1252 * @param WP_Post $post Post object
1253 */
1254 public function post_categories_meta_box($post) {
1255 global $uc_categories_meta_box, $site_id;
1256
1257 $site_meta = $this->get_site_meta_instance();
1258 $preloaded_data = $site_meta->get_site_meta($site_id, 'updraftcentral_editor_preloaded_data_'.$post->post_type, true);
1259 $options = $misc = array();
1260
1261 if (!empty($preloaded_data)) {
1262 if (isset($preloaded_data['categories'])) {
1263 $options = $preloaded_data['categories']['misc'];
1264 }
1265
1266 if (isset($preloaded_data['post_data'])) {
1267 $misc = $preloaded_data['post_data']['misc'];
1268 }
1269 }
1270
1271 if (empty($options) || empty($misc)) return;
1272
1273 $taxonomy = json_decode($options['tax']);
1274 $popular_terms_checklist = $options['popular'];
1275 $terms_checklist = $misc['categories_checklist'];
1276 $parent_dropdown = $options['parent_dropdown'];
1277
1278 // We're pulling and rendering the template in the client, so, we're
1279 // preparing the information for the template's consumption.
1280 $uc_categories_meta_box = array(
1281 'labels' => array(
1282 'all_items' => isset($taxonomy->labels->all_items) ? $taxonomy->labels->all_items : __('All Categories', 'updraftcentral'),
1283 'most_used' => isset($taxonomy->labels->most_used) ? esc_html($taxonomy->labels->most_used) : __('Most Used', 'updraftcentral'),
1284 'add_new_item' => isset($taxonomy->labels->add_new_item) ? $taxonomy->labels->add_new_item : __('Add New Category', 'updraftcentral')
1285 ),
1286 'attributes' => array(
1287 'new_item_name' => isset($taxonomy->labels->new_item_name) ? esc_attr($taxonomy->labels->new_item_name) : __('New Category Name', 'updraftcentral'),
1288 'add_new_item' => isset($taxonomy->labels->add_new_item) ? esc_attr($taxonomy->labels->add_new_item) : __('Add New Category', 'updraftcentral')
1289 ),
1290 'can_edit_terms' => (bool) $options['capabilities']['can_edit_terms'],
1291 'popular_terms_checklist' => $popular_terms_checklist,
1292 'terms_checklist' => $terms_checklist,
1293 'parent_dropdown' => $parent_dropdown
1294 );
1295 }
1296
1297 /**
1298 * Gathers post tags metabox information to be rendered
1299 * in the client later on using the Handlerbarsjs templating system
1300 *
1301 * @param WP_Post $post Post object
1302 */
1303 public function post_tags_meta_box($post) {
1304 global $uc_tags_meta_box, $site_id;
1305
1306 $site_meta = $this->get_site_meta_instance();
1307 $preloaded_data = $site_meta->get_site_meta($site_id, 'updraftcentral_editor_preloaded_data_'.$post->post_type, true);
1308 $options = $misc = array();
1309
1310 if (!empty($preloaded_data)) {
1311 if (isset($preloaded_data['tags'])) {
1312 $options = $preloaded_data['tags']['misc'];
1313 }
1314
1315 if (isset($preloaded_data['post_data'])) {
1316 $misc = $preloaded_data['post_data']['misc'];
1317 }
1318 }
1319
1320 if (empty($options) || empty($misc)) return;
1321
1322 $tag_cloud = $options['tag_cloud'];
1323 $taxonomy = json_decode($options['tax']);
1324
1325 $terms_list = array();
1326 $terms_to_edit = '';
1327 if (!empty($misc['tags_list'])) {
1328 $terms_to_edit = str_replace(', ', ',', $misc['tags_list']);
1329 $terms_list = explode(',', $terms_to_edit);
1330 }
1331
1332 // We're pulling and rendering the template in the client, so, we're
1333 // preparing the information for the template's consumption.
1334 $uc_tags_meta_box = array(
1335 'labels' => array(
1336 'add_or_remove_items' => isset($taxonomy->labels->add_or_remove_items) ? $taxonomy->labels->add_or_remove_items : __('Add or remove tags', 'updraftcentral'),
1337 'add_new_item' => isset($taxonomy->labels->add_new_item) ? $taxonomy->labels->add_new_item : __('Add New Tag', 'updraftcentral'),
1338 'separate_items_with_commas' => isset($taxonomy->labels->separate_items_with_commas) ? $taxonomy->labels->separate_items_with_commas : __('Separate tags with commas', 'updraftcentral'),
1339 'no_terms' => isset($taxonomy->labels->no_terms) ? $taxonomy->labels->no_terms : __('No tags', 'updraftcentral'),
1340 'choose_from_most_used' => isset($taxonomy->labels->choose_from_most_used) ? $taxonomy->labels->choose_from_most_used : __('Choose from the most used tags', 'updraftcentral')
1341 ),
1342 'attributes' => array(
1343 'add' => __('Add', 'updraftcentral'),
1344 ),
1345 'can_assign_terms' => (bool) $options['capabilities']['can_assign_terms'],
1346 'terms_to_edit' => $terms_to_edit,
1347 'terms_list' => $terms_list,
1348 'tag_cloud' => $tag_cloud
1349 );
1350 }
1351 }
1352
1353 endif;
1354