PluginProbe ʕ •ᴥ•ʔ
Kirki – Freeform Page Builder, Website Builder & Customizer / 6.2.0
Kirki – Freeform Page Builder, Website Builder & Customizer v6.2.0
6.2.0 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 4 days ago Apps.php 1 month ago Collection.php 1 month ago Comments.php 3 months ago DynamicContent.php 4 days ago ExportImport.php 2 weeks ago Form.php 1 month ago Media.php 2 weeks ago Page.php 4 days ago PageSettings.php 1 month ago RBAC.php 1 month ago Symbol.php 1 month ago Taxonomy.php 3 months ago TemplateExportImport.php 3 months ago UserData.php 1 month ago Users.php 3 months ago Walkthrough.php 4 days ago WordpressData.php 3 months ago WpAdmin.php 2 weeks ago
Page.php
1082 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 * @deprecated
357 * @see \Kirki\App\Resources\PageContentResource::class
358 */
359 public static function get_page_blocks_and_styles() {
360 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
361 $post_id = (int) HelperFunctions::sanitize_text( isset( $_GET['id'] ) ? $_GET['id'] : '' );
362 $stage_version = HelperFunctions::sanitize_text( isset( $_GET['stage_version'] ) ? intval( $_GET['stage_version'] ) : false );
363 if ( ! $stage_version ) {
364 $stage_version = Staging::get_most_recent_stage_version( $post_id, false );
365 }
366
367 if ( ! empty( $post_id ) ) {
368 $post_meta = get_post_meta( $post_id, 'kirki', true );
369 if ( ! $post_meta ) {
370 $post_meta = array();
371 $post_meta['blocks'] = null;
372 }
373
374 if ( $stage_version ) {
375 $meta_name = Staging::get_staged_meta_name( 'kirki', $post_id, $stage_version );
376 $staging_post_meta = get_post_meta( $post_id, $meta_name, true );
377 if ( $staging_post_meta ) {
378 $post_meta = $staging_post_meta;
379 }
380 }
381
382 $styles = HelperFunctions::get_page_styleblocks( $post_id, $stage_version );
383 $post_meta['styles'] = $styles;
384
385 $post_meta['preview_url'] = HelperFunctions::get_post_url_arr_from_post_id( $post_id, array( 'preview_url' => true ) )['preview_url'];
386
387 $post_meta['is_kirki_editor_mode'] = HelperFunctions::is_editor_mode_is_kirki( $post_id );
388
389 $content = get_the_content( null, false, $post_id );
390 $post_meta['content_length'] = strlen( $content );
391 wp_send_json( $post_meta );
392 }
393 die();
394 }
395
396 /**
397 * Format single post data
398 *
399 * @param int $post_id post id.
400 * @return object|null post with custom data.
401 *
402 * @deprecated
403 * @see \Kirki\App\Resources\PageResource
404 */
405 public function format_single_post( $post_id ) {
406 $post = get_post( $post_id );
407 if ( $post ) {
408 $page = array();
409 if ('kirki_popup' === $post->post_type ) {
410 $page['blocks'] = get_post_meta( $post->ID, 'kirki', true );
411 $page['styleBlocks'] = get_post_meta( $post->ID, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', true );
412 $page['usedFonts'] = get_post_meta( $post->ID, KIRKI_META_NAME_FOR_USED_FONT_LIST, true );
413 }
414
415 if ('kirki_template' === $post->post_type ) {
416 $conditions = get_post_meta( $post->ID,'kirki_template_conditions', true );
417 $page['conditions'] = $conditions ? $conditions : array();
418 $collection_type = get_post_meta( $post->ID,'kirki_template_collection_type', true );
419 $page['collection_type'] = $collection_type ? $collection_type : '';
420 }
421
422 if ('kirki_utility' === $post->post_type ) {
423 $utility_type_page = get_post_meta( $post->ID,'kirki_utility_page_type', true );
424 $page['utility_page_type'] = $utility_type_page ? $utility_type_page : '';
425 }
426
427 $temp_urls = HelperFunctions::get_post_url_arr_from_post_id(
428 $post->ID,
429 array(
430 'preview_url' => true,
431 'editor_url' => true,
432 )
433 );
434 $page['preview_url'] = $temp_urls['preview_url'];
435 $page['editor_url'] = $temp_urls['editor_url'];
436
437 $page['id'] = $post->ID;
438 $page['title'] = $post->post_title;
439 $page['status'] = $post->post_status;
440 $page['post_type'] = $post->post_type;
441 $page['post_parent'] = $post->post_parent;
442 $page['slug'] = $post->post_name;
443 $page['variableMode'] = self::get_variable_mode( $post->ID );
444 $page['isFrontPage'] = get_option( 'page_on_front' ) == $post->ID ? true : false;
445
446 $disabled_page_symbols = get_post_meta( $post_id, KIRKI_META_NAME_FOR_PAGE_HF_SYMBOL_DISABLE_STATUS, true );
447 if ( ! isset( $disabled_page_symbols ) || ! is_array( $disabled_page_symbols ) ) {
448 $disabled_page_symbols = array();
449 }
450 $page['disabled_page_symbols'] = $disabled_page_symbols;
451 $page = self::add_published_staged_info( $page );
452
453 return $page;
454 }
455 return null;
456 }
457
458 /**
459 * @deprecated
460 * @see \Kirki\App\Resources\PageResource::get_staged_last_updated()
461 */
462 public static function add_published_staged_info( $page ){
463 $staged_info = Staging::get_published_stage_version_info( $page['id'] );
464 $page['staged_last_updated'] = isset($staged_info['last_updated']) ? $staged_info['last_updated'] : null;
465 return $page;
466 }
467
468 /**
469 * @deprecated
470 * @see \Kirki\App\Managers\PageManager::get_variable_mode()
471 */
472 public static function get_variable_mode( $post_id ) {
473 $variable_mode = get_post_meta( $post_id, 'kirki_variable_mode', true );
474 return $variable_mode ? $variable_mode : 'inherit';
475 }
476
477 /**
478 * Fetch page list
479 *
480 * @return void wp_send_json.
481 * @deprecated
482 * @see \Kirki\App\Http\Controllers\Api\PageController::paginated()
483 */
484 public static function fetch_list_api() {
485 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
486 $post_types = HelperFunctions::sanitize_text( isset( $_GET['post_types'] ) ? $_GET['post_types'] : '[]' );
487 $post_types = json_decode( $post_types, true );
488 $exclude_post_ids = json_decode( HelperFunctions::sanitize_text( isset( $_GET['exclude_post_ids'] ) ? $_GET['exclude_post_ids'] : '[]' ), true );
489
490 $query = HelperFunctions::sanitize_text( isset( $_GET['query'] ) ? $_GET['query'] : null );
491 $numberposts = HelperFunctions::sanitize_text( isset( $_GET['numberposts'] ) ? $_GET['numberposts'] : 20 );
492
493 $page_list = array();
494 if ( HelperFunctions::user_has_post_edit_access() ) {
495 $page_list = static::fetch_list( $post_types, true, array( 'publish', 'draft' ), $query, $numberposts, 1, $exclude_post_ids );
496 }
497
498 wp_send_json( $page_list );
499 }
500
501 /**
502 * @deprecated
503 * @see \Kirki\App\Http\Controllers\Api\PageController::page_panel_pages()
504 */
505 public static function get_pages_for_pages_panel() {
506 // Sanitize and validate inputs
507 $query = HelperFunctions::sanitize_text( isset( $_GET['query'] ) ? $_GET['query'] : null );
508 $page = HelperFunctions::sanitize_text( isset( $_GET['page'] ) ? $_GET['page'] : 1 );
509 $numberposts = intval( HelperFunctions::sanitize_text( isset( $_GET['numberposts'] ) ? $_GET['numberposts'] : 20 ) );
510 $post_types = HelperFunctions::sanitize_text( isset( $_GET['post_types'] ) ? $_GET['post_types'] : '[]' );
511 $post_types = json_decode( $post_types, true );
512
513 // Set a default post type if not provided
514 if ( empty( $post_types ) ) {
515 $post_types = array( 'page' ); // Default to pages if no post types are provided
516 }
517 $page_list = array();
518 $page_list = static::fetch_list( $post_types, true, array( 'publish', 'draft' ), $query, $numberposts, $page );
519 // if ( HelperFunctions::user_has_page_edit_access() ) {
520 // }
521
522 // Get total posts count
523 $total_arg = array(
524 'post_type' => $post_types,
525 'post_status' => array( 'publish', 'draft' ),
526 'posts_per_page' => -1,
527 'fields' => 'ids',
528 );
529 if ( $query ) {
530 $total_arg['s'] = $query;
531 }
532 $total_posts = count(get_posts($total_arg));
533
534 // Return the data as a JSON response
535 wp_send_json_success( array(
536 'pages' => $page_list,
537 'total' => $total_posts,
538 ) );
539 }
540
541 /**
542 * Fetch post list for search
543 *
544 * @return void wp_send_json.
545 * @deprecated
546 * @see \Kirki\App\Http\Controllers\Api\PageController::get_data_list_for_template_edit_search_flyout()
547 */
548 public static function get_data_list_for_template_edit_search_flyout() {
549 $query = HelperFunctions::sanitize_text( isset( $_GET['query'] ) ? $_GET['query'] : '' );
550 $conditions = HelperFunctions::sanitize_text( isset( $_GET['conditions'] ) ? $_GET['conditions'] : array() );
551 $conditions = json_decode( $conditions, true );
552 $data = HelperFunctions::get_collection_items_from_conditions( $conditions, $query );
553 wp_send_json( $data['data'] );
554 }
555
556 /**
557 * Get all post types and found the all post types that are not discarded post types
558 *
559 * @return void wp_send_json
560 */
561 public static function fetch_post_list_data_post_type_wise() {
562
563 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
564 $search_query = HelperFunctions::sanitize_text( isset( $_GET['search'] ) ? $_GET['search'] : '' );
565
566 $post_types = get_post_types();
567 $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' );
568
569 $post_types['kirki_template'] = 'kirki_template';
570 $post_types['kirki_utility'] = 'kirki_utility';
571 $post_types['kirki_popup'] = 'kirki_popup';
572
573 $post_types = array_diff_key( $post_types, array_flip( $discarded_post_types ) );
574
575 $args = array(
576 'post_type' => $post_types,
577 's' => $search_query,
578 'posts_per_page' => -1,
579 'post_status' => 'any',
580 );
581
582 $all_posts = get_posts( $args );
583 $data = array();
584
585 // Post types to be grouped under "page"
586 $group_under_page = array( 'kirki_template', 'kirki_utility', 'kirki_page' );
587
588 foreach ( $all_posts as $p ) {
589 $single_post = array(
590 'id' => $p->ID,
591 'title' => $p->post_title,
592 'editor_url' => HelperFunctions::get_post_url_arr_from_post_id( $p->ID, array( 'editor_url' => true ) )['editor_url'],
593 );
594
595 // Normalize post_type
596 $type_key = in_array( $p->post_type, $group_under_page, true ) ? 'page' : $p->post_type;
597 $data[ $type_key ][] = $single_post;
598 }
599
600 wp_send_json( $data );
601 }
602
603 /**
604 * Fetch page list
605 * if $internal is true then it will return array
606 * otherwise it will return json for api call
607 *
608 * @param string $type post type.
609 * @param boolean $internal if this method call from internal response.
610 * @param string $post_status post status.
611 *
612 * @return void|array
613 * @deprecated
614 * @see \Kirki\App\Services\PageService::paginated()
615 */
616 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() ) {
617 $pages = array();
618
619 $arg = array(
620 'post_type' => $type,
621 'post_status' => $post_status,
622 // 'numberposts' => $numberposts,
623 'orderby' => 'ID',
624 'order' => 'DESC',
625 'posts_per_page' => $numberposts,
626 'paged' => $current_page,
627 'post__not_in' => $exclude_post_ids,
628 );
629 if ( $query ) {
630 $arg['s'] = $query;
631 }
632
633 $posts = get_posts( $arg );
634
635 if ( ! empty( $posts ) ) {
636 foreach ( $posts as $post ) {
637
638 /**
639 * If page template type is kirki full page then check if GET['type'] is set to kirki_page otherwise send any page type data
640 */
641 $pages[] = ( new self() )->format_single_post( $post->ID );
642 }
643 }
644
645 // $pages items has isFrontPage true then add it to first position of array also do not duplicate same item
646 $frontPage = null;
647
648 foreach ($pages as $key => $page) {
649 if ($page['isFrontPage']) {
650 $frontPage = $page;
651 unset($pages[$key]); // remove original to avoid duplication
652 break;
653 }
654 }
655
656 if ($frontPage) {
657 array_unshift($pages, $frontPage); // add to first position
658 }
659
660 $pages = array_values($pages); // reindex array
661
662 if ( $internal ) {
663 return $pages;
664 }
665 wp_send_json( $pages );
666 }
667
668 /**
669 * Get current page data
670 *
671 * @return void wp_send_json.
672 * @deprecated
673 * @see \Kirki\App\Http\Controllers\Api\PageController::get_current_page()
674 */
675 public static function get_current_page_data() {
676 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
677 $post_id = (int) HelperFunctions::sanitize_text( isset( $_GET['id'] ) ? $_GET['id'] : '' );
678 $post_formatted = null;
679 if ( $post_id ) {
680 $post_formatted = ( new self() )->format_single_post( $post_id );
681 }
682 wp_send_json( $post_formatted );
683 }
684
685 /**
686 * Remove all unused style blocks from option meta
687 * it will collect all posts unused style block id
688 * then it will remove all unused style blocks from option meta
689 *
690 * @return void wp_send_json.
691 *
692 */
693 public static function remove_unused_style_block_from_db() {
694 $post_id = (int) HelperFunctions::sanitize_text( $_POST['post_id'] ?? '' );
695
696 if ( ! $post_id || ! get_post( $post_id ) ) {
697 wp_send_json_error( array( 'message' => 'Invalid post ID.' ) );
698 }
699
700 $all_post_ids = self::get_all_post_ids();
701 $all_used_style_ids = array_flip( self::get_all_used_style_ids() ); // faster lookup
702
703 // Helper to clean any style array
704 /**
705 * @see Kirki\App\Managers\PageManager::clean_styles()
706 */
707 $clean_styles = function ( array $styles ) use ( $all_used_style_ids ) {
708 $changed = false;
709 foreach ( $styles as $key => $style ) {
710 if ( ! isset( $all_used_style_ids[ $key ] ) && empty( $style['isDefault'] ) ) {
711 unset( $styles[ $key ] );
712 $changed = true;
713 }
714 }
715 return array( $styles, $changed );
716 };
717
718 // Clean global styles.
719 $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();
720 $result = (array) $clean_styles( $all_global_styles );
721 $all_global_styles = $result[0] ?? array();
722 $changed = $result[1] ?? false;
723 if ( $changed ) {
724 HelperFunctions::save_global_style_blocks( $all_global_styles );
725 }
726
727 // Clean post styles
728 foreach ( $all_post_ids as $p_id ) {
729 // Random styles
730 $post_styles = get_post_meta( $p_id, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', true ) ?: array();
731 $temp_result = (array) $clean_styles( $post_styles );
732 $post_styles = $temp_result[0] ?? array();
733 $changed = $temp_result[1] ?? false; // $changed
734 if ( $changed ) {
735 HelperFunctions::save_random_style_blocks( $p_id, $post_styles );
736 }
737
738 // Staged styles
739 $most_recent_stage_id = Staging::get_most_recent_unpublished_stage_id( $p_id );
740 if ( $most_recent_stage_id ) {
741 foreach ( array(
742 KIRKI_GLOBAL_STYLE_BLOCK_META_KEY,
743 KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random',
744 ) as $meta_key_base ) {
745 $meta_key = Staging::get_staged_meta_name( $meta_key_base, $p_id, $most_recent_stage_id );
746 $staged_styles = get_post_meta( $p_id, $meta_key, true ) ? get_post_meta( $p_id, $meta_key, true ) : array();
747
748 $temp_styles = $clean_styles( $staged_styles );
749
750 $staged_styles = $temp_styles[0] ?? array();
751 $changed = $temp_styles[1] ?? false;
752
753 if ( $changed ) {
754 HelperFunctions::save_staged_style_blocks( $p_id, $meta_key, $staged_styles );
755 }
756 }
757 }
758 }
759
760 wp_send_json(
761 array(
762 'status' => 'success',
763 'data' => HelperFunctions::get_page_styleblocks( $post_id ),
764 )
765 );
766 }
767 /**
768 * Get unused class info from db
769 *
770 * @param boolean $internal if this method call from internally.
771 * @return void|array wp_send_json.
772 */
773 public static function get_unused_class_info_from_db( $internal = false ) {
774 $all_post_ids = self::get_all_post_ids();
775 $all_used_style_ids = self::get_all_used_style_ids();
776
777 // Add global style IDs
778 $all_style_ids = array();
779
780 // Add global style IDs exclude default
781 $global_styles = HelperFunctions::get_global_data_using_key( KIRKI_GLOBAL_STYLE_BLOCK_META_KEY ) ?: array();
782 foreach ( $global_styles as $key => $style ) {
783 if ( empty( $style['isDefault'] ) ) {
784 $all_style_ids[] = $key;
785 }
786 }
787
788 // Add all post style IDs excluding default
789 foreach ( $all_post_ids as $p_id ) {
790 $post_styles = get_post_meta( $p_id, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', true ) ?: array();
791 foreach ( $post_styles as $key => $style ) {
792 if ( empty( $style['isDefault'] ) ) {
793 $all_style_ids[] = $key;
794 }
795 }
796 }
797
798 $all_style_ids = array_unique( $all_style_ids );
799
800 // Filter out any IDs that are used anywhere
801 $common_unused = array_values(
802 array_filter(
803 $all_style_ids,
804 function ( $id ) use ( $all_used_style_ids ) {
805 return ! in_array( $id, $all_used_style_ids, true );
806 }
807 )
808 );
809
810 if ( $internal ) {
811 return $common_unused;
812 }
813
814 wp_send_json(
815 array(
816 'status' => 'success',
817 'data' => $common_unused,
818 )
819 );
820 }
821
822 /**
823 * Collect all post IDs (including draft, published)
824 *
825 * @return array
826 *
827 * @deprecated
828 * @see \Kirki\App\Managers\PageManager::get_all_block_post_ids()
829 */
830 private static function get_all_post_ids() {
831 global $wpdb;
832
833 $results = $wpdb->get_col(
834 $wpdb->prepare(
835 "SELECT DISTINCT pm.post_id
836 FROM {$wpdb->postmeta} AS pm
837 INNER JOIN {$wpdb->posts} AS p ON p.ID = pm.post_id
838 WHERE pm.meta_key = %s
839 AND p.post_type NOT IN (%s, %s)",
840 'kirki',
841 'kirki_symbol',
842 'kirki_popup'
843 )
844 );
845
846 return $results;
847 }
848
849 /**
850 * Collect all used style IDs across published + most recent staged version.
851 *
852 * @return array
853 */
854 private static function get_all_used_style_ids() {
855 $all_post_ids = self::get_all_post_ids();
856 $all_used_style_ids = array();
857
858 foreach ( $all_post_ids as $p_id ) {
859 // Published
860 $published_used_ids = get_post_meta( $p_id, KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS, true ) ?: array();
861 $published_used_ids_random = get_post_meta( $p_id, KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS . '_random', true ) ?: array();
862 $published_used_ids = array_unique( array_merge( $published_used_ids, $published_used_ids_random ) );
863
864 // Most recent staged
865 $most_recent_stage_id = Staging::get_most_recent_unpublished_stage_id( $p_id );
866 $staged_used_ids = array();
867 if ( $most_recent_stage_id ) {
868 $staged_used_keys = array(
869 Staging::get_staged_meta_name( KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS, $p_id, $most_recent_stage_id ),
870 Staging::get_staged_meta_name( KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS . '_random', $p_id, $most_recent_stage_id ),
871 );
872 foreach ( $staged_used_keys as $key ) {
873 $staged_used_ids = array_merge( $staged_used_ids, get_post_meta( $p_id, $key, true ) ?: array() );
874 }
875 }
876
877 $all_used_style_ids = array_merge( $all_used_style_ids, $published_used_ids, $staged_used_ids );
878 }
879
880 return array_unique( $all_used_style_ids );
881 }
882
883 /**
884 * Validate post slug
885 *
886 * @deprecated
887 * @see \Kirki\App\Http\Controllers\Api\PostController::validate_wp_post_slug()
888 */
889 public static function validate_wp_post_slug() {
890 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
891 $post_id = (int) HelperFunctions::sanitize_text( isset( $_GET['post_id'] ) ? $_GET['post_id'] : '' );
892 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
893 $post_type = HelperFunctions::sanitize_text( isset( $_GET['post_type'] ) ? $_GET['post_type'] : '' );
894 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
895 $post_name = HelperFunctions::sanitize_text( isset( $_GET['post_name'] ) ? $_GET['post_name'] : '' );
896
897 wp_send_json(
898 array(
899 'status' => 'success',
900 'data' => HelperFunctions::validate_slug( $post_id, $post_type, $post_name ),
901 )
902 );
903 }
904
905 /**
906 * @deprecated
907 * @see function \Kirki\App\soft_flush_rewrite_rules()
908 */
909 private static function flush_utility_rewrite_rules() {
910 flush_rewrite_rules( false );
911 }
912
913 public static function get_editor_read_only_access_data() {
914 wp_send_json(
915 array(
916 'status' => 'success',
917 'data' => self::format_editor_access_data(),
918 )
919 );
920 }
921
922 private static function format_editor_access_data() {
923 $status = HelperFunctions::get_global_data_using_key( 'kirki_editor_read_only_access_status' );
924 $arr = array(
925 'status' => $status ? $status : false,
926 'url' => self::get_post_read_only_access_url(),
927 );
928 return $arr;
929 }
930
931 public static function save_editor_read_only_access_data() {
932 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
933 $data = isset( $_POST['data'] ) ? $_POST['data'] : null;
934 $data = json_decode( stripslashes( $data ), true );
935
936 if ( $data['type'] === 'status' ) {
937 HelperFunctions::update_global_data_using_key( 'kirki_editor_read_only_access_status', HelperFunctions::sanitize_text( $data['status'] ) );
938 }
939
940 if ( $data['type'] === 'regenerate' ) {
941 self::generate_read_only_access_token();
942 }
943
944 wp_send_json(
945 array(
946 'status' => 'success',
947 'data' => self::format_editor_access_data(),
948 )
949 );
950 }
951
952 private static function get_post_read_only_access_url() {
953 $token = HelperFunctions::get_global_data_using_key( 'kirki_editor_read_only_access_token' );
954 if ( ! $token ) {
955 $token = self::generate_read_only_access_token();
956 }
957
958 // Try to get the home page ID first
959 $home_page_id = get_option( 'page_on_front' ); // Retrieves the ID of the homepage if set
960
961 if ( $home_page_id ) {
962 $home_page_url_arr = HelperFunctions::get_post_url_arr_from_post_id( $home_page_id, array( 'editor_url' => true ) );
963 return esc_url( $home_page_url_arr['editor_url'] ) . '&editor-preview-token=' . $token;
964 }
965
966 // If no homepage is set, fallback to the last edited kirki editor page
967 $last_edited_kirki_editor_page = HelperFunctions::get_last_edited_kirki_editor_type_page();
968 if ( $last_edited_kirki_editor_page ) {
969 $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 ) );
970 return esc_url( $last_edited_kirki_editor_page_url_arr['editor_url'] ) . '&editor-preview-token=' . $token;
971 }
972
973 // If neither the home page nor the last edited page is found, default to home URL
974 return home_url( '?action=kirki&editor-preview-token=' . $token );
975 }
976
977 private static function generate_read_only_access_token() {
978 $token = wp_generate_password( 32, false, false ); // Generate a secure random token
979 HelperFunctions::update_global_data_using_key( 'kirki_editor_read_only_access_token', $token );
980 return $token;
981 }
982 /**
983 * Get all global used style block ids
984 * first get all posts used global style ids
985 * then merge and returns.
986 *
987 * @return array style ids.
988 */
989 private static function get_all_global_used_style_block_ids() {
990 global $wpdb;
991 //phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.DirectQuery
992 $used_global_ids = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}postmeta WHERE meta_key = '" . KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS . "'", OBJECT );
993
994 $all_used_block_ids = array();
995 foreach ( $used_global_ids as $key => $p_meta ) {
996 $this_used_global = get_post_meta( $p_meta->post_id, $p_meta->meta_key, true );
997 $all_used_block_ids = array_merge( $all_used_block_ids, $this_used_global );
998 }
999 $all_used_block_ids_global = array_unique( $all_used_block_ids );
1000 return $all_used_block_ids_global;
1001 }
1002
1003 public static function get_all_data_by_kirki_meta_key() {
1004 global $wpdb;
1005 //phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.DirectQuery
1006 // $all_page_meta_data = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}postmeta WHERE meta_key = 'kirki'", ARRAY_A );
1007 $all_page_meta_data = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}postmeta WHERE meta_key = 'kirki' ORDER BY meta_id DESC", ARRAY_A );
1008
1009 return $all_page_meta_data;
1010 }
1011
1012 /**
1013 * Get all global unused style block ids
1014 * first get all posts used global style ids using get_all_global_used_style_block_ids()
1015 * then collect and return.
1016 *
1017 * @return array style ids.
1018 */
1019 private static function get_unused_global_style_ids() {
1020 $all_used_ids = self::get_all_global_used_style_block_ids();
1021 $styles = HelperFunctions::get_global_data_using_key( KIRKI_GLOBAL_STYLE_BLOCK_META_KEY );
1022 $unused_keys = array();
1023
1024 foreach ( $styles as $key => $sb ) {
1025
1026 // we will also remove default style block too. if it is not used in any post. and added latest style block from front end.
1027 if ( ( true || ( ( isset( $sb['isDefault'] ) && ! $sb['isDefault'] ) || ! isset( $sb['isDefault'] ) ) ) && ! in_array( $key, $all_used_ids, true ) ) {
1028 $unused_keys[] = $key;
1029 }
1030 }
1031 return $unused_keys;
1032 }
1033
1034 /**
1035 * Get all post unused style block ids
1036 * first get all posts used post style ids using get_unused_post_style_ids()
1037 * then collect and return.
1038 *
1039 * @param int $post_id wp post id.
1040 * @return array style ids.
1041 */
1042 private static function get_unused_post_style_ids( $post_id ) {
1043 $all_used_ids = get_post_meta( $post_id, KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS . '_random', true );
1044 $styles = get_post_meta( $post_id, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', true );
1045
1046 if ( ! $styles ) {
1047 return array();
1048 }
1049 $unused_keys = array();
1050
1051 foreach ( $styles as $key => $sb ) {
1052 if ( ! $all_used_ids || ! in_array( $key, $all_used_ids, true ) ) {
1053 $unused_keys[] = $key;
1054 }
1055 }
1056 return $unused_keys;
1057 }
1058
1059 /**
1060 * @deprecated
1061 * @see Kirki\App\Services\PageService::toggle_disabled_page_symbols()
1062 */
1063 public static function toggle_disabled_page_symbols() {
1064 //phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1065 $post_id = (int) HelperFunctions::sanitize_text( isset( $_POST['post_id'] ) ? $_POST['post_id'] : get_the_ID() );
1066 $symbol_type = HelperFunctions::sanitize_text( isset( $_POST['symbol_type'] ) ? $_POST['symbol_type'] : null );
1067 $disable = HelperFunctions::sanitize_text( isset( $_POST['disable'] ) ? $_POST['disable'] : null );
1068
1069 if ( $post_id && $symbol_type && $disable ) {
1070 $prev_status = get_post_meta( $post_id, KIRKI_META_NAME_FOR_PAGE_HF_SYMBOL_DISABLE_STATUS, true );
1071 if ( ! isset( $prev_status ) || ! is_array( $prev_status ) ) {
1072 $prev_status = array();
1073 }
1074 $disable = filter_var( $disable, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ) ?? false;
1075 $current_status = array_merge( $prev_status, array( $symbol_type => $disable ) );
1076 update_post_meta( $post_id, KIRKI_META_NAME_FOR_PAGE_HF_SYMBOL_DISABLE_STATUS, $current_status );
1077 wp_send_json( array( 'status' => 'Page data saved.' ) );
1078 }
1079 wp_send_json( array( 'status' => 'Page data save failed!' ) );
1080 }
1081 }
1082