: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* importing/erasing contents of the theme
defined('ABSPATH') || exit;
class Themify_Import_Helper {
const DEMO_KEY = 'tf_demo';
public static function init() {
add_action('wp_ajax_themify_import_terms', array(__CLASS__, 'import_ajax_terms'));
add_action('wp_ajax_themify_import_posts', array(__CLASS__, 'import_ajax_posts'));
add_action('wp_ajax_themify_import_theme_data', array(__CLASS__, 'import_ajax_theme_data'));
add_action('wp_ajax_themify_upload_image', array(__CLASS__, 'import_ajax_image'));
add_action('wp_ajax_themify_import_gallery', array(__CLASS__, 'import_ajax_post_gallery'));
add_action('wp_ajax_themify_erase_content', array(__CLASS__, 'erase_demo'));
public static function import_ajax_posts() {
check_ajax_referer('tf_nonce', 'nonce');
if (current_user_can('import')) {
if (isset($_POST['data'])) {
$posts = stripslashes_deep($_POST['data']);
} elseif (isset($_FILES['data'])) {
$posts = file_get_contents($_FILES['data']['tmp_name']);
self::raise_memory_limit();
$posts = json_decode($posts, true);
$skinId = !empty($_POST['id']) ? $_POST['id'] : 'default';
foreach ($posts as $post) {
$id = self::import_post($post, $skinId);
if (is_numeric($id) && $post['post_type'] !== 'tbp_template') {
self::set_import_id($post['ID'], $id, 'post', $skinId);
wp_send_json_success($ids);
public static function import_ajax_terms() {
check_ajax_referer('tf_nonce', 'nonce');
if (current_user_can('import')) {
if (isset($_POST['data'])) {
$terms = stripslashes_deep($_POST['data']);
} elseif (isset($_FILES['data'])) {
$terms = file_get_contents($_FILES['data']['tmp_name']);
self::raise_memory_limit();
$terms = json_decode($terms, true);
$skinId = !empty($_POST['id']) ? $_POST['id'] : 'default';
foreach ($terms as $term) {
$id = self::import_term($term);
self::set_import_id($term['term_id'], $id, 'taxonomy', $skinId);
$ids[$term['term_id']] = $id;
wp_send_json_success($ids);
public static function import_ajax_theme_data() {
check_ajax_referer('tf_nonce', 'nonce');
if (current_user_can('manage_options')) {
if (isset($_POST['data'])) {
$settings = stripslashes_deep($_POST['data']);
} elseif (isset($_FILES['data'])) {
$settings = file_get_contents($_FILES['data']['tmp_name']);
self::raise_memory_limit();
$settings = json_decode($settings, true);
$skinId = !empty($_POST['id']) ? $_POST['id'] : 'default';
$id = self::import_settings($settings, $skinId);
wp_send_json_success($id);
public static function import_ajax_image() {
if (!empty($_POST['postData']) && current_user_can('import')) {
check_ajax_referer('tf_nonce', 'nonce');
$postData = json_decode(stripslashes_deep($_POST['postData']), true);
self::raise_memory_limit('image');
$skinId = !empty($_POST['save_id']) ? $_POST['save_id'] : '';
$webp = empty($_POST['stop_webp']) ? true : false;
foreach ($postData as $key => $arrPost) {
if (!empty($arrPost['thumb'])) {
$blob = !empty($_FILES[$key]) && $_FILES[$key] != '1' ? $_FILES[$key] : null;
$res = self::import_media($arrPost, $blob, $webp);
if ($skinId !== '' && is_array($res) && isset($res['id'])) {
self::set_import_id(null, $res['id'], 'attachment', $skinId);
$response[$arrPost['thumb']] = $res;
wp_send_json_success($response);
public static function import_ajax_post_gallery() {
check_ajax_referer('tf_nonce', 'nonce');
if (current_user_can('import')) {
if (isset($_POST['data'])) {
$data = stripslashes_deep($_POST['data']);
} elseif (isset($_FILES['data'])) {
$data = file_get_contents($_FILES['data']['tmp_name']);
$data = json_decode($data, true);
self::raise_memory_limit();
foreach ($data as $post_id => $gallery) {
self::import_post_gallery($post_id, $gallery);
protected static function set_time_limit(int $limit = 0) {
if (function_exists('set_time_limit') && false === strpos(ini_get('disable_functions'), 'set_time_limit') && !ini_get('safe_mode')) { // phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.safe_modeDeprecatedRemoved
@set_time_limit($limit); // @codingStandardsIgnoreLine
protected static function raise_memory_limit(string $context = 'admin',string $size = '512MB') {
if (!defined('WP_MAX_MEMORY_LIMIT')) {
define('WP_MAX_MEMORY_LIMIT', $size);
return wp_raise_memory_limit($context);
public static function import_product_attribute($name, $slug) {
if (function_exists('wc_create_attribute') && !empty($name) && !empty($slug) && current_user_can('import')) {
wc_create_attribute(array(
$slug = wc_attribute_taxonomy_name($slug);
register_taxonomy($slug, array('product'), array(
'name' => sprintf(_x('Product %s', 'Product Attribute', 'woocommerce'), $name),
'singular_name' => $name,
protected static function get_term_id_by_slug($slug, $tax, $importId = 0) {
$term = get_term_by('slug', $slug, $tax);
if ($importId > 0 && (!$term || is_wp_error($term))) {
$term = get_term((int) $importId, $tax);
if (!empty($term) && !is_wp_error($term) && $term->taxonomy === $tax) {
return (int) $term->term_id;
* Removes all content marked as demo
public static function erase_demo() {
check_ajax_referer('tf_nonce', 'nonce');
if (!current_user_can('delete_pages')) {
wp_send_json_error(__('You are not allowed to delete pages on this site', 'themify'));
if (isset($_POST['data'])) {
$data = json_decode(stripslashes_deep($_POST['data']), true);
} elseif (isset($_FILES['data'])) {
$data = file_get_contents($_FILES['data']['tmp_name']);
self::raise_memory_limit();
$keepModified = !empty($data['keep_modify']) && $data['keep_modify'] !== '0';
$isWc = themify_is_woocommerce_active();
foreach (array('myaccount', 'shop', 'cart', 'checkout', 'view_order', 'terms') as $wc_page) {
$page_id = wc_get_page_id($wc_page);
$wc_pages[$page_id] = $wc_page;
'meta_key' => '_' . static::DEMO_KEY,
foreach ($terms as $term) {
wp_delete_term($term->term_id, $term->taxonomy);
'post_type' => get_post_types(),
'meta_key' => '_' . static::DEMO_KEY,
foreach ($posts as $post) {
$delete = $keepModified === true ? !(strtotime($post->post_modified) > strtotime($post->post_date)) : true;
if ($post->post_type === 'attachment') {
self::erase_image($post, $keepModified);
} elseif ($isWc === true && $post->post_type === 'product') {
self::erase_product($post->ID, $keepModified);
wp_delete_post($post->ID, true);
if (isset($wc_pages[$post->ID])) {
delete_option('woocommerce_' . $post->post_name . '_page_id');
$items = Themify_Storage::get(static::DEMO_KEY);
$items = json_decode($items, true);
$memory = (int) (wp_convert_hr_to_bytes(WP_MEMORY_LIMIT) * MB_IN_BYTES);
$limit = $memory > 128 ? 100 : ($memory < 64 ? 60 : 80);
foreach ($items as $skin => $el) {
if (!empty($el['taxonomy'])) {
foreach ($el['taxonomy'] as $oldId => $newId) {
$term = get_term($newId);
if (!empty($term) && !is_wp_error($term)) {
$success = current_user_can('delete_term', $newId) ? wp_delete_term($newId, $term->taxonomy) : false;
} elseif ($success === false) {
} elseif (is_wp_error($success) && $success === 0) {
unset($items[$skin]['taxonomy'][$oldId]);
unset($items[$skin]['taxonomy'][$oldId]);
if (!empty($el['post']) && $count < $limit) {
foreach ($el['post'] as $oldId => $newId) {
$post = get_post($newId);
$delete = $keepModified === true ? !(strtotime($post->post_modified) > strtotime($post->post_date)) : true;
$post_type = $post->post_type;
if (($post_type !== 'page' && current_user_can('delete_post', $newId)) || ($post_type === 'page' && current_user_can('delete_page', $newId))) {
if ($post_type === 'attachment') {
$el['attachment'][] = $newId;
if ($isWc === true && $post_type === 'product') {
$deletedItems = self::erase_product($post->ID, $keepModified);
foreach ($deletedItems['posts'] as $product_id => $is_deleted) {
if ($is_deleted === true) {
$product_id = (int) $product_id;
unset($items[$skin]['post'][$product_id]);
if (!empty($deletedItems['attachment'])) {
foreach ($deletedItems['attachment'] as $image_id => $is_deleted) {
if ($is_deleted === true) {
if (isset($items[$skin]['attachment'])) {
$image_id = (int) $image_id;
unset($items[$skin]['attachment'][$image_id], $el['attachment'][$image_id]);
$success = wp_delete_post($post->ID, true);
$delete = !empty($success);
unset($items[$skin]['post'][$oldId]);
if (!empty($post) && isset($wc_pages[$post->ID])) {
delete_option('woocommerce_' . str_replace('-', '', $post->post_name) . '_page_id');
if (!empty($el['attachment']) && $count < $limit) {
foreach ($el['attachment'] as $oldId => $newId) {
$post = get_post($newId);
if (!empty($post) && $post->post_type === 'attachment') {
$delete = $keepModified === true ? !(strtotime($post->post_modified) > strtotime($post->post_date)) : true;
$delete = current_user_can('delete_post', $newId) ? self::erase_image($post, $keepModified) : false;
unset($items[$skin]['attachment'][$oldId]);
if (empty($items[$skin]['taxonomy'])) {
unset($items[$skin]['taxonomy']);
if (empty($items[$skin]['post'])) {
unset($items[$skin]['post']);
if (empty($items[$skin]['attachment'])) {
unset($items[$skin]['attachment']);
if (empty($items[$skin])) {
Themify_Storage::set(static::DEMO_KEY, $items);
Themify_Storage::delete(static::DEMO_KEY);
$response = self::has_demo_content() ? 'hasdemo' : 0;
wp_send_json_success($response);
public static function erase_product($id, $keepModified = false) {
$product = themify_is_woocommerce_active() ? wc_get_product($id) : null;
$res = array('posts' => array());
$isVariable = $product->is_type('variable');
$isGroup = $product->is_type('grouped');
if ($isVariable || $isGroup) {
foreach ($product->get_children() as $child_id) {
$child = wc_get_product($child_id);
$delete = $child->delete(true);
$child->set_parent_id(0);
$delete = $child->save();
$delete = $delete > 0 ? true : false;
$res['posts'][$child_id] = $delete;
$image_galleries_id = $product->get_gallery_image_ids();
if (!empty($image_galleries_id)) {
$res['attachment'] = array();
foreach ($image_galleries_id as $image_id) {
$post = get_post($image_id);
if (!empty($post) && $post->post_type === 'attachment') {
$delete = $keepModified === true ? !(strtotime($post->post_modified) > strtotime($post->post_date)) : true;
$delete = self::erase_image($image_id, $keepModified);
$res['attachment'][$image_id] = $delete;
$res['posts'][$id] = $product->delete(true);
// Delete parent product transients.
if ($parent_id = wp_get_post_parent_id($id)) {
wc_delete_product_transients($parent_id);
$res['posts'][$id] = wp_delete_post($id, true);
public static function erase_image($post, $force = false) {
if (!empty($post) && $post->post_type === 'attachment') {
$delete = $force === true || $post->post_parent === 0 || get_post_status($post->post_parent) === false;
$file_name = wp_basename(wp_get_attachment_url($post->ID));
$path = pathinfo($file_name);
$file_name = esc_sql($path['basename']);
$size_name = esc_sql($path['filename']) . '-';
$sql = "'%$file_name%' OR '%$size_name%'";
unset($path, $file_name, $size_name);
$exist = $wpdb->query("SELECT 1 FROM $wpdb->postmeta WHERE `meta_value` LIKE $sql LIMIT 1");
$exist = $wpdb->query("SELECT 1 FROM $wpdb->posts WHERE `post_content` LIKE $sql LIMIT 1");
$exist = $wpdb->query("SELECT 1 FROM $wpdb->termmeta WHERE `meta_value` LIKE $sql LIMIT 1");
return wp_delete_attachment($post->ID, true);
* Returns true only if there are any demo contents installed on this site
public static function has_demo_content() {
$content = Themify_Storage::get(static::DEMO_KEY);
'meta_key' => '_' . static::DEMO_KEY,
'no_found_rows' => true,]