kollapsminoriteten/wp-content/plugins/blocksy-companion/framework/features/demo-install/install-finish.php

701 lines
16 KiB
PHP

<?php
namespace Blocksy;
if (! defined('ABSPATH')) {
exit;
}
class DemoInstallFinalActions {
protected $is_ajax_request = true;
public function __construct($args = []) {
$args = wp_parse_args($args, [
'is_ajax_request' => true,
]);
$this->is_ajax_request = $args['is_ajax_request'];
}
public function import() {
if (
! current_user_can('edit_theme_options')
&&
$this->is_ajax_request
) {
wp_send_json_error([
'message' => __("Sorry, you don't have permission to finish the installation.", 'blocksy-companion')
]);
}
delete_option('blocksy_ext_demos_currently_installing_demo');
$wpforms_settings = get_option('wpforms_settings', []);
$wpforms_settings['disable-css'] = '2';
update_option('wpforms_settings', $wpforms_settings);
$this->replace_urls();
if (class_exists('\FluentForm\App\Hooks\Handlers\ActivationHandler')) {
$fluentFormActivation = new \FluentForm\App\Hooks\Handlers\ActivationHandler();
$fluentFormActivation->migrate();
}
if (class_exists('WC_REST_System_Status_Tools_V2_Controller')) {
if (! defined('WP_CLI')) {
define('WP_CLI', true);
}
$s = new \WC_REST_System_Status_Tools_V2_Controller();
$s->execute_tool('clear_transients');
if (function_exists('wc_update_product_lookup_tables')) {
wc_update_product_lookup_tables();
}
$s->execute_tool('clear_transients');
}
$this->handle_brizy_posts();
global $wp_rewrite;
$wp_rewrite->flush_rules();
if (get_option('qubely_global_options')) {
$maybe_presets = json_decode(
get_option('qubely_global_options'),
true
);
if (
$maybe_presets
&&
isset($maybe_presets['activePreset'])
&&
$maybe_presets['activePreset'] !== 'theme'
) {
$maybe_presets['activePreset'] = 'theme';
update_option(
'qubely_global_options',
json_encode($maybe_presets)
);
}
}
$this->maybe_activate_elementor_experimental_container();
$this->maybe_recreate_elementor_kit();
$this->update_counts_for_all_terms();
$this->patch_attachment_ids_in_mods();
$this->patch_header_conditions();
$this->patch_nav_menu_locations();
// Clean up duplicate menu items that may have been created during chunked imports
// due to race conditions with concurrent PHP processes
$this->cleanup_duplicate_menu_items();
do_action('customize_save_after');
do_action('blocksy:dynamic-css:refresh-caches');
do_action('blocksy:cache-manager:purge-all');
do_action('blocksy:demo-install:finish');
if ($this->is_ajax_request) {
wp_send_json_success();
}
}
/**
* Replace elementor URLs
*/
public function replace_urls() {
$current_demo = Plugin::instance()->demo->get_current_demo();
if (
! $current_demo
||
! isset($current_demo['demo'])
) {
return;
}
$demo_name = explode(':', $current_demo['demo']);
if (! isset($demo_name[1])) {
$demo_name[1] = '';
}
$demo = $demo_name[0];
$builder = $demo_name[1];
$demo_content = Plugin::instance()->demo->fetch_single_demo([
'demo' => $demo,
'builder' => $builder
]);
if (
! $demo_content
||
! isset($demo_content['url'])
) {
return;
}
$from = $demo_content['url'];
$to = get_site_url();
$from = trim($from);
$to = trim($to);
$from = rtrim($from, '/');
$to = rtrim($to, '/');
$wp_uploads = wp_upload_dir();
if (isset($wp_uploads['baseurl'])) {
$from .= '/wp-content/uploads';
$to = $wp_uploads['baseurl'];
}
if (
! filter_var($from, FILTER_VALIDATE_URL)
||
! filter_var($to, FILTER_VALIDATE_URL)
) {
return;
}
global $wpdb;
// @codingStandardsIgnoreStart cannot use `$wpdb->prepare` because it remove's the backslashes
$wpdb->query(
"UPDATE {$wpdb->postmeta} " .
"SET `meta_value` = REPLACE(`meta_value`, '" . str_replace( '/', '\\\/', $from ) . "', '" . str_replace( '/', '\\\/', $to ) . "') " .
"WHERE `meta_key` = '_elementor_data' AND `meta_value` LIKE '[%' ;"
); // meta_value LIKE '[%' are json formatted
// @codingStandardsIgnoreEnd
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$option_keys = $wpdb->get_results(
$wpdb->prepare(
"SELECT option_name from {$wpdb->options} WHERE `option_value` LIKE %s;",
'%%' . $from . '%%'
)
);
foreach ($option_keys as $single_key) {
update_option($single_key->option_name, json_decode(str_replace(
str_replace('/', '\\/', $from),
str_replace('/', '\\/', $to),
json_encode(get_option($single_key->option_name))
), true));
}
$demo_to_install = Plugin::instance()->demo->get_currently_installing_demo();
$from_menu_link = $demo_content['url'];
$to_menu_link = trailingslashit(get_site_url());
$escaped_from = esc_sql($from_menu_link);
$escaped_to = esc_sql($to_menu_link);
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->query(
$wpdb->prepare(
"UPDATE {$wpdb->postmeta}
SET meta_value = REPLACE(meta_value, %s, %s)
WHERE meta_key = %s
AND meta_value LIKE %s",
$from_menu_link,
$to_menu_link,
'_menu_item_url',
'%' . $wpdb->esc_like($from_menu_link) . '%'
)
);
}
private function handle_brizy_posts() {
if (! is_callable('Brizy_Editor_Storage_Common::instance')) {
return;
}
$post_types = \Brizy_Editor_Storage_Common::instance()->get('post-types');
if (empty($post_types) && ! is_array($post_types)) {
return;
}
$post_ids = $this->get_pages($post_types);
if (empty($post_ids) && ! is_array($post_ids)) {
return;
}
foreach ($post_ids as $post_id) {
$this->import_single_post($post_id);
}
}
public function import_single_post($post_id = 0) {
$is_brizy_post = get_post_meta($post_id, 'brizy_post_uid', true);
if (! $is_brizy_post) {
return;
}
update_post_meta($post_id, 'brizy_enabled', true);
$post = \Brizy_Editor_Post::get((int) $post_id);
$editor_data = $post->get_editor_data();
$post->set_editor_data( $editor_data );
$post->set_editor_version(BRIZY_EDITOR_VERSION);
$post->set_needs_compile(true);
$post->saveStorage();
}
private function get_pages($post_types = array()) {
if (! $post_types) {
return null;
}
$args = array(
'post_type' => $post_types,
// Query performance optimization.
'fields' => 'ids',
'no_found_rows' => true,
'post_status' => 'publish',
'posts_per_page' => -1,
);
$query = new \WP_Query($args);
if (! $query->have_posts()) {
return null;
}
return $query->posts;
}
public function maybe_activate_elementor_experimental_container() {
if (! defined('ELEMENTOR_VERSION')) {
return;
}
$current_demo = Plugin::instance()->demo->get_current_demo();
if (! $current_demo) {
return;
}
if (! isset($current_demo['demo'])) {
return;
}
$demo_name = explode(':', $current_demo['demo']);
if (! isset($demo_name[1])) {
$demo_name[1] = '';
}
$demo = $demo_name[0];
$builder = $demo_name[1];
$demo_content = Plugin::instance()->demo->fetch_single_demo([
'demo' => $demo,
'builder' => $builder
]);
if (! $demo_content) {
return;
}
if ($demo_content['builder'] !== 'elementor') {
return;
}
if (! isset($demo_content['elementor_experiment_container'])) {
return;
}
update_option('elementor_experiment-container', 'active');
}
public function update_counts_for_all_terms() {
if (! blocksy_companion_theme_functions()->blocksy_manager()) {
return;
}
$taxonomies = array_reduce(
blocksy_companion_theme_functions()->blocksy_manager()->post_types->get_supported_post_types(),
function ($result, $item) {
return array_unique(array_merge(
$result,
array_values(array_diff(
get_object_taxonomies($item),
['post_format']
))
));
},
[]
);
foreach ($taxonomies as $taxonomy) {
if (! taxonomy_exists($taxonomy)) {
continue;
}
$terms = get_terms(['taxonomy' => $taxonomy, 'hide_empty' => false]);
$term_taxonomy_ids = wp_list_pluck($terms, 'term_taxonomy_id');
wp_update_term_count($term_taxonomy_ids, $taxonomy);
}
}
public function patch_attachment_ids_in_mods() {
$body = json_decode(file_get_contents('php://input'), true);
if (! $body) {
return;
}
$requestsPayload = [];
if (isset($body['requestsPayload'])) {
$requestsPayload = $body['requestsPayload'];
}
if (! isset($requestsPayload['processed_posts'])) {
return;
}
$all_mods = get_theme_mods();
foreach ($all_mods as $key => $val) {
if ($key === 'header_placements') {
$new_val = $val;
foreach ($val['sections'] as $section_index => $section) {
foreach ($section['items'] as $item_index => $item) {
$new_val['sections'][$section_index][
'items'
][$item_index]['values'] = $this->patch_attachment_ids_in_array(
$item['values'],
$requestsPayload
);
}
if (
! isset($section['settings']['transparent_conditions'])
||
! is_array($section['settings']['transparent_conditions'])
) {
continue;
}
$new_val['sections'][$section_index]['settings']['transparent_conditions'] = $this->patch_transparent_conditions(
$section['settings']['transparent_conditions'],
$requestsPayload['processed_posts']
);
}
set_theme_mod($key, $new_val);
}
if (
$key === 'custom_logo'
&&
is_array($val)
&&
isset($val['desktop'])
) {
$new_val = $val;
$desktop_val = intval($val['desktop']);
if (isset($requestsPayload['processed_posts'][$desktop_val])) {
$new_val['desktop'] = intval($requestsPayload['processed_posts'][$desktop_val]);
}
$tablet_val = intval($val['tablet']);
if (isset($requestsPayload['processed_posts'][$tablet_val])) {
$new_val['tablet'] = intval($requestsPayload['processed_posts'][$tablet_val]);
}
$mobile_val = intval($val['mobile']);
if (isset($requestsPayload['processed_posts'][$mobile_val])) {
$new_val['mobile'] = intval($requestsPayload['processed_posts'][$mobile_val]);
}
set_theme_mod($key, $new_val);
}
if (
$key === 'custom_logo'
&&
is_numeric($val)
&&
isset($requestsPayload['processed_posts'][intval($val)])
) {
set_theme_mod(
$key,
intval($requestsPayload['processed_posts'][intval($val)])
);
}
if (
is_array($val)
&&
isset($val['attachment_id'])
&&
$val['attachment_id']
&&
isset(
$requestsPayload['processed_posts'][
intval($val['attachment_id'])
]
)
) {
$new_val = $val;
$new_val['attachment_id'] = intval($requestsPayload['processed_posts'][
intval($val['attachment_id'])
]);
set_theme_mod($key, $new_val);
}
}
}
public function patch_attachment_ids_in_array($array, $requestsPayload) {
foreach ($array as $key => $val) {
if (
$key === 'custom_logo'
&&
is_array($val)
&&
isset($val['desktop'])
) {
$new_val = $val;
$desktop_val = intval($val['desktop']);
if (isset($requestsPayload['processed_posts'][$desktop_val])) {
$new_val['desktop'] = intval($requestsPayload['processed_posts'][$desktop_val]);
}
$tablet_val = intval($val['tablet']);
if (isset($requestsPayload['processed_posts'][$tablet_val])) {
$new_val['tablet'] = intval($requestsPayload['processed_posts'][$tablet_val]);
}
$mobile_val = intval($val['mobile']);
if (isset($requestsPayload['processed_posts'][$mobile_val])) {
$new_val['mobile'] = intval($requestsPayload['processed_posts'][$mobile_val]);
}
$array[$key] = $new_val;
}
if (
$key === 'custom_logo'
&&
is_numeric($val)
&&
isset($requestsPayload['processed_posts'][intval($val)])
) {
$array[$key] = intval($requestsPayload['processed_posts'][intval($val)]);
}
if (
is_array($val)
&&
isset($val['attachment_id'])
&&
$val['attachment_id']
&&
isset(
$requestsPayload['processed_posts'][
intval($val['attachment_id'])
]
)
) {
$new_val = $val;
$new_val['attachment_id'] = intval($requestsPayload['processed_posts'][
intval($val['attachment_id'])
]);
$array[$key] = $new_val;
}
}
return $array;
}
public function patch_header_conditions() {
$body = json_decode(file_get_contents('php://input'), true);
if (! $body) {
return;
}
$requestsPayload = [];
if (isset($body['requestsPayload'])) {
$requestsPayload = $body['requestsPayload'];
}
if (! isset($requestsPayload['processed_posts'])) {
return;
}
Plugin::instance()->header->patch_conditions(
$requestsPayload['processed_posts']
);
}
public function patch_transparent_conditions($transparent_conditions, $processed_posts) {
$has_relation = isset($transparent_conditions['relation']);
$conditions_list = $has_relation
? $transparent_conditions['conditions']
: $transparent_conditions;
foreach ($conditions_list as $cond_index => $single_condition) {
if (! is_array($single_condition)) {
continue;
}
if (
isset($single_condition['payload']['post_id'])
&&
isset($processed_posts[intval($single_condition['payload']['post_id'])])
) {
$patched_id = intval(
$processed_posts[intval($single_condition['payload']['post_id'])]
);
if ($has_relation) {
$transparent_conditions['conditions'][$cond_index]['payload']['post_id'] = $patched_id;
} else {
$transparent_conditions[$cond_index]['payload']['post_id'] = $patched_id;
}
}
}
return $transparent_conditions;
}
public function patch_nav_menu_locations() {
$body = json_decode(file_get_contents('php://input'), true);
if (! $body) {
return;
}
$requestsPayload = [];
if (isset($body['requestsPayload'])) {
$requestsPayload = $body['requestsPayload'];
}
if (! isset($requestsPayload['processed_terms'])) {
return;
}
$processed_terms = $requestsPayload['processed_terms'];
$old_nav_menu_locations = get_theme_mod('nav_menu_locations', []);
$should_update_nav_menu_locations = false;
foreach ($old_nav_menu_locations as $location => $menu_id) {
if (isset($processed_terms[$menu_id])) {
$should_update_nav_menu_locations = true;
$old_nav_menu_locations[
$location
] = $processed_terms[$menu_id];
}
}
if ($should_update_nav_menu_locations) {
set_theme_mod('nav_menu_locations', $old_nav_menu_locations);
}
}
/**
* Recreate Elementor default kit if it doesn't exist.
*
* After demo import, Elementor may show a warning that the default kit
* is missing. This method creates a new default kit if there isn't one.
*/
public function maybe_recreate_elementor_kit() {
if (! defined('ELEMENTOR_VERSION')) {
return;
}
if (! class_exists('\Elementor\Plugin')) {
return;
}
$kit = \Elementor\Plugin::$instance->kits_manager->get_active_kit();
// If there's already an active kit, do nothing
if ($kit->get_id()) {
return;
}
$created_default_kit = \Elementor\Plugin::$instance->kits_manager->create_default();
if (! $created_default_kit) {
return;
}
update_option(\Elementor\Core\Kits\Manager::OPTION_ACTIVE, $created_default_kit);
}
/**
* Clean up duplicate menu items created during chunked imports.
*
* During chunked imports, race conditions between concurrent PHP processes
* can result in duplicate menu items being created. This has been observed
* on EasyWP (Namecheap) hosting so far. This method finds all menu items
* with the same blocksy_original_post_id and keeps only the one with the
* lowest ID, deleting the rest.
*/
public function cleanup_duplicate_menu_items() {
global $wpdb;
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$duplicates = $wpdb->get_results("
SELECT meta_value as original_id, GROUP_CONCAT(post_id ORDER BY post_id) as post_ids
FROM {$wpdb->postmeta}
WHERE meta_key = 'blocksy_original_post_id'
GROUP BY meta_value
HAVING COUNT(*) > 1
");
if (empty($duplicates)) {
return;
}
foreach ($duplicates as $duplicate) {
$post_ids = explode(',', $duplicate->post_ids);
// Keep the first one (lowest ID), delete the rest
array_shift($post_ids);
foreach ($post_ids as $post_id) {
wp_delete_post((int) $post_id, true);
}
}
}
}