PluginProbe ʕ •ᴥ•ʔ
Kirki – Freeform Page Builder, Website Builder & Customizer / 6.0.13
Kirki – Freeform Page Builder, Website Builder & Customizer v6.0.13
6.1.1 6.1.0 6.0.14 6.0.13 6.0.12 6.0.11 6.0.10 6.0.9 6.0.8 6.0.7 6.0.6 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 4.0.19 4.0.20 4.0.21 4.0.22 4.0.23 4.0.24 4.1 4.2.0 5.0.0 5.1.0 5.1.1 5.2.0 5.2.1 5.2.2 5.2.3 6.0.0 trunk 3.0.40 3.0.41 3.0.42 3.0.43 3.0.44 3.0.45 3.1.0 3.1.1 3.1.2
kirki / includes / Ajax / Page.php
kirki / includes / Ajax Last commit date
Collaboration 2 weeks ago Apps.php 2 weeks ago Collection.php 1 month ago Comments.php 2 months ago DynamicContent.php 1 month ago ExportImport.php 2 weeks ago Form.php 2 weeks ago Media.php 2 weeks ago Page.php 2 weeks ago PageSettings.php 2 weeks ago RBAC.php 2 weeks ago Symbol.php 2 weeks ago Taxonomy.php 2 months ago TemplateExportImport.php 2 months ago UserData.php 2 weeks ago Users.php 2 months ago Walkthrough.php 2 months ago WordpressData.php 2 months ago WpAdmin.php 2 months ago
Page.php
1088 lines
1 <?php
2 /**
3 * Page or post data manager
4 *
5 * @package kirki
6 */
7
8 namespace Kirki\Ajax;
9
10 if ( ! defined( 'ABSPATH' ) ) {
11 exit; // Exit if accessed directly.
12 }
13 use Kirki\HelperFunctions;
14 use Kirki\Staging;
15
16 /**
17 * Page API Class
18 */
19 class Page {
20
21 const TYPE_FORGOT_PASSWORD = 'forgot_password';
22 const TYPE_RESET_PASSWORD = 'reset_password';
23
24 /**
25 * Save page data
26 *
27 * @return void wp_send_json.
28 *
29 * @deprecated
30 * @see Kirki\App\Services\PageService::save_page_data()
31 */
32 public static function save_page_data() {
33 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
34 $page_data = isset( $_POST['data'] ) ? $_POST['data'] : null;
35 $page_data = json_decode( stripslashes( $page_data ), true );
36 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
37 $post_id = (int) HelperFunctions::sanitize_text( isset( $_POST['id'] ) ? $_POST['id'] : '' );
38 $is_staging = isset( $_POST['is_staging'] ) ? HelperFunctions::sanitize_text( $_POST['is_staging'] ) : false;
39
40 if ( ! empty( $page_data ) && ! empty( $post_id ) ) {
41
42 $version_where_saved = HelperFunctions::save_kirki_data_to_db( $post_id, $page_data, $is_staging );
43
44 $post = get_post( $post_id );
45 $arr = array(
46 'ID' => $post->ID,
47 'type' => $post->post_type,
48 );
49 $post_id = wp_update_post( $arr );
50 wp_send_json(
51 array(
52 'status' => 'Page data saved.',
53 'staging_version' => $version_where_saved,
54 )
55 );
56 } else {
57 wp_send_json( array( 'status' => 'Page data save failed!' ) );
58 }
59 die();
60 }
61
62 /**
63 * Delete page
64 *
65 * @return void wp_send_json.
66 *
67 * @deprecated
68 * @see Kirki\App\Services\PageService::delete_page()
69 */
70 public static function delete_page() {
71 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
72 $id = (int) HelperFunctions::sanitize_text( isset( $_POST['id'] ) ? $_POST['id'] : '' );
73 $post = get_post( $id );
74 wp_delete_post( $id );
75 if ( $post && $post->post_type === 'kirki_utility' ) {
76 self::flush_utility_rewrite_rules();
77 }
78 wp_send_json( array( 'status' => 'Page deleted' ) );
79 }
80
81 /**
82 * Add new page
83 *
84 * @return void wp_send_json.
85 *
86 * @deprecated
87 * @see Kirki\App\Services\PageService::save()
88 */
89 public static function add_new_page() {
90 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
91 $options = isset( $_POST['options'] ) ? $_POST['options'] : null;
92 $options = json_decode( stripslashes( $options ), true );
93
94 if ( HelperFunctions::user_has_post_edit_access() ) {
95 $post_id = wp_insert_post(
96 array(
97 'post_title' => $options['post_title'],
98 'post_name' => $options['post_title'],
99 // check if type = kirki_page then change it to wp page type. cause we only set template if page type is kirki_page.
100 'post_type' => $options['post_type'] === 'kirki_page' ? 'page' : $options['post_type'],
101 )
102 );
103
104 if ( isset( $options['blocks'] ) ) {
105 // this is for popup creation. cause popup has predefined blocks.
106 update_post_meta( $post_id, 'kirki', $options['blocks'] );
107 }
108
109 if ( isset( $options['conditions'] ) ) {
110 // this is for template creation. cause popup has predefined conditions.
111 update_post_meta( $post_id,'kirki_template_conditions', $options['conditions'] );
112 }
113
114 // TODO: need to remove this code. after checking collection_type used or not
115 if ( isset( $options['collection_type'] ) && ! empty( $options['collection_type'] ) ) {
116 update_post_meta( $post_id,'kirki_template_collection_type', $options['collection_type'] );
117 }
118
119 if ( isset( $options['utility_page_type'] ) && ! empty( $options['utility_page_type'] ) ) {
120 update_post_meta( $post_id,'kirki_utility_page_type', $options['utility_page_type'] );
121 }
122
123 update_post_meta( $post_id, KIRKI_META_NAME_FOR_POST_EDITOR_MODE, 'kirki' );
124 if ( $options['post_type'] === 'page' || $options['post_type'] === 'kirki_page' ) {
125 // check if type = kirki_page then change it to wp page type. cause we only set template if page type is kirki_page.
126 update_post_meta( $post_id, '_wp_page_template', HelperFunctions::get_kirki_full_canvas_template_path() );
127 }
128
129 if ( $options['post_type'] ==='kirki_utility' ) {
130 self::initialize_predefine_template_data( $post_id, $options['utility_page_type'] );
131 self::flush_utility_rewrite_rules();
132 }
133
134 if ( isset( $options['custom_template'] ) && ! empty( $options['custom_template'] ) &&
135 isset( $options['custom_template']['url'] ) && ! empty( $options['custom_template']['url'] ) ) {
136 self::add_custom_template_to_page( $post_id, $options['custom_template']['url'] );
137 }
138
139 wp_send_json( ( new self() )->format_single_post( $post_id ) );
140 } else {
141 wp_send_json_error( 'Limited permission', 403 );
142 }
143 }
144
145 /**
146 * @deprecated
147 * @see \Kirki\App\Supports\Template::assign_utility_page_template()
148 */
149 public static function initialize_predefine_template_data( $post_id, $type ) {
150 if ( $type === '404' || $type === 'login' || $type === 'sign_up' || $type === 'forgot_password' || $type === 'reset_password' || $type === 'retrive_username' ) {
151 self::fetch_template_data( $post_id, $type );
152 }
153 }
154
155 /**
156 * @deprecated
157 * @see \Kirki\App\Supports\Template::assign_custom_page_template()
158 */
159 public static function add_custom_template_to_page( $post_id, $template_url ) {
160 self::fetch_template_data( $post_id, $template_url, true );
161 }
162
163 /**
164 * @deprecated
165 * @see \Kirki\App\Supports\Template::process_template()
166 */
167 public static function fetch_template_data( $post_id, $type, $custom = false ) {
168 $zip_file_path = KIRKI_PUBLIC_ASSETS_URL . '/pre-built-pages/basic/' . $type . '.zip';
169 if ( $custom ) {
170 $zip_file_path = $type;
171 }
172 $file_name_new = uniqid( '', true ) . '.zip'; // 'random.ext'
173 $zip_file_path = HelperFunctions::download_zip_from_remote( $zip_file_path, $file_name_new );
174 if ( $zip_file_path ) {
175 $d = ExportImport::process_kirki_template_zip( $zip_file_path, false, $post_id );
176 if ( $d ) {
177 // delete zip file
178 wp_delete_file( $zip_file_path );
179 return true;
180 } else {
181 wp_send_json_error( 'Failed to extract zip file' );
182 }
183 } else {
184 wp_send_json_error( 'Failed to download zip file' );
185 }
186 }
187
188 /**
189 * Update current page data
190 *
191 * @return void wp_send_json.
192 * @deprecated
193 * @see \Kirki\App\Services\PageService::update()
194 * @see \Kirki\App\Services\PageService::update_popup_data()
195 */
196 public static function update_page_data() {
197 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
198 $options = isset( $_POST['options'] ) ? $_POST['options'] : null;
199 $options = json_decode( stripslashes( $options ), true );
200 $arr = array();
201 if ( isset( $options['ID'] ) ) {
202 $arr['ID'] = $options['ID'];
203 $post_id = $arr['ID'];
204 if ( isset( $options['post_title'] ) ) {
205 $arr['post_title'] = $options['post_title'];
206 }
207 if ( isset( $options['post_name'] ) ) {
208 $arr['post_name'] = $options['post_name'];
209 }
210 if ( isset( $options['post_status'] ) ) {
211 $arr['post_status'] = $options['post_status'];
212 }
213 wp_update_post( $arr );
214
215 if ( isset( $options['blocks'] ) ) {
216 update_post_meta( $post_id, 'kirki', $options['blocks'] );
217 }
218 if ( isset( $options['styleBlocks'] ) ) {
219 update_post_meta( $post_id, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', $options['styleBlocks'] );
220 }
221 if ( isset( $options['usedFonts'] ) ) {
222 update_post_meta( $post_id, KIRKI_META_NAME_FOR_USED_FONT_LIST, $options['usedFonts'] );
223 }
224 if ( isset( $options['conditions'] ) ) {
225 update_post_meta( $post_id,'kirki_template_conditions', $options['conditions'] );
226 }
227 if ( isset( $options['variableMode'] ) ) {
228 update_post_meta( $post_id, 'kirki_variable_mode', $options['variableMode'] );
229 }
230 if ( isset( $options['post_name'] ) ) {
231 $post = get_post( $post_id );
232 if ( $post && $post->post_type === 'kirki_utility' ) {
233 self::flush_utility_rewrite_rules();
234 }
235 }
236 wp_send_json( ( new self() )->format_single_post( $post_id ) );
237 die();
238 } else {
239 wp_send_json( array( 'status' => 'Page data update failed' ) );
240 die();
241 }
242 }
243
244 /**
245 * Duplicate page data
246 *
247 * @return void wp_send_json.
248 * @deprecated
249 * @see \Kirki\App\Services\PageService::duplicate_page()
250 */
251 public static function duplicate_page() {
252 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
253 $post_id = (int) HelperFunctions::sanitize_text( isset( $_POST['id'] ) ? $_POST['id'] : '' );
254 $post = get_post( $post_id );
255 $new_post_id = wp_insert_post(
256 array(
257 'post_title' => $post->post_title . ' (copy)',
258 'post_content' => $post->post_content,
259 'post_name' => $post->post_name,
260 'post_type' => $post->post_type,
261 'post_status' => $post->post_status,
262 )
263 );
264
265 $page_data = get_post_meta( $post_id, 'kirki', true );
266 if ( $page_data ) {
267 update_post_meta( $new_post_id, 'kirki', $page_data );
268 update_post_meta( $new_post_id, KIRKI_META_NAME_FOR_POST_EDITOR_MODE, 'kirki' );
269 }
270
271 /**
272 * Also duplicate _wp_page_template meta if exists
273 */
274 $page_template = get_post_meta( $post_id, '_wp_page_template', true );
275 if ( $page_template ) {
276 $page_template = HelperFunctions::normalize_kirki_full_canvas_template_path($page_template);
277 update_post_meta( $new_post_id, '_wp_page_template', $page_template );
278 }
279
280 /**
281 * Also duplicate this page style blocks if exists
282 */
283 $post_styles = get_post_meta( $post_id, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', true );
284 if ( $post_styles ) {
285 update_post_meta( $new_post_id, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', $post_styles );
286 }
287
288 $used_fonts = get_post_meta( $post_id, KIRKI_META_NAME_FOR_USED_FONT_LIST, true );
289 if ( $used_fonts ) {
290 update_post_meta( $new_post_id, KIRKI_META_NAME_FOR_USED_FONT_LIST, $used_fonts );
291 }
292
293 if ( $post && $post->post_type === 'kirki_utility' ) {
294 self::flush_utility_rewrite_rules();
295 }
296
297 wp_send_json( ( new self() )->format_single_post( $new_post_id ) );
298 }
299
300 /**
301 * Back to kirki editor
302 *
303 * @return void wp_send_json.
304 *
305 * @deprecated
306 * @see \Kirki\App\Services\EditorService::back_to_kirki_editor()
307 */
308 public static function back_to_kirki_editor() {
309 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
310 $post_id = (int) HelperFunctions::sanitize_text( isset( $_POST['postId'] ) ? $_POST['postId'] : '' );
311
312 $post = get_post( $post_id );
313
314 if ( $post->post_status === 'auto-draft' ) {
315 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
316 $post_title = HelperFunctions::sanitize_text( isset( $_POST['title'] ) ? $_POST['title'] : null );
317
318 if ( ! isset( $post_title ) ) {
319 $post_title = 'Untitled';
320 }
321
322 $data = array(
323 'ID' => $post_id,
324 'post_title' => $post_title,
325 'post_name' => $post_title,
326 'post_status' => 'draft',
327 );
328 wp_update_post( $data );
329 }
330
331 update_post_meta( $post_id, '_wp_page_template', HelperFunctions::get_kirki_full_canvas_template_path() );
332 wp_send_json( array( 'status' => true ) );
333 }
334
335 /**
336 * Back to WordPress editor
337 *
338 * @return void wp_send_json.
339 *
340 * @deprecated
341 * @see \Kirki\App\Services\EditorService::back_to_wordpress_editor()
342 */
343 public static function back_to_wordpress_editor() {
344 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
345 $post_id = (int) HelperFunctions::sanitize_text( isset( $_POST['postId'] ) ? $_POST['postId'] : '' );
346
347 delete_post_meta( $post_id, KIRKI_META_NAME_FOR_POST_EDITOR_MODE );
348 wp_send_json( array( 'status' => true ) );
349 }
350
351 /**
352 * This function is called from EDITOR panel
353 *
354 * @return void wp_send_json.
355 */
356 public static function get_page_blocks_and_styles() {
357 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
358 $post_id = (int) HelperFunctions::sanitize_text( isset( $_GET['id'] ) ? $_GET['id'] : '' );
359 $stage_version = HelperFunctions::sanitize_text( isset( $_GET['stage_version'] ) ? intval( $_GET['stage_version'] ) : false );
360 if ( ! $stage_version ) {
361 $stage_version = Staging::get_most_recent_stage_version( $post_id, false );
362 }
363
364 if ( ! empty( $post_id ) ) {
365 $post_meta = get_post_meta( $post_id, 'kirki', true );
366 if ( ! $post_meta ) {
367 $post_meta = array();
368 $post_meta['blocks'] = null;
369 }
370
371 if ( $stage_version ) {
372 $meta_name = Staging::get_staged_meta_name( 'kirki', $post_id, $stage_version );
373 $staging_post_meta = get_post_meta( $post_id, $meta_name, true );
374 if ( $staging_post_meta ) {
375 $post_meta = $staging_post_meta;
376 }
377 }
378
379 $styles = HelperFunctions::get_page_styleblocks( $post_id, $stage_version );
380 $post_meta['styles'] = $styles;
381
382 $post_meta['preview_url'] = HelperFunctions::get_post_url_arr_from_post_id( $post_id, array( 'preview_url' => true ) )['preview_url'];
383
384 $post_meta['is_kirki_editor_mode'] = HelperFunctions::is_editor_mode_is_kirki( $post_id );
385
386 $content = get_the_content( null, false, $post_id );
387 $post_meta['content_length'] = strlen( $content );
388 wp_send_json( $post_meta );
389 }
390 die();
391 }
392
393 public static function get_page_html() {
394 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
395 $post_id = (int) HelperFunctions::sanitize_text( isset( $_GET['id'] ) ? $_GET['id'] : '' );
396 if ( ! empty( $post_id ) ) {
397 $post_meta = get_post_meta( $post_id, 'kirki', true );
398 if ( ! $post_meta ) {
399 $post_meta = array();
400 $post_meta['blocks'] = null;
401 }
402
403 $params = array(
404 'blocks' => $post_meta['blocks'],
405 'style_blocks' => null,
406 'root' => 'root',
407 'post_id' => false,
408 'options' => array( 'check_access' => false ),
409 'get_style' => false,
410 'get_variable' => false,
411 'should_take_app_script' => false,
412 );
413
414 $html = HelperFunctions::get_html_using_preview_script( $params );
415 wp_send_json( $html );
416 }
417 die();
418 }
419
420 /**
421 * Format single post data
422 *
423 * @param int $post_id post id.
424 * @return object|null post with custom data.
425 *
426 * @deprecated
427 * @see \Kirki\App\Resources\PageResource
428 */
429 public function format_single_post( $post_id ) {
430 $post = get_post( $post_id );
431 if ( $post ) {
432 $page = array();
433 if ('kirki_popup' === $post->post_type ) {
434 $page['blocks'] = get_post_meta( $post->ID, 'kirki', true );
435 $page['styleBlocks'] = get_post_meta( $post->ID, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', true );
436 $page['usedFonts'] = get_post_meta( $post->ID, KIRKI_META_NAME_FOR_USED_FONT_LIST, true );
437 }
438
439 if ('kirki_template' === $post->post_type ) {
440 $conditions = get_post_meta( $post->ID,'kirki_template_conditions', true );
441 $page['conditions'] = $conditions ? $conditions : array();
442 $collection_type = get_post_meta( $post->ID,'kirki_template_collection_type', true );
443 $page['collection_type'] = $collection_type ? $collection_type : '';
444 }
445
446 if ('kirki_utility' === $post->post_type ) {
447 $utility_type_page = get_post_meta( $post->ID,'kirki_utility_page_type', true );
448 $page['utility_page_type'] = $utility_type_page ? $utility_type_page : '';
449 }
450
451 $temp_urls = HelperFunctions::get_post_url_arr_from_post_id(
452 $post->ID,
453 array(
454 'preview_url' => true,
455 'editor_url' => true,
456 )
457 );
458 $page['preview_url'] = $temp_urls['preview_url'];
459 $page['editor_url'] = $temp_urls['editor_url'];
460
461 $page['id'] = $post->ID;
462 $page['title'] = $post->post_title;
463 $page['status'] = $post->post_status;
464 $page['post_type'] = $post->post_type;
465 $page['post_parent'] = $post->post_parent;
466 $page['slug'] = $post->post_name;
467 $page['variableMode'] = self::get_variable_mode( $post->ID );
468 $page['isFrontPage'] = get_option( 'page_on_front' ) == $post->ID ? true : false;
469
470 $disabled_page_symbols = get_post_meta( $post_id, KIRKI_META_NAME_FOR_PAGE_HF_SYMBOL_DISABLE_STATUS, true );
471 if ( ! isset( $disabled_page_symbols ) || ! is_array( $disabled_page_symbols ) ) {
472 $disabled_page_symbols = array();
473 }
474 $page['disabled_page_symbols'] = $disabled_page_symbols;
475 $page = self::add_published_staged_info( $page );
476
477 return $page;
478 }
479 return null;
480 }
481
482 /**
483 * @deprecated
484 * @see \Kirki\App\Resources\PageResource::get_staged_last_updated()
485 */
486 public static function add_published_staged_info( $page ){
487 $staged_info = Staging::get_published_stage_version_info( $page['id'] );
488 $page['staged_last_updated'] = isset($staged_info['last_updated']) ? $staged_info['last_updated'] : null;
489 return $page;
490 }
491
492 /**
493 * @deprecated
494 * @see \Kirki\App\Managers\PageManager::get_variable_mode()
495 */
496 public static function get_variable_mode( $post_id ) {
497 $variable_mode = get_post_meta( $post_id, 'kirki_variable_mode', true );
498 return $variable_mode ? $variable_mode : 'inherit';
499 }
500
501 /**
502 * Fetch page list
503 *
504 * @return void wp_send_json.
505 */
506 public static function fetch_list_api() {
507 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
508 $post_types = HelperFunctions::sanitize_text( isset( $_GET['post_types'] ) ? $_GET['post_types'] : '[]' );
509 $post_types = json_decode( $post_types, true );
510 $exclude_post_ids = json_decode( HelperFunctions::sanitize_text( isset( $_GET['exclude_post_ids'] ) ? $_GET['exclude_post_ids'] : '[]' ), true );
511
512 $query = HelperFunctions::sanitize_text( isset( $_GET['query'] ) ? $_GET['query'] : null );
513 $numberposts = HelperFunctions::sanitize_text( isset( $_GET['numberposts'] ) ? $_GET['numberposts'] : 20 );
514
515 $page_list = array();
516 if ( HelperFunctions::user_has_post_edit_access() ) {
517 $page_list = static::fetch_list( $post_types, true, array( 'publish', 'draft' ), $query, $numberposts, 1, $exclude_post_ids );
518 }
519
520 wp_send_json( $page_list );
521 }
522
523 public static function get_pages_for_pages_panel() {
524 // Sanitize and validate inputs
525 $query = HelperFunctions::sanitize_text( isset( $_GET['query'] ) ? $_GET['query'] : null );
526 $page = HelperFunctions::sanitize_text( isset( $_GET['page'] ) ? $_GET['page'] : 1 );
527 $numberposts = intval( HelperFunctions::sanitize_text( isset( $_GET['numberposts'] ) ? $_GET['numberposts'] : 20 ) );
528 $post_types = HelperFunctions::sanitize_text( isset( $_GET['post_types'] ) ? $_GET['post_types'] : '[]' );
529 $post_types = json_decode( $post_types, true );
530
531 // Set a default post type if not provided
532 if ( empty( $post_types ) ) {
533 $post_types = array( 'page' ); // Default to pages if no post types are provided
534 }
535 $page_list = array();
536 $page_list = static::fetch_list( $post_types, true, array( 'publish', 'draft' ), $query, $numberposts, $page );
537 // if ( HelperFunctions::user_has_page_edit_access() ) {
538 // }
539
540 // Get total posts count
541 $total_arg = array(
542 'post_type' => $post_types,
543 'post_status' => array( 'publish', 'draft' ),
544 'posts_per_page' => -1,
545 'fields' => 'ids',
546 );
547 if ( $query ) {
548 $total_arg['s'] = $query;
549 }
550 $total_posts = count(get_posts($total_arg));
551
552 // Return the data as a JSON response
553 wp_send_json_success( array(
554 'pages' => $page_list,
555 'total' => $total_posts,
556 ) );
557 }
558
559 /**
560 * Fetch post list for search
561 *
562 * @return void wp_send_json.
563 */
564 public static function get_data_list_for_template_edit_search_flyout() {
565 $query = HelperFunctions::sanitize_text( isset( $_GET['query'] ) ? $_GET['query'] : '' );
566 $conditions = HelperFunctions::sanitize_text( isset( $_GET['conditions'] ) ? $_GET['conditions'] : array() );
567 $conditions = json_decode( $conditions, true );
568 $data = HelperFunctions::get_collection_items_from_conditions( $conditions, $query );
569 wp_send_json( $data['data'] );
570 }
571
572 /**
573 * Get all post types and found the all post types that are not discarded post types
574 *
575 * @return void wp_send_json
576 */
577 public static function fetch_post_list_data_post_type_wise() {
578
579 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
580 $search_query = HelperFunctions::sanitize_text( isset( $_GET['search'] ) ? $_GET['search'] : '' );
581
582 $post_types = get_post_types();
583 $discarded_post_types = array( 'attachment', 'custom_css', 'customize_changeset', 'wp_global_styles', 'revision', 'nav_menu_item', 'oembed_cache', 'user_request', 'wp_block', 'wp_template', 'wp_template_part', 'wp_navigation' );
584
585 $post_types['kirki_template'] = 'kirki_template';
586 $post_types['kirki_utility'] = 'kirki_utility';
587 $post_types['kirki_popup'] = 'kirki_popup';
588
589 $post_types = array_diff_key( $post_types, array_flip( $discarded_post_types ) );
590
591 $args = array(
592 'post_type' => $post_types,
593 's' => $search_query,
594 'posts_per_page' => -1,
595 'post_status' => 'any',
596 );
597
598 $all_posts = get_posts( $args );
599 $data = array();
600
601 // Post types to be grouped under "page"
602 $group_under_page = array( 'kirki_template', 'kirki_utility', 'kirki_page' );
603
604 foreach ( $all_posts as $p ) {
605 $single_post = array(
606 'id' => $p->ID,
607 'title' => $p->post_title,
608 'editor_url' => HelperFunctions::get_post_url_arr_from_post_id( $p->ID, array( 'editor_url' => true ) )['editor_url'],
609 );
610
611 // Normalize post_type
612 $type_key = in_array( $p->post_type, $group_under_page, true ) ? 'page' : $p->post_type;
613 $data[ $type_key ][] = $single_post;
614 }
615
616 wp_send_json( $data );
617 }
618
619 /**
620 * Fetch page list
621 * if $internal is true then it will return array
622 * otherwise it will return json for api call
623 *
624 * @param string $type post type.
625 * @param boolean $internal if this method call from internal response.
626 * @param string $post_status post status.
627 *
628 * @return void|array
629 */
630 public static function fetch_list( $type = 'page', $internal = true, $post_status = array( 'publish', 'draft' ), $query = null, $numberposts = 20, $current_page = 1, $exclude_post_ids = array() ) {
631 $pages = array();
632
633 $arg = array(
634 'post_type' => $type,
635 'post_status' => $post_status,
636 // 'numberposts' => $numberposts,
637 'orderby' => 'ID',
638 'order' => 'DESC',
639 'posts_per_page' => $numberposts,
640 'paged' => $current_page,
641 'post__not_in' => $exclude_post_ids,
642 );
643 if ( $query ) {
644 $arg['s'] = $query;
645 }
646
647 $posts = get_posts( $arg );
648
649 if ( ! empty( $posts ) ) {
650 foreach ( $posts as $post ) {
651
652 /**
653 * If page template type is kirki full page then check if GET['type'] is set to kirki_page otherwise send any page type data
654 */
655 $pages[] = ( new self() )->format_single_post( $post->ID );
656 }
657 }
658
659 // $pages items has isFrontPage true then add it to first position of array also do not duplicate same item
660 $frontPage = null;
661
662 foreach ($pages as $key => $page) {
663 if ($page['isFrontPage']) {
664 $frontPage = $page;
665 unset($pages[$key]); // remove original to avoid duplication
666 break;
667 }
668 }
669
670 if ($frontPage) {
671 array_unshift($pages, $frontPage); // add to first position
672 }
673
674 $pages = array_values($pages); // reindex array
675
676 if ( $internal ) {
677 return $pages;
678 }
679 wp_send_json( $pages );
680 }
681
682 /**
683 * Get current page data
684 *
685 * @return void wp_send_json.
686 */
687 public static function get_current_page_data() {
688 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
689 $post_id = (int) HelperFunctions::sanitize_text( isset( $_GET['id'] ) ? $_GET['id'] : '' );
690 $post_formatted = null;
691 if ( $post_id ) {
692 $post_formatted = ( new self() )->format_single_post( $post_id );
693 }
694 wp_send_json( $post_formatted );
695 }
696
697 /**
698 * Remove all unused style blocks from option meta
699 * it will collect all posts unused style block id
700 * then it will remove all unused style blocks from option meta
701 *
702 * @return void wp_send_json.
703 *
704 */
705 public static function remove_unused_style_block_from_db() {
706 $post_id = (int) HelperFunctions::sanitize_text( $_POST['post_id'] ?? '' );
707
708 if ( ! $post_id || ! get_post( $post_id ) ) {
709 wp_send_json_error( array( 'message' => 'Invalid post ID.' ) );
710 }
711
712 $all_post_ids = self::get_all_post_ids();
713 $all_used_style_ids = array_flip( self::get_all_used_style_ids() ); // faster lookup
714
715 // Helper to clean any style array
716 /**
717 * @see Kirki\App\Managers\PageManager::clean_styles()
718 */
719 $clean_styles = function ( array $styles ) use ( $all_used_style_ids ) {
720 $changed = false;
721 foreach ( $styles as $key => $style ) {
722 if ( ! isset( $all_used_style_ids[ $key ] ) && empty( $style['isDefault'] ) ) {
723 unset( $styles[ $key ] );
724 $changed = true;
725 }
726 }
727 return array( $styles, $changed );
728 };
729
730 // Clean global styles.
731 $all_global_styles = HelperFunctions::get_global_data_using_key( KIRKI_GLOBAL_STYLE_BLOCK_META_KEY ) ? HelperFunctions::get_global_data_using_key( KIRKI_GLOBAL_STYLE_BLOCK_META_KEY ) : array();
732 $result = (array) $clean_styles( $all_global_styles );
733 $all_global_styles = $result[0] ?? array();
734 $changed = $result[1] ?? false;
735 if ( $changed ) {
736 HelperFunctions::save_global_style_blocks( $all_global_styles );
737 }
738
739 // Clean post styles
740 foreach ( $all_post_ids as $p_id ) {
741 // Random styles
742 $post_styles = get_post_meta( $p_id, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', true ) ?: array();
743 $temp_result = (array) $clean_styles( $post_styles );
744 $post_styles = $temp_result[0] ?? array();
745 $changed = $temp_result[1] ?? false; // $changed
746 if ( $changed ) {
747 HelperFunctions::save_random_style_blocks( $p_id, $post_styles );
748 }
749
750 // Staged styles
751 $most_recent_stage_id = Staging::get_most_recent_unpublished_stage_id( $p_id );
752 if ( $most_recent_stage_id ) {
753 foreach ( array(
754 KIRKI_GLOBAL_STYLE_BLOCK_META_KEY,
755 KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random',
756 ) as $meta_key_base ) {
757 $meta_key = Staging::get_staged_meta_name( $meta_key_base, $p_id, $most_recent_stage_id );
758 $staged_styles = get_post_meta( $p_id, $meta_key, true ) ? get_post_meta( $p_id, $meta_key, true ) : array();
759
760 $temp_styles = $clean_styles( $staged_styles );
761
762 $staged_styles = $temp_styles[0] ?? array();
763 $changed = $temp_styles[1] ?? false;
764
765 if ( $changed ) {
766 HelperFunctions::save_staged_style_blocks( $p_id, $meta_key, $staged_styles );
767 }
768 }
769 }
770 }
771
772 wp_send_json(
773 array(
774 'status' => 'success',
775 'data' => HelperFunctions::get_page_styleblocks( $post_id ),
776 )
777 );
778 }
779 /**
780 * Get unused class info from db
781 *
782 * @param boolean $internal if this method call from internally.
783 * @return void|array wp_send_json.
784 */
785 public static function get_unused_class_info_from_db( $internal = false ) {
786 $all_post_ids = self::get_all_post_ids();
787 $all_used_style_ids = self::get_all_used_style_ids();
788
789 // Add global style IDs
790 $all_style_ids = array();
791
792 // Add global style IDs exclude default
793 $global_styles = HelperFunctions::get_global_data_using_key( KIRKI_GLOBAL_STYLE_BLOCK_META_KEY ) ?: array();
794 foreach ( $global_styles as $key => $style ) {
795 if ( empty( $style['isDefault'] ) ) {
796 $all_style_ids[] = $key;
797 }
798 }
799
800 // Add all post style IDs excluding default
801 foreach ( $all_post_ids as $p_id ) {
802 $post_styles = get_post_meta( $p_id, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', true ) ?: array();
803 foreach ( $post_styles as $key => $style ) {
804 if ( empty( $style['isDefault'] ) ) {
805 $all_style_ids[] = $key;
806 }
807 }
808 }
809
810 $all_style_ids = array_unique( $all_style_ids );
811
812 // Filter out any IDs that are used anywhere
813 $common_unused = array_values(
814 array_filter(
815 $all_style_ids,
816 function ( $id ) use ( $all_used_style_ids ) {
817 return ! in_array( $id, $all_used_style_ids, true );
818 }
819 )
820 );
821
822 if ( $internal ) {
823 return $common_unused;
824 }
825
826 wp_send_json(
827 array(
828 'status' => 'success',
829 'data' => $common_unused,
830 )
831 );
832 }
833
834 /**
835 * Collect all post IDs (including draft, published)
836 *
837 * @return array
838 *
839 * @deprecated
840 * @see \Kirki\App\Managers\PageManager::get_all_block_post_ids()
841 */
842 private static function get_all_post_ids() {
843 global $wpdb;
844
845 $results = $wpdb->get_col(
846 $wpdb->prepare(
847 "SELECT DISTINCT pm.post_id
848 FROM {$wpdb->postmeta} AS pm
849 INNER JOIN {$wpdb->posts} AS p ON p.ID = pm.post_id
850 WHERE pm.meta_key = %s
851 AND p.post_type NOT IN (%s, %s)",
852 'kirki',
853 'kirki_symbol',
854 'kirki_popup'
855 )
856 );
857
858 return $results;
859 }
860
861 /**
862 * Collect all used style IDs across published + most recent staged version.
863 *
864 * @return array
865 */
866 private static function get_all_used_style_ids() {
867 $all_post_ids = self::get_all_post_ids();
868 $all_used_style_ids = array();
869
870 foreach ( $all_post_ids as $p_id ) {
871 // Published
872 $published_used_ids = get_post_meta( $p_id, KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS, true ) ?: array();
873 $published_used_ids_random = get_post_meta( $p_id, KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS . '_random', true ) ?: array();
874 $published_used_ids = array_unique( array_merge( $published_used_ids, $published_used_ids_random ) );
875
876 // Most recent staged
877 $most_recent_stage_id = Staging::get_most_recent_unpublished_stage_id( $p_id );
878 $staged_used_ids = array();
879 if ( $most_recent_stage_id ) {
880 $staged_used_keys = array(
881 Staging::get_staged_meta_name( KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS, $p_id, $most_recent_stage_id ),
882 Staging::get_staged_meta_name( KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS . '_random', $p_id, $most_recent_stage_id ),
883 );
884 foreach ( $staged_used_keys as $key ) {
885 $staged_used_ids = array_merge( $staged_used_ids, get_post_meta( $p_id, $key, true ) ?: array() );
886 }
887 }
888
889 $all_used_style_ids = array_merge( $all_used_style_ids, $published_used_ids, $staged_used_ids );
890 }
891
892 return array_unique( $all_used_style_ids );
893 }
894
895 public static function validate_wp_post_slug() {
896 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
897 $post_id = (int) HelperFunctions::sanitize_text( isset( $_GET['post_id'] ) ? $_GET['post_id'] : '' );
898 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
899 $post_type = HelperFunctions::sanitize_text( isset( $_GET['post_type'] ) ? $_GET['post_type'] : '' );
900 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
901 $post_name = HelperFunctions::sanitize_text( isset( $_GET['post_name'] ) ? $_GET['post_name'] : '' );
902
903 wp_send_json(
904 array(
905 'status' => 'success',
906 'data' => HelperFunctions::validate_slug( $post_id, $post_type, $post_name ),
907 )
908 );
909 }
910
911 /**
912 * @deprecated
913 * @see function \Kirki\App\soft_flush_rewrite_rules()
914 */
915 private static function flush_utility_rewrite_rules() {
916 flush_rewrite_rules( false );
917 }
918
919 public static function get_editor_read_only_access_data() {
920 wp_send_json(
921 array(
922 'status' => 'success',
923 'data' => self::format_editor_access_data(),
924 )
925 );
926 }
927
928 private static function format_editor_access_data() {
929 $status = HelperFunctions::get_global_data_using_key( 'kirki_editor_read_only_access_status' );
930 $arr = array(
931 'status' => $status ? $status : false,
932 'url' => self::get_post_read_only_access_url(),
933 );
934 return $arr;
935 }
936
937 public static function save_editor_read_only_access_data() {
938 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
939 $data = isset( $_POST['data'] ) ? $_POST['data'] : null;
940 $data = json_decode( stripslashes( $data ), true );
941
942 if ( $data['type'] === 'status' ) {
943 HelperFunctions::update_global_data_using_key( 'kirki_editor_read_only_access_status', HelperFunctions::sanitize_text( $data['status'] ) );
944 }
945
946 if ( $data['type'] === 'regenerate' ) {
947 self::generate_read_only_access_token();
948 }
949
950 wp_send_json(
951 array(
952 'status' => 'success',
953 'data' => self::format_editor_access_data(),
954 )
955 );
956 }
957
958 private static function get_post_read_only_access_url() {
959 $token = HelperFunctions::get_global_data_using_key( 'kirki_editor_read_only_access_token' );
960 if ( ! $token ) {
961 $token = self::generate_read_only_access_token();
962 }
963
964 // Try to get the home page ID first
965 $home_page_id = get_option( 'page_on_front' ); // Retrieves the ID of the homepage if set
966
967 if ( $home_page_id ) {
968 $home_page_url_arr = HelperFunctions::get_post_url_arr_from_post_id( $home_page_id, array( 'editor_url' => true ) );
969 return esc_url( $home_page_url_arr['editor_url'] ) . '&editor-preview-token=' . $token;
970 }
971
972 // If no homepage is set, fallback to the last edited kirki editor page
973 $last_edited_kirki_editor_page = HelperFunctions::get_last_edited_kirki_editor_type_page();
974 if ( $last_edited_kirki_editor_page ) {
975 $last_edited_kirki_editor_page_url_arr = HelperFunctions::get_post_url_arr_from_post_id( $last_edited_kirki_editor_page->ID, array( 'editor_url' => true ) );
976 return esc_url( $last_edited_kirki_editor_page_url_arr['editor_url'] ) . '&editor-preview-token=' . $token;
977 }
978
979 // If neither the home page nor the last edited page is found, default to home URL
980 return home_url( '?action=kirki&editor-preview-token=' . $token );
981 }
982
983 private static function generate_read_only_access_token() {
984 $token = wp_generate_password( 32, false, false ); // Generate a secure random token
985 HelperFunctions::update_global_data_using_key( 'kirki_editor_read_only_access_token', $token );
986 return $token;
987 }
988 /**
989 * Get all global used style block ids
990 * first get all posts used global style ids
991 * then merge and returns.
992 *
993 * @return array style ids.
994 */
995 private static function get_all_global_used_style_block_ids() {
996 global $wpdb;
997 //phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.DirectQuery
998 $used_global_ids = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}postmeta WHERE meta_key = '" . KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS . "'", OBJECT );
999
1000 $all_used_block_ids = array();
1001 foreach ( $used_global_ids as $key => $p_meta ) {
1002 $this_used_global = get_post_meta( $p_meta->post_id, $p_meta->meta_key, true );
1003 $all_used_block_ids = array_merge( $all_used_block_ids, $this_used_global );
1004 }
1005 $all_used_block_ids_global = array_unique( $all_used_block_ids );
1006 return $all_used_block_ids_global;
1007 }
1008
1009 public static function get_all_data_by_kirki_meta_key() {
1010 global $wpdb;
1011 //phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.DirectQuery
1012 // $all_page_meta_data = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}postmeta WHERE meta_key = 'kirki'", ARRAY_A );
1013 $all_page_meta_data = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}postmeta WHERE meta_key = 'kirki' ORDER BY meta_id DESC", ARRAY_A );
1014
1015 return $all_page_meta_data;
1016 }
1017
1018 /**
1019 * Get all global unused style block ids
1020 * first get all posts used global style ids using get_all_global_used_style_block_ids()
1021 * then collect and return.
1022 *
1023 * @return array style ids.
1024 */
1025 private static function get_unused_global_style_ids() {
1026 $all_used_ids = self::get_all_global_used_style_block_ids();
1027 $styles = HelperFunctions::get_global_data_using_key( KIRKI_GLOBAL_STYLE_BLOCK_META_KEY );
1028 $unused_keys = array();
1029
1030 foreach ( $styles as $key => $sb ) {
1031
1032 // we will also remove default style block too. if it is not used in any post. and added latest style block from front end.
1033 if ( ( true || ( ( isset( $sb['isDefault'] ) && ! $sb['isDefault'] ) || ! isset( $sb['isDefault'] ) ) ) && ! in_array( $key, $all_used_ids, true ) ) {
1034 $unused_keys[] = $key;
1035 }
1036 }
1037 return $unused_keys;
1038 }
1039
1040 /**
1041 * Get all post unused style block ids
1042 * first get all posts used post style ids using get_unused_post_style_ids()
1043 * then collect and return.
1044 *
1045 * @param int $post_id wp post id.
1046 * @return array style ids.
1047 */
1048 private static function get_unused_post_style_ids( $post_id ) {
1049 $all_used_ids = get_post_meta( $post_id, KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS . '_random', true );
1050 $styles = get_post_meta( $post_id, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', true );
1051
1052 if ( ! $styles ) {
1053 return array();
1054 }
1055 $unused_keys = array();
1056
1057 foreach ( $styles as $key => $sb ) {
1058 if ( ! $all_used_ids || ! in_array( $key, $all_used_ids, true ) ) {
1059 $unused_keys[] = $key;
1060 }
1061 }
1062 return $unused_keys;
1063 }
1064
1065 /**
1066 * @deprecated
1067 * @see Kirki\App\Services\PageService::toggle_disabled_page_symbols()
1068 */
1069 public static function toggle_disabled_page_symbols() {
1070 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1071 $post_id = (int) HelperFunctions::sanitize_text( isset( $_POST['post_id'] ) ? $_POST['post_id'] : get_the_ID() );
1072 $symbol_type = HelperFunctions::sanitize_text( isset( $_POST['symbol_type'] ) ? $_POST['symbol_type'] : null );
1073 $disable = HelperFunctions::sanitize_text( isset( $_POST['disable'] ) ? $_POST['disable'] : null );
1074
1075 if ( $post_id && $symbol_type && $disable ) {
1076 $prev_status = get_post_meta( $post_id, KIRKI_META_NAME_FOR_PAGE_HF_SYMBOL_DISABLE_STATUS, true );
1077 if ( ! isset( $prev_status ) || ! is_array( $prev_status ) ) {
1078 $prev_status = array();
1079 }
1080 $disable = filter_var( $disable, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ) ?? false;
1081 $current_status = array_merge( $prev_status, array( $symbol_type => $disable ) );
1082 update_post_meta( $post_id, KIRKI_META_NAME_FOR_PAGE_HF_SYMBOL_DISABLE_STATUS, $current_status );
1083 wp_send_json( array( 'status' => 'Page data saved.' ) );
1084 }
1085 wp_send_json( array( 'status' => 'Page data save failed!' ) );
1086 }
1087 }
1088