File: //home/globfdxw/www/wp-content/plugins/kirki/includes/Ajax/Page.php
<?php
/**
* Page or post data manager
*
* @package kirki
*/
namespace Kirki\Ajax;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
use Kirki\HelperFunctions;
use Kirki\Staging;
/**
* Page API Class
*/
class Page {
/**
* Save page data
*
* @return void wp_send_json.
*/
public static function save_page_data() {
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$page_data = isset( $_POST['data'] ) ? $_POST['data'] : null;
$page_data = json_decode( stripslashes( $page_data ), true );
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$post_id = (int) HelperFunctions::sanitize_text( isset( $_POST['id'] ) ? $_POST['id'] : '' );
$is_staging = isset( $_POST['is_staging'] ) ? HelperFunctions::sanitize_text( $_POST['is_staging'] ) : false;
if ( ! empty( $page_data ) && ! empty( $post_id ) ) {
$version_where_saved = HelperFunctions::save_kirki_data_to_db( $post_id, $page_data, $is_staging );
$post = get_post( $post_id );
$arr = array(
'ID' => $post->ID,
'type' => $post->post_type,
);
$post_id = wp_update_post( $arr );
wp_send_json(
array(
'status' => 'Page data saved.',
'staging_version' => $version_where_saved,
)
);
} else {
wp_send_json( array( 'status' => 'Page data save failed!' ) );
}
die();
}
/**
* Delete page
*
* @return void wp_send_json.
*/
public static function delete_page() {
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$id = (int) HelperFunctions::sanitize_text( isset( $_POST['id'] ) ? $_POST['id'] : '' );
wp_delete_post( $id );
wp_send_json( array( 'status' => 'Page deleted' ) );
}
/**
* Add new page
*
* @return void wp_send_json.
*/
public static function add_new_page() {
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$options = isset( $_POST['options'] ) ? $_POST['options'] : null;
$options = json_decode( stripslashes( $options ), true );
if ( HelperFunctions::user_has_post_edit_access() ) {
$post_id = wp_insert_post(
array(
'post_title' => $options['post_title'],
'post_name' => $options['post_title'],
// check if type = kirki_page then change it to wp page type. cause we only set template if page type is kirki_page.
'post_type' => $options['post_type'] === 'kirki_page' ? 'page' : $options['post_type'],
)
);
if ( isset( $options['blocks'] ) ) {
// this is for popup creation. cause popup has predefined blocks.
update_post_meta( $post_id, 'kirki', $options['blocks'] );
}
if ( isset( $options['conditions'] ) ) {
// this is for template creation. cause popup has predefined conditions.
update_post_meta( $post_id,'kirki_template_conditions', $options['conditions'] );
}
// TODO: need to remove this code. after checking collection_type used or not
if ( isset( $options['collection_type'] ) && ! empty( $options['collection_type'] ) ) {
update_post_meta( $post_id,'kirki_template_collection_type', $options['collection_type'] );
}
if ( isset( $options['utility_page_type'] ) && ! empty( $options['utility_page_type'] ) ) {
update_post_meta( $post_id,'kirki_utility_page_type', $options['utility_page_type'] );
}
update_post_meta( $post_id, KIRKI_META_NAME_FOR_POST_EDITOR_MODE, 'kirki' );
if ( $options['post_type'] === 'page' || $options['post_type'] === 'kirki_page' ) {
// check if type = kirki_page then change it to wp page type. cause we only set template if page type is kirki_page.
update_post_meta( $post_id, '_wp_page_template', HelperFunctions::get_kirki_full_canvas_template_path() );
}
if ( $options['post_type'] ==='kirki_utility' ) {
self::initialize_predefine_template_data( $post_id, $options['utility_page_type'] );
}
if ( isset( $options['custom_template'] ) && ! empty( $options['custom_template'] ) &&
isset( $options['custom_template']['url'] ) && ! empty( $options['custom_template']['url'] ) ) {
self::add_custom_template_to_page( $post_id, $options['custom_template']['url'] );
}
wp_send_json( ( new self() )->format_single_post( $post_id ) );
} else {
wp_send_json_error( 'Limited permission', 403 );
}
}
public static function initialize_predefine_template_data( $post_id, $type ) {
if ( $type === '404' || $type === 'login' || $type === 'sign_up' || $type === 'forgot_password' || $type === 'reset_password' || $type === 'retrive_username' ) {
self::fetch_template_data( $post_id, $type );
}
}
public static function add_custom_template_to_page( $post_id, $template_url ) {
self::fetch_template_data( $post_id, $template_url, true );
}
public static function fetch_template_data( $post_id, $type, $custom = false ) {
$zip_file_path = KIRKI_PUBLIC_ASSETS_URL . '/pre-built-pages/basic/' . $type . '.zip';
if ( $custom ) {
$zip_file_path = $type;
}
$file_name_new = uniqid( '', true ) . '.zip'; // 'random.ext'
$zip_file_path = HelperFunctions::download_zip_from_remote( $zip_file_path, $file_name_new );
if ( $zip_file_path ) {
$d = ExportImport::process_kirki_template_zip( $zip_file_path, false, $post_id );
if ( $d ) {
// delete zip file
wp_delete_file( $zip_file_path );
return true;
} else {
wp_send_json_error( 'Failed to extract zip file' );
}
} else {
wp_send_json_error( 'Failed to download zip file' );
}
}
/**
* Update current page data
*
* @return void wp_send_json.
*/
public static function update_page_data() {
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$options = isset( $_POST['options'] ) ? $_POST['options'] : null;
$options = json_decode( stripslashes( $options ), true );
$arr = array();
if ( isset( $options['ID'] ) ) {
$arr['ID'] = $options['ID'];
$post_id = $arr['ID'];
if ( isset( $options['post_title'] ) ) {
$arr['post_title'] = $options['post_title'];
}
if ( isset( $options['post_name'] ) ) {
$arr['post_name'] = $options['post_name'];
}
if ( isset( $options['post_status'] ) ) {
$arr['post_status'] = $options['post_status'];
}
wp_update_post( $arr );
if ( isset( $options['blocks'] ) ) {
update_post_meta( $post_id, 'kirki', $options['blocks'] );
}
if ( isset( $options['styleBlocks'] ) ) {
update_post_meta( $post_id, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', $options['styleBlocks'] );
}
if ( isset( $options['usedFonts'] ) ) {
update_post_meta( $post_id, KIRKI_META_NAME_FOR_USED_FONT_LIST, $options['usedFonts'] );
}
if ( isset( $options['conditions'] ) ) {
update_post_meta( $post_id,'kirki_template_conditions', $options['conditions'] );
}
if ( isset( $options['variableMode'] ) ) {
update_post_meta( $post_id, 'kirki_variable_mode', $options['variableMode'] );
}
if ( isset( $options['post_name'] ) ) {
flush_rewrite_rules( true );
}
wp_send_json( ( new self() )->format_single_post( $post_id ) );
die();
} else {
wp_send_json( array( 'status' => 'Page data update failed' ) );
die();
}
}
/**
* Duplicate page data
*
* @return void wp_send_json.
*/
public static function duplicate_page() {
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$post_id = (int) HelperFunctions::sanitize_text( isset( $_POST['id'] ) ? $_POST['id'] : '' );
$post = get_post( $post_id );
$new_post_id = wp_insert_post(
array(
'post_title' => $post->post_title . ' (copy)',
'post_content' => $post->post_content,
'post_name' => $post->post_name,
'post_type' => $post->post_type,
'post_status' => $post->post_status,
)
);
$page_data = get_post_meta( $post_id, 'kirki', true );
if ( $page_data ) {
update_post_meta( $new_post_id, 'kirki', $page_data );
update_post_meta( $new_post_id, KIRKI_META_NAME_FOR_POST_EDITOR_MODE, 'kirki' );
}
/**
* Also duplicate _wp_page_template meta if exists
*/
$page_template = get_post_meta( $post_id, '_wp_page_template', true );
if ( $page_template ) {
$page_template = HelperFunctions::normalize_kirki_full_canvas_template_path($page_template);
update_post_meta( $new_post_id, '_wp_page_template', $page_template );
}
/**
* Also duplicate this page style blocks if exists
*/
$post_styles = get_post_meta( $post_id, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', true );
if ( $post_styles ) {
update_post_meta( $new_post_id, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', $post_styles );
}
$used_fonts = get_post_meta( $post_id, KIRKI_META_NAME_FOR_USED_FONT_LIST, true );
if ( $used_fonts ) {
update_post_meta( $new_post_id, KIRKI_META_NAME_FOR_USED_FONT_LIST, $used_fonts );
}
flush_rewrite_rules( true );
wp_send_json( ( new self() )->format_single_post( $new_post_id ) );
}
/**
* Back to kirki editor
*
* @return void wp_send_json.
*/
public static function back_to_kirki_editor() {
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$post_id = (int) HelperFunctions::sanitize_text( isset( $_POST['postId'] ) ? $_POST['postId'] : '' );
$post = get_post( $post_id );
if ( $post->post_status === 'auto-draft' ) {
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$post_title = HelperFunctions::sanitize_text( isset( $_POST['title'] ) ? $_POST['title'] : null );
if ( ! isset( $post_title ) ) {
$post_title = 'Untitled';
}
$data = array(
'ID' => $post_id,
'post_title' => $post_title,
'post_name' => $post_title,
'post_status' => 'draft',
);
wp_update_post( $data );
}
update_post_meta( $post_id, '_wp_page_template', HelperFunctions::get_kirki_full_canvas_template_path() );
wp_send_json( array( 'status' => true ) );
}
/**
* Back to WordPress editor
*
* @return void wp_send_json.
*/
public static function back_to_wordpress_editor() {
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$post_id = (int) HelperFunctions::sanitize_text( isset( $_POST['postId'] ) ? $_POST['postId'] : '' );
delete_post_meta( $post_id, KIRKI_META_NAME_FOR_POST_EDITOR_MODE );
wp_send_json( array( 'status' => true ) );
}
/**
* This function is called from EDITOR panel
*
* @return void wp_send_json.
*/
public static function get_page_blocks_and_styles() {
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$post_id = (int) HelperFunctions::sanitize_text( isset( $_GET['id'] ) ? $_GET['id'] : '' );
$stage_version = HelperFunctions::sanitize_text( isset( $_GET['stage_version'] ) ? intval( $_GET['stage_version'] ) : false );
if ( ! $stage_version ) {
$stage_version = Staging::get_most_recent_stage_version( $post_id, false );
}
if ( ! empty( $post_id ) ) {
$post_meta = get_post_meta( $post_id, 'kirki', true );
if ( ! $post_meta ) {
$post_meta = array();
$post_meta['blocks'] = null;
}
if ( $stage_version ) {
$meta_name = Staging::get_staged_meta_name( 'kirki', $post_id, $stage_version );
$staging_post_meta = get_post_meta( $post_id, $meta_name, true );
if ( $staging_post_meta ) {
$post_meta = $staging_post_meta;
}
}
$styles = HelperFunctions::get_page_styleblocks( $post_id, $stage_version );
$post_meta['styles'] = $styles;
$post_meta['preview_url'] = HelperFunctions::get_post_url_arr_from_post_id( $post_id, array( 'preview_url' => true ) )['preview_url'];
$post_meta['is_kirki_editor_mode'] = HelperFunctions::is_editor_mode_is_kirki( $post_id );
$content = get_the_content( null, false, $post_id );
$post_meta['content_length'] = strlen( $content );
wp_send_json( $post_meta );
}
die();
}
public static function get_page_html() {
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$post_id = (int) HelperFunctions::sanitize_text( isset( $_GET['id'] ) ? $_GET['id'] : '' );
if ( ! empty( $post_id ) ) {
$post_meta = get_post_meta( $post_id, 'kirki', true );
if ( ! $post_meta ) {
$post_meta = array();
$post_meta['blocks'] = null;
}
$params = array(
'blocks' => $post_meta['blocks'],
'style_blocks' => null,
'root' => 'root',
'post_id' => false,
'options' => array( 'check_access' => false ),
'get_style' => false,
'get_variable' => false,
'should_take_app_script' => false,
);
$html = HelperFunctions::get_html_using_preview_script( $params );
wp_send_json( $html );
}
die();
}
/**
* Format single post data
*
* @param int $post_id post id.
* @return object|null post with custom data.
*/
public function format_single_post( $post_id ) {
$post = get_post( $post_id );
if ( $post ) {
$page = array();
if ('kirki_popup' === $post->post_type ) {
$page['blocks'] = get_post_meta( $post->ID, 'kirki', true );
$page['styleBlocks'] = get_post_meta( $post->ID, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', true );
$page['usedFonts'] = get_post_meta( $post->ID, KIRKI_META_NAME_FOR_USED_FONT_LIST, true );
}
if ('kirki_template' === $post->post_type ) {
$conditions = get_post_meta( $post->ID,'kirki_template_conditions', true );
$page['conditions'] = $conditions ? $conditions : array();
$collection_type = get_post_meta( $post->ID,'kirki_template_collection_type', true );
$page['collection_type'] = $collection_type ? $collection_type : '';
}
if ('kirki_utility' === $post->post_type ) {
$utility_type_page = get_post_meta( $post->ID,'kirki_utility_page_type', true );
$page['utility_page_type'] = $utility_type_page ? $utility_type_page : '';
}
$temp_urls = HelperFunctions::get_post_url_arr_from_post_id(
$post->ID,
array(
'preview_url' => true,
'editor_url' => true,
)
);
$page['preview_url'] = $temp_urls['preview_url'];
$page['editor_url'] = $temp_urls['editor_url'];
$page['id'] = $post->ID;
$page['title'] = $post->post_title;
$page['status'] = $post->post_status;
$page['post_type'] = $post->post_type;
$page['post_parent'] = $post->post_parent;
$page['slug'] = $post->post_name;
$page['variableMode'] = self::get_variable_mode( $post->ID );
$page['isFrontPage'] = get_option( 'page_on_front' ) == $post->ID ? true : false;
$disabled_page_symbols = get_post_meta( $post_id, KIRKI_META_NAME_FOR_PAGE_HF_SYMBOL_DISABLE_STATUS, true );
if ( ! isset( $disabled_page_symbols ) || ! is_array( $disabled_page_symbols ) ) {
$disabled_page_symbols = array();
}
$page['disabled_page_symbols'] = $disabled_page_symbols;
$page = self::add_published_staged_info( $page );
return $page;
}
return null;
}
public static function add_published_staged_info( $page ){
$staged_info = Staging::get_published_stage_version_info( $page['id'] );
$page['staged_last_updated'] = isset($staged_info['last_updated']) ? $staged_info['last_updated'] : null;
return $page;
}
public static function get_variable_mode( $post_id ) {
$variable_mode = get_post_meta( $post_id, 'kirki_variable_mode', true );
return $variable_mode ? $variable_mode : 'inherit';
}
/**
* Fetch page list
*
* @return void wp_send_json.
*/
public static function fetch_list_api() {
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$post_types = HelperFunctions::sanitize_text( isset( $_GET['post_types'] ) ? $_GET['post_types'] : '[]' );
$post_types = json_decode( $post_types, true );
$exclude_post_ids = json_decode( HelperFunctions::sanitize_text( isset( $_GET['exclude_post_ids'] ) ? $_GET['exclude_post_ids'] : '[]' ), true );
$query = HelperFunctions::sanitize_text( isset( $_GET['query'] ) ? $_GET['query'] : null );
$numberposts = HelperFunctions::sanitize_text( isset( $_GET['numberposts'] ) ? $_GET['numberposts'] : 20 );
$page_list = array();
if ( HelperFunctions::user_has_post_edit_access() ) {
$page_list = static::fetch_list( $post_types, true, array( 'publish', 'draft' ), $query, $numberposts, 1, $exclude_post_ids );
}
wp_send_json( $page_list );
}
public static function get_pages_for_pages_panel() {
// Sanitize and validate inputs
$query = HelperFunctions::sanitize_text( isset( $_GET['query'] ) ? $_GET['query'] : null );
$page = HelperFunctions::sanitize_text( isset( $_GET['page'] ) ? $_GET['page'] : 1 );
$numberposts = intval( HelperFunctions::sanitize_text( isset( $_GET['numberposts'] ) ? $_GET['numberposts'] : 20 ) );
$post_types = HelperFunctions::sanitize_text( isset( $_GET['post_types'] ) ? $_GET['post_types'] : '[]' );
$post_types = json_decode( $post_types, true );
// Set a default post type if not provided
if ( empty( $post_types ) ) {
$post_types = array( 'page' ); // Default to pages if no post types are provided
}
$page_list = array();
$page_list = static::fetch_list( $post_types, true, array( 'publish', 'draft' ), $query, $numberposts, $page );
// if ( HelperFunctions::user_has_page_edit_access() ) {
// }
// Get total posts count
$total_arg = array(
'post_type' => $post_types,
'post_status' => array( 'publish', 'draft' ),
'posts_per_page' => -1,
'fields' => 'ids',
);
if ( $query ) {
$total_arg['s'] = $query;
}
$total_posts = count(get_posts($total_arg));
// Return the data as a JSON response
wp_send_json_success( array(
'pages' => $page_list,
'total' => $total_posts,
) );
}
/**
* Fetch post list for search
*
* @return void wp_send_json.
*/
public static function get_data_list_for_template_edit_search_flyout() {
$query = HelperFunctions::sanitize_text( isset( $_GET['query'] ) ? $_GET['query'] : '' );
$conditions = HelperFunctions::sanitize_text( isset( $_GET['conditions'] ) ? $_GET['conditions'] : array() );
$conditions = json_decode( $conditions, true );
$data = HelperFunctions::get_collection_items_from_conditions( $conditions, $query );
wp_send_json( $data['data'] );
}
/**
* Get all post types and found the all post types that are not discarded post types
*
* @return void wp_send_json
*/
public static function fetch_post_list_data_post_type_wise() {
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$search_query = HelperFunctions::sanitize_text( isset( $_GET['search'] ) ? $_GET['search'] : '' );
$post_types = get_post_types();
$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' );
$post_types['kirki_template'] = 'kirki_template';
$post_types['kirki_utility'] = 'kirki_utility';
$post_types['kirki_popup'] = 'kirki_popup';
$post_types = array_diff_key( $post_types, array_flip( $discarded_post_types ) );
$args = array(
'post_type' => $post_types,
's' => $search_query,
'posts_per_page' => -1,
'post_status' => 'any',
);
$all_posts = get_posts( $args );
$data = array();
// Post types to be grouped under "page"
$group_under_page = array( 'kirki_template', 'kirki_utility', 'kirki_page' );
foreach ( $all_posts as $p ) {
$single_post = array(
'id' => $p->ID,
'title' => $p->post_title,
'editor_url' => HelperFunctions::get_post_url_arr_from_post_id( $p->ID, array( 'editor_url' => true ) )['editor_url'],
);
// Normalize post_type
$type_key = in_array( $p->post_type, $group_under_page, true ) ? 'page' : $p->post_type;
$data[ $type_key ][] = $single_post;
}
wp_send_json( $data );
}
/**
* Fetch page list
* if $internal is true then it will return array
* otherwise it will return json for api call
*
* @param string $type post type.
* @param boolean $internal if this method call from internal response.
* @param string $post_status post status.
*
* @return void|array
*/
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() ) {
$pages = array();
$arg = array(
'post_type' => $type,
'post_status' => $post_status,
// 'numberposts' => $numberposts,
'orderby' => 'ID',
'order' => 'DESC',
'posts_per_page' => $numberposts,
'paged' => $current_page,
'post__not_in' => $exclude_post_ids,
);
if ( $query ) {
$arg['s'] = $query;
}
$posts = get_posts( $arg );
if ( ! empty( $posts ) ) {
foreach ( $posts as $post ) {
/**
* If page template type is kirki full page then check if GET['type'] is set to kirki_page otherwise send any page type data
*/
$pages[] = ( new self() )->format_single_post( $post->ID );
}
}
// $pages items has isFrontPage true then add it to first position of array also do not duplicate same item
$frontPage = null;
foreach ($pages as $key => $page) {
if ($page['isFrontPage']) {
$frontPage = $page;
unset($pages[$key]); // remove original to avoid duplication
break;
}
}
if ($frontPage) {
array_unshift($pages, $frontPage); // add to first position
}
$pages = array_values($pages); // reindex array
if ( $internal ) {
return $pages;
}
wp_send_json( $pages );
}
/**
* Get current page data
*
* @return void wp_send_json.
*/
public static function get_current_page_data() {
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$post_id = (int) HelperFunctions::sanitize_text( isset( $_GET['id'] ) ? $_GET['id'] : '' );
$post_formatted = null;
if ( $post_id ) {
$post_formatted = ( new self() )->format_single_post( $post_id );
}
wp_send_json( $post_formatted );
}
/**
* Remove all unused style blocks from option meta
* it will collect all posts unused style block id
* then it will remove all unused style blocks from option meta
*
* @return void wp_send_json.
*/
public static function remove_unused_style_block_from_db() {
$post_id = (int) HelperFunctions::sanitize_text( $_POST['post_id'] ?? '' );
if ( ! $post_id || ! get_post( $post_id ) ) {
wp_send_json_error( array( 'message' => 'Invalid post ID.' ) );
}
$all_post_ids = self::get_all_post_ids();
$all_used_style_ids = array_flip( self::get_all_used_style_ids() ); // faster lookup
// Helper to clean any style array
$clean_styles = function ( array $styles ) use ( $all_used_style_ids ) {
$changed = false;
foreach ( $styles as $key => $style ) {
if ( ! isset( $all_used_style_ids[ $key ] ) && empty( $style['isDefault'] ) ) {
unset( $styles[ $key ] );
$changed = true;
}
}
return array( $styles, $changed );
};
// Clean global styles.
$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();
$result = (array) $clean_styles( $all_global_styles );
$all_global_styles = $result[0] ?? array();
$changed = $result[1] ?? false;
if ( $changed ) {
HelperFunctions::save_global_style_blocks( $all_global_styles );
}
// Clean post styles
foreach ( $all_post_ids as $p_id ) {
// Random styles
$post_styles = get_post_meta( $p_id, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', true ) ?: array();
$temp_result = (array) $clean_styles( $post_styles );
$post_styles = $temp_result[0] ?? array();
$changed = $temp_result[1] ?? false; // $changed
if ( $changed ) {
HelperFunctions::save_random_style_blocks( $p_id, $post_styles );
}
// Staged styles
$most_recent_stage_id = Staging::get_most_recent_unpublished_stage_id( $p_id );
if ( $most_recent_stage_id ) {
foreach ( array(
KIRKI_GLOBAL_STYLE_BLOCK_META_KEY,
KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random',
) as $meta_key_base ) {
$meta_key = Staging::get_staged_meta_name( $meta_key_base, $p_id, $most_recent_stage_id );
$staged_styles = get_post_meta( $p_id, $meta_key, true ) ? get_post_meta( $p_id, $meta_key, true ) : array();
$temp_styles = $clean_styles( $staged_styles );
$staged_styles = $temp_styles[0] ?? array();
$changed = $temp_styles[1] ?? false;
if ( $changed ) {
HelperFunctions::save_staged_style_blocks( $p_id, $meta_key, $staged_styles );
}
}
}
}
wp_send_json(
array(
'status' => 'success',
'data' => HelperFunctions::get_page_styleblocks( $post_id ),
)
);
}
/**
* Get unused class info from db
*
* @param boolean $internal if this method call from internally.
* @return void|array wp_send_json.
*/
public static function get_unused_class_info_from_db( $internal = false ) {
$all_post_ids = self::get_all_post_ids();
$all_used_style_ids = self::get_all_used_style_ids();
// Add global style IDs
$all_style_ids = array();
// Add global style IDs exclude default
$global_styles = HelperFunctions::get_global_data_using_key( KIRKI_GLOBAL_STYLE_BLOCK_META_KEY ) ?: array();
foreach ( $global_styles as $key => $style ) {
if ( empty( $style['isDefault'] ) ) {
$all_style_ids[] = $key;
}
}
// Add all post style IDs excluding default
foreach ( $all_post_ids as $p_id ) {
$post_styles = get_post_meta( $p_id, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', true ) ?: array();
foreach ( $post_styles as $key => $style ) {
if ( empty( $style['isDefault'] ) ) {
$all_style_ids[] = $key;
}
}
}
$all_style_ids = array_unique( $all_style_ids );
// Filter out any IDs that are used anywhere
$common_unused = array_values(
array_filter(
$all_style_ids,
function ( $id ) use ( $all_used_style_ids ) {
return ! in_array( $id, $all_used_style_ids, true );
}
)
);
if ( $internal ) {
return $common_unused;
}
wp_send_json(
array(
'status' => 'success',
'data' => $common_unused,
)
);
}
/**
* Collect all post IDs (including draft, published)
*
* @return array
*/
private static function get_all_post_ids() {
global $wpdb;
$results = $wpdb->get_col(
$wpdb->prepare(
"SELECT DISTINCT pm.post_id
FROM {$wpdb->postmeta} AS pm
INNER JOIN {$wpdb->posts} AS p ON p.ID = pm.post_id
WHERE pm.meta_key = %s
AND p.post_type NOT IN (%s, %s)",
'kirki',
'kirki_symbol',
'kirki_popup'
)
);
return $results;
}
/**
* Collect all used style IDs across published + most recent staged version.
*
* @return array
*/
private static function get_all_used_style_ids() {
$all_post_ids = self::get_all_post_ids();
$all_used_style_ids = array();
foreach ( $all_post_ids as $p_id ) {
// Published
$published_used_ids = get_post_meta( $p_id, KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS, true ) ?: array();
$published_used_ids_random = get_post_meta( $p_id, KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS . '_random', true ) ?: array();
$published_used_ids = array_unique( array_merge( $published_used_ids, $published_used_ids_random ) );
// Most recent staged
$most_recent_stage_id = Staging::get_most_recent_unpublished_stage_id( $p_id );
$staged_used_ids = array();
if ( $most_recent_stage_id ) {
$staged_used_keys = array(
Staging::get_staged_meta_name( KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS, $p_id, $most_recent_stage_id ),
Staging::get_staged_meta_name( KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS . '_random', $p_id, $most_recent_stage_id ),
);
foreach ( $staged_used_keys as $key ) {
$staged_used_ids = array_merge( $staged_used_ids, get_post_meta( $p_id, $key, true ) ?: array() );
}
}
$all_used_style_ids = array_merge( $all_used_style_ids, $published_used_ids, $staged_used_ids );
}
return array_unique( $all_used_style_ids );
}
public static function validate_wp_post_slug() {
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$post_id = (int) HelperFunctions::sanitize_text( isset( $_GET['post_id'] ) ? $_GET['post_id'] : '' );
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$post_type = HelperFunctions::sanitize_text( isset( $_GET['post_type'] ) ? $_GET['post_type'] : '' );
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$post_name = HelperFunctions::sanitize_text( isset( $_GET['post_name'] ) ? $_GET['post_name'] : '' );
wp_send_json(
array(
'status' => 'success',
'data' => HelperFunctions::validate_slug( $post_id, $post_type, $post_name ),
)
);
}
public static function get_editor_read_only_access_data() {
wp_send_json(
array(
'status' => 'success',
'data' => self::format_editor_access_data(),
)
);
}
private static function format_editor_access_data() {
$status = HelperFunctions::get_global_data_using_key( 'kirki_editor_read_only_access_status' );
$arr = array(
'status' => $status ? $status : false,
'url' => self::get_post_read_only_access_url(),
);
return $arr;
}
public static function save_editor_read_only_access_data() {
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$data = isset( $_POST['data'] ) ? $_POST['data'] : null;
$data = json_decode( stripslashes( $data ), true );
if ( $data['type'] === 'status' ) {
HelperFunctions::update_global_data_using_key( 'kirki_editor_read_only_access_status', HelperFunctions::sanitize_text( $data['status'] ) );
}
if ( $data['type'] === 'regenerate' ) {
self::generate_read_only_access_token();
}
wp_send_json(
array(
'status' => 'success',
'data' => self::format_editor_access_data(),
)
);
}
private static function get_post_read_only_access_url() {
$token = HelperFunctions::get_global_data_using_key( 'kirki_editor_read_only_access_token' );
if ( ! $token ) {
$token = self::generate_read_only_access_token();
}
// Try to get the home page ID first
$home_page_id = get_option( 'page_on_front' ); // Retrieves the ID of the homepage if set
if ( $home_page_id ) {
$home_page_url_arr = HelperFunctions::get_post_url_arr_from_post_id( $home_page_id, array( 'editor_url' => true ) );
return esc_url( $home_page_url_arr['editor_url'] ) . '&editor-preview-token=' . $token;
}
// If no homepage is set, fallback to the last edited kirki editor page
$last_edited_kirki_editor_page = HelperFunctions::get_last_edited_kirki_editor_type_page();
if ( $last_edited_kirki_editor_page ) {
$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 ) );
return esc_url( $last_edited_kirki_editor_page_url_arr['editor_url'] ) . '&editor-preview-token=' . $token;
}
// If neither the home page nor the last edited page is found, default to home URL
return home_url( '?action=kirki&editor-preview-token=' . $token );
}
private static function generate_read_only_access_token() {
$token = wp_generate_password( 32, false, false ); // Generate a secure random token
HelperFunctions::update_global_data_using_key( 'kirki_editor_read_only_access_token', $token );
return $token;
}
/**
* Get all global used style block ids
* first get all posts used global style ids
* then merge and returns.
*
* @return array style ids.
*/
private static function get_all_global_used_style_block_ids() {
global $wpdb;
//phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.DirectQuery
$used_global_ids = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}postmeta WHERE meta_key = '" . KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS . "'", OBJECT );
$all_used_block_ids = array();
foreach ( $used_global_ids as $key => $p_meta ) {
$this_used_global = get_post_meta( $p_meta->post_id, $p_meta->meta_key, true );
$all_used_block_ids = array_merge( $all_used_block_ids, $this_used_global );
}
$all_used_block_ids_global = array_unique( $all_used_block_ids );
return $all_used_block_ids_global;
}
public static function get_all_data_by_kirki_meta_key() {
global $wpdb;
//phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.DirectQuery
// $all_page_meta_data = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}postmeta WHERE meta_key = 'kirki'", ARRAY_A );
$all_page_meta_data = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}postmeta WHERE meta_key = 'kirki' ORDER BY meta_id DESC", ARRAY_A );
return $all_page_meta_data;
}
/**
* Get all global unused style block ids
* first get all posts used global style ids using get_all_global_used_style_block_ids()
* then collect and return.
*
* @return array style ids.
*/
private static function get_unused_global_style_ids() {
$all_used_ids = self::get_all_global_used_style_block_ids();
$styles = HelperFunctions::get_global_data_using_key( KIRKI_GLOBAL_STYLE_BLOCK_META_KEY );
$unused_keys = array();
foreach ( $styles as $key => $sb ) {
// we will also remove default style block too. if it is not used in any post. and added latest style block from front end.
if ( ( true || ( ( isset( $sb['isDefault'] ) && ! $sb['isDefault'] ) || ! isset( $sb['isDefault'] ) ) ) && ! in_array( $key, $all_used_ids, true ) ) {
$unused_keys[] = $key;
}
}
return $unused_keys;
}
/**
* Get all post unused style block ids
* first get all posts used post style ids using get_unused_post_style_ids()
* then collect and return.
*
* @param int $post_id wp post id.
* @return array style ids.
*/
private static function get_unused_post_style_ids( $post_id ) {
$all_used_ids = get_post_meta( $post_id, KIRKI_META_NAME_FOR_USED_STYLE_BLOCK_IDS . '_random', true );
$styles = get_post_meta( $post_id, KIRKI_GLOBAL_STYLE_BLOCK_META_KEY . '_random', true );
if ( ! $styles ) {
return array();
}
$unused_keys = array();
foreach ( $styles as $key => $sb ) {
if ( ! $all_used_ids || ! in_array( $key, $all_used_ids, true ) ) {
$unused_keys[] = $key;
}
}
return $unused_keys;
}
public static function toggle_disabled_page_symbols() {
//phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$post_id = (int) HelperFunctions::sanitize_text( isset( $_POST['post_id'] ) ? $_POST['post_id'] : get_the_ID() );
$symbol_type = HelperFunctions::sanitize_text( isset( $_POST['symbol_type'] ) ? $_POST['symbol_type'] : null );
$disable = HelperFunctions::sanitize_text( isset( $_POST['disable'] ) ? $_POST['disable'] : null );
if ( $post_id && $symbol_type && $disable ) {
$prev_status = get_post_meta( $post_id, KIRKI_META_NAME_FOR_PAGE_HF_SYMBOL_DISABLE_STATUS, true );
if ( ! isset( $prev_status ) || ! is_array( $prev_status ) ) {
$prev_status = array();
}
$disable = filter_var( $disable, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ) ?? false;
$current_status = array_merge( $prev_status, array( $symbol_type => $disable ) );
update_post_meta( $post_id, KIRKI_META_NAME_FOR_PAGE_HF_SYMBOL_DISABLE_STATUS, $current_status );
wp_send_json( array( 'status' => 'Page data saved.' ) );
}
wp_send_json( array( 'status' => 'Page data save failed!' ) );
}
}