Themler notice: different protocols are used in WordPress Address and Site Address.

' . '

This may cause cross-origin errors in Themler editor. ' . 'Please check your options or follow the article.

' ); } } add_action('init', 'theme_check_site_url'); function theme_get_preview_link($link) { $template = get_template() . '_preview'; $preview_args = has_action('setup_theme', 'preview_theme') ? array('preview' => '1', 'template' => $template, 'stylesheet' => $template, 'preview_iframe' => 1, 'TB_iframe' => 'true') : array('preview' => '1', 'theme' => $template, 'wp_customize' => 'on', 'nonce' => wp_create_nonce("preview-customize_$template"), 'original' => get_template()); return add_query_arg($preview_args, $link); } function theme_add_themler_button($post) { if (!current_user_can('edit_themes')) { return; } $type = $post->post_type; if ($type === 'post' || $type === 'page') { $editor_link = add_query_arg(array( 'start' => urlencode(theme_get_preview_link(get_permalink($post->ID))) ), theme_get_editor_link()); $tip = 'Edit the ' . $type . ' in Themler

Note: If you have other Themler instance opened in a different tab or browser, make sure to have saved and closed it. Otherwise unsaved changes will be lost.'; ?>
  • ' . implode('
  • ', theme_get_permissions_check_folders()) . '
  • ', $e->getExtendedMessage())); } FilesHelper::create_dir($base_template_dir . '/preview'); FilesHelper::rename($preview_template_dir, $path); } add_action('switch_theme', 'theme_deactivation_function'); function theme_print_billion_menu_styles() { ?> $value) { if (in_array('theme_editor', $value)) { unset($submenu['themes.php'][$key]); break; } } } } add_action('admin_menu', 'theme_add_export_option_page'); function theme_editor() { $base_template_dir = get_template_directory(); load_template($base_template_dir . '/export/editor.php'); die(); } add_action('load-appearance_page_theme_editor', 'theme_editor'); if (!function_exists('theme_verify_nonce_and_login_user')) { function theme_verify_nonce_and_login_user() { $uid = isset($_REQUEST['uid']) ? $_REQUEST['uid'] : 0; $nonce = isset($_REQUEST['_ajax_nonce']) ? $_REQUEST['_ajax_nonce'] : $_REQUEST['_wpnonce']; if (false !== wp_verify_nonce($nonce, 'theme_template_export')){ wp_clear_auth_cookie(); wp_set_auth_cookie($uid); wp_set_current_user($uid); return true; } return false; } } function theme_handle_bad_request($error = '') { header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request', true, 400); if (is_wp_error($error)) die($error->get_error_code() . ', ' . $error->get_error_message()); die('400 Bad Request'); } function theme_nopriv_export_wrapper() { if (theme_verify_nonce_and_login_user()){ theme_export_wrapper(); } die('session_error'); } function theme_export_wrapper() { $action = isset( $_REQUEST[ 'action' ] ) ? $_REQUEST[ 'action' ] : null; if (apply_filters('theme_check_ajax_referer', true, $action)) { if (!isset($_REQUEST['uid'])) { // may be post_max_size exceeded theme_handle_bad_request(); } check_ajax_referer('theme_template_export'); } do_action('theme_check_instance_token_' . $action); ProviderLog::start($action); if (null !== $action && is_callable($action)) { $check_folders = theme_get_permissions_check_folders(); theme_check_memory_limit(false); try { foreach ($check_folders as $path) FilesHelper::test_permission($path); $base_upload_dir = wp_upload_dir(); if (false !== $base_upload_dir['error']) throw new Exception('Upload folder error!'); $result = call_user_func($action); if ($result && is_array($result)){ ProviderLog::end($action); $result['log'] = ProviderLog::getLog(); $result['errors'] = ProviderLog::getErrors(); echo json_encode($result); } // TODO else exception } catch(PermissionDeniedException $e) { $errors = ProviderLog::getErrors(); $msg = str_replace('{folders}', '
    1. ' . implode('
    2. ', $check_folders) . '
    ', $e->getExtendedMessage()); if (count($errors) > 0) { $warnings_string = ''; foreach($errors as $error) { $warnings_string .= "\"{$error['message']}\" in {$error['file']} on line {$error['line']} "; } $msg .= ''; print_r($errors); } echo '[permission_denied]' . $msg . '[permission_denied]'; } catch(UnzipException $e) { echo json_encode(array( 'result' => 'error', 'message' => $e->getExtendedMessage() )); } catch(Exception $e) { echo $e->getMessage(); } die; } die('invalid_action'); } function theme_add_export_action($function_name, $check_instance_token = false) { if (is_callable($function_name)) { if ($check_instance_token) { add_action('theme_check_instance_token_' . $function_name, 'theme_check_lockfile'); } add_action('wp_ajax_nopriv_'. $function_name, 'theme_nopriv_export_wrapper', 9); add_action('wp_ajax_' . $function_name, 'theme_export_wrapper', 9); } } function theme_template_clear() { $chunk = new Chunk(); $chunk->clear_chunk_directory(); echo '1'; } theme_add_export_action('theme_template_clear', true); function theme_update_preview() { $base_template_dir = get_template_directory(); $preview_template_dir = FilesHelper::normalize_path($base_template_dir . '_preview'); $helper = new PreviewHelper(); $changed_files = theme_get_preview_changed_files(); ProviderLog::start('Process files'); if ($changed_files === null || !file_exists($preview_template_dir)) { // full copy FilesHelper::empty_dir($preview_template_dir, true); FilesHelper::copy_recursive($base_template_dir, $preview_template_dir, array($helper, "restoreDataId")); FilesHelper::remove_file($preview_template_dir . '/export/project.json'); } else { // copy only changed files foreach($changed_files as $file){ $file_path = $preview_template_dir . $file; if (file_exists($base_template_dir . $file)) { FilesHelper::copy_recursive($base_template_dir . $file, $file_path, array($helper, "restoreDataId")); } else { FilesHelper::remove_file($file_path); } } theme_set_preview_changed_files(array()); } ProviderLog::end('Process files'); FilesHelper::empty_dir($preview_template_dir . '/preview', true); theme_set_name($preview_template_dir . '/style.css', theme_get_preview_theme_name(get_template())); FilesHelper::remove_empty_subfolders($preview_template_dir); if (is_multisite()) { $allowed_themes = get_site_option('allowedthemes'); if (is_array($allowed_themes)) { $allowed_themes[get_stylesheet() . '_preview'] = true; update_site_option('allowedthemes', $allowed_themes); } } return array( 'result' => 'done', 'instanceId' => theme_make_lockfile() ); } theme_add_export_action('theme_update_preview'); // deprecated function theme_get_theme() { echo theme_get_archive_data(); } theme_add_export_action('theme_get_theme'); function theme_get_zip() { $archive_info = theme_get_theme_archive(); header('Content-Type: application/zip'); header("Content-Disposition: attachment; filename=\"{$archive_info['name']}.zip\""); header("Pragma: no-cache"); FilesHelper::readfile($archive_info['path']); FilesHelper::remove_file($archive_info['path']); } theme_add_export_action('theme_get_zip', true); function theme_get_chunk_info() { return array( 'id' => isset($_POST['id']) ? $_POST['id'] : '', 'content' => isset($_POST['content']) ? stripslashes_deep($_POST['content']) : '', 'current' => isset($_POST['current']) ? $_POST['current'] : '', 'total' => isset($_POST['total']) ? $_POST['total'] : '', 'encode' => !empty($_POST['encode']) && $_POST['encode'] === 'true', 'zip' => !empty($_POST['zip']) && $_POST['zip'] === 'true', 'blob' => !empty($_POST['blob']) ); } function theme_template_export() { if (!isset($_POST['info'])) { $info = theme_get_chunk_info(); } else { $info = json_decode(stripslashes_deep($_POST['info']), true); } if (is_null($info)) { error_log(sprintf(admin_url() . ' Invalid info; info: %s; json_last_error: %s', $_POST['info'], json_last_error())); throw new Exception('Invalid info'); } $chunk = new Chunk(); if (is_wp_error($error = $chunk->save($info))) { theme_handle_bad_request($error); } if ($chunk->last()) { // merge and decode content $content = $chunk->complete(); ProviderLog::start('json_decode'); $content = json_decode($content, true); ProviderLog::end('json_decode'); $theme = isset($content['themeFso']) ? $content['themeFso'] : null; $images = isset($content['images']) ? $content['images'] : null; $fonts = isset($content['iconSetFiles']) ? $content['iconSetFiles'] : null; $base_template_dir = get_template_directory(); $template_dir = FilesHelper::normalize_path($base_template_dir . '_preview'); theme_export($theme, $images, $fonts, $base_template_dir, $template_dir); return array('result' => 'done'); } return array('result' => 'processed'); } theme_add_export_action('theme_template_export', true); function theme_set_name($path, $theme_name) { ProviderLog::start('theme_set_name'); if (file_exists($path)) { $content = file_get_contents($path); if (false === $content) throw new PermissionDeniedException($path); if (false === file_put_contents($path, preg_replace('|(Theme Name:) (.*)$|m', '$1 ' . $theme_name, $content))) throw new PermissionDeniedException($path); } ProviderLog::end('theme_set_name'); } function theme_export($theme, $images, $fonts, $base_template_dir, $template_dir) { $dir = $template_dir; $images_dir = $dir . '/images'; $fonts_dir = $dir . '/fonts'; $changed_files = theme_get_preview_changed_files(); if (!is_array($changed_files)) $changed_files = array(); if (!theme_is_converted() && file_exists($template_dir . '/export/converter.data')) { FilesHelper::empty_dir($template_dir, true); $changed_files = array(); } $replace_data = array(); $replace_data = array_merge_recursive($replace_data, (array)process_images($images, $images_dir, $changed_files)); $replace_data = array_merge_recursive($replace_data, (array)process_fonts($fonts, $fonts_dir, $changed_files)); ProviderLog::start('copy_fso_to_fs'); copy_fso_to_fs($theme, $dir, $changed_files, $replace_data); ProviderLog::end('copy_fso_to_fs'); theme_set_name($dir . '/style.css', theme_get_preview_theme_name(get_template())); $changed_files[] = $dir . '/style.css'; theme_set_preview_changed_files($changed_files); } function copy_fso_to_fs($fso, $path, &$changed_files, &$replace_data) { if (is_array($fso) && is_array($fso['items'])) { FilesHelper::create_dir($path); foreach ($fso['items'] as $name => $file) { if (isset($file['content']) && isset($file['type'])) { $to = $path . '/' . $name; $content = $file['type'] == 'text' ? $file['content'] : base64_decode($file['content']); process_file($to, $content, $replace_data); $changed_files[] = $to; } elseif (isset($file['items']) && isset($file['type'])) { copy_fso_to_fs($file, $path . '/' . $name, $changed_files, $replace_data); } } } } function theme_get_image_name($id) { return preg_replace('/[^a-z0-9_\.]/i', '', $id); } function process_images($images, $images_dir, &$changed_files) { ProviderLog::start('process_images'); $result = null; if (isset($images) && is_array($images)) { $ids = array(); $paths = array(); FilesHelper::create_dir($images_dir); foreach ($images as $id => $content) { $image_filename = theme_get_image_name($id); $image_path = $images_dir . '/' . $image_filename; if ($content) { $changed_files[] = $image_path; if ($content === '[DELETED]') { FilesHelper::remove_file($image_path); continue; } if (false === file_put_contents($image_path, base64_decode($content))) throw new PermissionDeniedException($image_path); } $ids[] = 'url(' . $id . ')'; $paths[] = 'url(images/' . $image_filename . ')'; // css path } $result = array('ids' => $ids, 'paths' => $paths); } ProviderLog::end('process_images'); return $result; } function process_fonts($fonts, $fonts_dir, &$changed_files) { ProviderLog::start('process_fonts'); $result = null; if (isset($fonts)) { FilesHelper::create_dir($fonts_dir); foreach ($fonts as $name => $content) { $file_path = $fonts_dir . '/' . $name; if (false === file_put_contents($file_path, base64_decode($content))) throw new PermissionDeniedException($file_path); $changed_files[] = $file_path; } $existing_fonts = scandir($fonts_dir); $ids = array(); $paths = array(); foreach($existing_fonts as $filename) { if ($filename !== '.' && $filename !== '..') { $ids[] = '"' . $filename . '"'; $paths[] = '"' . 'fonts/' . $filename . '"'; } } $result = array('ids' => $ids, 'paths' => $paths); } ProviderLog::end('process_fonts'); return $result; } function process_file($path, $content, &$replace_data) { $info = pathinfo($path); if ($content === '[DELETED]') { FilesHelper::remove_file($path); return; } $file_ext = isset($info['extension']) && $info['extension'] ? $info['extension'] : ''; if ('css' == $file_ext) { $content = str_replace($replace_data['ids'], $replace_data['paths'], $content); } elseif (in_array($file_ext, array('php'))) { foreach ($replace_data['ids'] as $key => $value) { // replace to $to = preg_replace('/url\((.+)\)/', '$1', $replace_data['paths'][$key]); $content = str_replace($value, '', $content); } $content = preg_replace('#src=["\']url\((https?://[^\)]+)\)["\']#', 'src="$1"', $content); } if (false === file_put_contents($path, $content)) throw new PermissionDeniedException($path); } function theme_update_plugins() { CoreUpdateHelper::updateFromTheme(); return array('result' => 'done'); } theme_add_export_action('theme_update_plugins'); function theme_activate_plugins() { CoreUpdateHelper::activatePlugin(); return array('result' => 'done'); } theme_add_export_action('theme_activate_plugins'); function theme_reload_info() { $templates = theme_get_templates(); $info = array( 'templates' => isset($_REQUEST['full_urls']) ? $templates['urls'] : getThemeTemplates(), 'used_template_files' => $templates['used_files'], 'template_types' => $templates['types'], 'page_url' => $templates['page_url'], 'ajax_url' => admin_url('admin-ajax.php'), 'pages_url' => admin_url('edit.php?post_type=page'), 'home_url' => home_url(), 'woocommerce_enabled' => theme_woocommerce_enabled(), 'cms_version' => get_wp_versions(), 'plugin_active' => CoreUpdateHelper::isPluginActive(), 'active_plugins' => theme_get_plugins_info(), ); if (theme_is_converted()) { $info['importer_nonce'] = ''; } echo json_encode(apply_filters('theme_reload_info', $info)); } theme_add_export_action('theme_reload_info'); function theme_save_data(&$project_data, &$images) { $base_template_dir = get_template_directory(); $template_dir = FilesHelper::normalize_path($base_template_dir . '_preview'); $helper = new PreviewHelper(); $changed_files = theme_get_preview_changed_files(); if (!theme_is_converted()) { foreach(FilesHelper::enumerate_files($base_template_dir, false) as $file) { $path = str_replace($base_template_dir, '', $file['path']); if ($path === '/export' || $path === '/content' || $path === '/images') continue; FilesHelper::empty_dir($base_template_dir . $path, true); } } FilesHelper::create_dir($base_template_dir . '/images'); ProviderLog::start('Update images'); if ($images != null) { $existing_images = FilesHelper::enumerate_files($base_template_dir . '/images', false); $image_name = array(); foreach($images as $key => $content) { $image_name[theme_get_image_name($key)] = $key; } foreach($existing_images as $image) { $image_key = str_replace($base_template_dir . '/images/', '', $image['path']); if (isset($image_name[$image_key])) { $image_key = $image_name[$image_key]; } if (!isset($images[$image_key]) && is_file($image['path'])) { $images[$image_key] = '[DELETED]'; } } process_images($images, $template_dir . '/images', $changed_files); $export_plugin_folder = $template_dir . '/export/'; foreach(FilesHelper::enumerate_files($template_dir) as $_file) { $file = $_file['path']; $info = pathinfo($file); $file_ext = isset($info['extension']) && $info['extension'] ? $info['extension'] : ''; if ('php' !== $file_ext) continue; if (substr($file, 0, strlen($export_plugin_folder)) == $export_plugin_folder) continue; $content = file_get_contents($file); $old_content = $content; foreach($images as $key => $value) { $old_path = '/images/' . theme_get_image_name($key); $new_path = ''; $content = str_replace($old_path, $new_path, $content); } if ($old_content !== $content) { file_put_contents($file, $content); $changed_files[] = $file; } } } ProviderLog::end('Update images'); ProviderLog::start('Update files'); foreach($changed_files as $file) { $file = theme_get_preview_relative_path($file); $file_path = $base_template_dir . $file; if (file_exists($template_dir . $file)) { if (preg_match('/^\/images\/([^\/\\\]+)$/', $file)) { FilesHelper::rename($template_dir . $file, $file_path); } else { FilesHelper::copy_recursive($template_dir . $file, $file_path, array($helper, "removeDataId")); } } else { $helper->removeKey($file); FilesHelper::remove_file($file_path); } } ProviderLog::end('Update files'); ProviderLog::start('Clear Images'); if ($images != null) { foreach(FilesHelper::enumerate_files($template_dir . '/images', false) as $preview_image) { FilesHelper::remove_file($preview_image['path']); } } ProviderLog::end('Clear Images'); theme_set_preview_changed_files(array()); $helper->save(); setThemeProjectData($base_template_dir, $project_data); } function theme_reload_themes_info() { $themes = wp_get_themes(); $current_template = get_template() . ''; $themes_info = array(); foreach($themes as $name => $theme) { $project_file = $theme->get_template_directory() . '/export/project.json'; if (file_exists($project_file)) { $template = $theme->get_template() . ''; $screenshot = file_exists($theme->get_template_directory() . '/screenshot400x400.png') ? $theme->get_template_directory_uri() . '/screenshot400x400.png' : $theme->get_screenshot(); $themes_info[$name] = array( 'themeName' => $template, 'thumbnailUrl' => $screenshot, 'openUrl' => theme_get_editor_link($template) . '&ask_import_content=1', 'isActive' => $current_template === $template ); } } echo json_encode(array('themes' => $themes_info)); } theme_add_export_action('theme_reload_themes_info'); function theme_save_project() { if (!isset($_POST['info'])) { $info = theme_get_chunk_info(); } else { $info = json_decode(stripslashes_deep($_POST['info']), true); } if (is_null($info)) { error_log(sprintf(admin_url() . ' Invalid info; info: %s; json_last_error: %s', $_POST['info'], json_last_error())); throw new Exception('Invalid info'); } $chunk = new Chunk(); if (is_wp_error($error = $chunk->save($info))) { theme_handle_bad_request($error); } if ($chunk->last()) { // merge and decode content $content = $chunk->complete(); ProviderLog::start('json_decode'); $content = json_decode($content, true); ProviderLog::end('json_decode'); if (!isset($content['projectData'])) $content['projectData'] = ''; if (!isset($content['thumbnails'])) $content['thumbnails'] = null; if (!isset($content['cssJsSources'])) $content['cssJsSources'] = null; if (!isset($content['md5Hashes'])) $content['md5Hashes'] = null; if (!isset($content['images'])) $content['images'] = null; $project_data = &$content['projectData']; $thumbnails = &$content['thumbnails']; $css_js_sources = &$content['cssJsSources']; $md5_hashes = &$content['md5Hashes']; $images = &$content['images']; $base_template_dir = get_template_directory(); $template_dir = FilesHelper::normalize_path($base_template_dir . '_preview'); if ('' === $project_data) { throw new Exception('projectData is empty'); } theme_save_data($project_data, $images); if (null !== $css_js_sources) { theme_set_cache($base_template_dir, $css_js_sources); } if (null !== $md5_hashes) { theme_set_hashes($base_template_dir, $md5_hashes); } if (null != $thumbnails){ ProviderLog::start('Update thumbnails'); foreach ($thumbnails as $thumbnail) { $filename = $thumbnail['name']; list(, $data) = explode(',', $thumbnail['data']); $data = base64_decode($data); $file_path = $template_dir . '/' . $filename; $base_file_path = $base_template_dir . '/' . $filename; if (false === file_put_contents($base_file_path, $data)) throw new PermissionDeniedException($base_file_path); if (false === file_put_contents($file_path, $data)) throw new PermissionDeniedException($file_path); } ProviderLog::end('Update thumbnails'); } FilesHelper::remove_file($base_template_dir . '/style.min.css'); FilesHelper::remove_file($base_template_dir . '/bootstrap.min.css'); FilesHelper::remove_file($base_template_dir . '/woocommerce/style.min.css'); theme_set_name($base_template_dir . '/style.css', get_template()); FilesHelper::remove_empty_subfolders($base_template_dir); theme_mark_as_converted(); CoreUpdateHelper::updateFromTheme(); return array('result' => 'done'); } return array('result' => 'processed'); } theme_add_export_action('theme_save_project', true); function can_rename($new_template) { if (!theme_is_valid_name($new_template)) { return 'Not valid theme name: ' . $new_template; } $theme_root = get_theme_root(get_template()); $new_template_dir = $theme_root . '/' . $new_template; if (file_exists($new_template_dir)) { return 'You have already such theme: ' . $new_template; } return ''; } function theme_can_rename() { $rename_error = can_rename($_REQUEST['themeName']); return array('result' => 'done', 'message' => $rename_error); } theme_add_export_action('theme_can_rename'); function theme_rename() { global $theme_templates_options; $current_template = get_template(); $template = isset($_REQUEST['themeName']) ? $_REQUEST['themeName'] : $current_template; $template_preview = $template . '_preview'; $theme_root = get_theme_root($template); $template_dir = $theme_root . '/' . $template; $template_preview_dir = ($current_template === $template ? "$theme_root/" : "$template_dir/preview/") . $template_preview; $new_template = preg_replace('|[^a-z0-9_./-]|i', '', $_REQUEST['newName']); $new_template_preview = $new_template . '_preview'; $new_template_dir = $theme_root . '/' . $new_template; $new_template_preview_dir = ($current_template === $template ? "$theme_root/" : "$template_dir/preview/") . $new_template_preview; $rename_error = can_rename($new_template); if ($rename_error) throw new Exception($rename_error); if (!file_exists($template_dir)) throw new Exception("Theme $template does not exists"); if (file_exists($template_preview_dir) && !file_exists($new_template_preview_dir)){ FilesHelper::rename($template_preview_dir, $new_template_preview_dir); theme_set_name($new_template_preview_dir . '/style.css', theme_get_preview_theme_name($new_template)); } FilesHelper::rename($template_dir, $new_template_dir); theme_set_name($new_template_dir . '/style.css', $new_template); theme_rename_option("theme_mods_$template", "theme_mods_$new_template"); foreach($theme_templates_options as $key => $list) { $option = sanitize_title_with_dashes($key); theme_rename_option('theme_template_' . $template . '_' . $option, 'theme_template_' . $new_template . '_' . $option); } if ($template === $current_template) { update_option('template', $new_template); update_option('stylesheet', $new_template); } return array('result' => 'done'); } theme_add_export_action('theme_rename', true); function theme_create_name($theme_name) { $theme = wp_get_theme($theme_name); while ($theme->exists()) { preg_match('#(.*?)(\d{0,4})$#', $theme_name, $m); $theme_name = $m[1]; $suffix = (int)$m[2]; $suffix++; $theme_name .= $suffix; $theme = wp_get_theme($theme_name); } return $theme_name; } function theme_copy() { if (!isset($_REQUEST['id'])) throw new Exception('id is not defined'); $theme_name = $_REQUEST['id']; $theme = wp_get_theme($theme_name); if (!$theme->exists()) throw new Exception("$theme_name does not exists"); $new_theme_name = isset($_REQUEST['newName']) && $_REQUEST['newName'] ? $_REQUEST['newName'] : $theme_name; $new_theme_name = theme_create_name($new_theme_name); $new_theme = wp_get_theme($new_theme_name); $theme_path = $theme->get_template_directory(); $new_theme_path = $new_theme->get_template_directory(); FilesHelper::copy_recursive($theme_path, $new_theme_path); theme_set_name("$new_theme_path/style.css", $new_theme_name); if (get_template() === $theme->get_template()) { FilesHelper::create_dir("$new_theme_path/preview"); FilesHelper::create_dir("$new_theme_path/preview/$new_theme_name"."_preview"); FilesHelper::copy_recursive($theme_path.'_preview', "$new_theme_path/preview/$new_theme_name"."_preview"); } else { FilesHelper::rename_if_exists("$new_theme_path/preview/$theme_name"."_preview", "$new_theme_path/preview/$new_theme_name"."_preview"); } theme_set_name("$new_theme_path/preview/$new_theme_name"."_preview/style.css", theme_get_preview_theme_name($new_theme_name)); return array('result' => 'done'); } theme_add_export_action('theme_copy', true); function theme_activate() { if (!isset($_REQUEST['id'])) { // already active return array('result' => 'done'); } $id = $_REQUEST['id']; $theme = wp_get_theme($id); if (!$theme->exists()) throw new Exception("Theme $id does not exists"); if (get_template() . '' !== $id) switch_theme($id); return array('result' => 'done'); } theme_add_export_action('theme_activate', true); function theme_remove() { if (!isset($_REQUEST['id'])) throw new Exception('id is not defined'); $theme_name = $_REQUEST['id']; $current_name = get_template(); if ($theme_name === $current_name) throw new Exception("$theme_name is active"); $theme = wp_get_theme($theme_name); if (!$theme->exists()) throw new Exception("Theme $theme_name does not exists"); FilesHelper::empty_dir($theme->get_template_directory(), true); return array('result' => 'done'); } theme_add_export_action('theme_remove', true); function theme_get_files() { if (!isset($_POST['mask'])) { return array('error' => 'mask is not defined'); } $mask = $_POST['mask']; $filter = null; if (isset($_POST['filter']) && $_POST['filter'] !== '') { $filter = '#' . stripslashes_deep($_POST['filter']) . '#'; } $template = get_template(); $theme_root = get_theme_root($template); $files = array(); foreach (explode(';', $mask) as $name) { $name = preg_replace('#[\/]+#', '/', $name); if (is_string($filter) && preg_match($filter, $name)) { continue; } $path = "$theme_root/$template$name"; if (file_exists($path)) { $files[$name] = file_get_contents($path); if (false === $files[$name]) throw new PermissionDeniedException($path); } } return $files; } theme_add_export_action('theme_get_files'); function theme_get_manifest() { $version = $_REQUEST['ver']; header('Content-Type: text/cache-manifest'); header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); echo theme_load_manifest($version); } function theme_check_ajax_referer_filter($value, $action) { if ($action === 'theme_get_manifest' || $action === 'theme_get_project' || getenv('THEMLER_MANIFEST_STORAGE')) { return false; } return $value; } add_filter('theme_check_ajax_referer', 'theme_check_ajax_referer_filter', 10, 2); theme_add_export_action('theme_get_manifest'); function theme_set_files() { if (isset($_POST['files'])) { $files = json_decode(stripslashes_deep($_POST['files']), true); $result = '1'; } else { $info = theme_get_chunk_info(); $chunk = new Chunk(); if (is_wp_error($error = $chunk->save($info))) { theme_handle_bad_request($error); } if ($chunk->last()) { $files = json_decode($chunk->complete(), true); $result = array('result' => 'done'); } else { return array('result' => 'processed'); } } $template = get_template(); $theme_root = get_theme_root( $template ); $template_dir = $theme_root . '/' . $template; if (is_array($files)) { foreach($files as $file => $content) { if ($file === '/export/themler.manifest') theme_save_manifest($content); else if (false === file_put_contents($template_dir . $file, $content)) throw new PermissionDeniedException($template_dir . $file); } } if (is_array($result)) return $result; echo $result; } theme_add_export_action('theme_set_files', true); function theme_fso_zip() { $info = theme_get_chunk_info(); $chunk = new Chunk(); if (is_wp_error($error = $chunk->save($info))) { theme_handle_bad_request($error); } if (!$chunk->last()) { return array('result' => 'processed'); } $data = json_decode($chunk->complete(), true); if (!isset($data['fso'])) throw new Exception('Empty fso'); $base_upload_dir = wp_upload_dir(); $tmp_dir = $base_upload_dir['basedir'] . '/zip-data.tmp'; $zip_file = $base_upload_dir['basedir'] . '/zip-data.zip'; FilesHelper::empty_dir($tmp_dir, true); $changed_files = array(); $replace_data = array(); copy_fso_to_fs($data['fso'], $tmp_dir, $changed_files, $replace_data); $archive = new PclZip($zip_file); if (0 == $archive->create($tmp_dir, PCLZIP_OPT_REMOVE_PATH, $tmp_dir)) throw new Exception("Extract error : " . $archive->errorInfo(true)); $result = array('result' => 'done', 'data' => base64_encode(file_get_contents($zip_file))); FilesHelper::empty_dir($tmp_dir, true); FilesHelper::remove_file($zip_file); return $result; } theme_add_export_action('theme_fso_zip'); function theme_upload_rename_archive($archive_file, $tmp_dir) { $archive = new PclZip($archive_file); FilesHelper::empty_dir($tmp_dir, true); $default_name = 'Untitled'; $theme_root = "$tmp_dir/$default_name"; if (0 == $archive->extract(PCLZIP_OPT_PATH, $theme_root)) { return array( 'status' => 'error', 'message' => "

    Invalid WordPress Theme

    Extract error : " . $archive->errorInfo(true) ); } $files = FilesHelper::enumerate_files($theme_root, false); if (count($files) === 1 && is_dir($files[0]['path'])) { $theme_name = str_replace("$theme_root/", '', $files[0]['path']); } else { $theme_root = $tmp_dir; $theme_name = $default_name; } $new_theme_name = theme_create_name($theme_name); if ($new_theme_name !== $theme_name || $theme_root === $tmp_dir) { theme_set_name("$theme_root/$theme_name/preview/$theme_name"."_preview/style.css", theme_get_preview_theme_name($new_theme_name)); theme_set_name("$theme_root/$theme_name/style.css", $new_theme_name); FilesHelper::rename_if_exists("$theme_root/$theme_name/preview/$theme_name"."_preview", "$theme_root/$theme_name/preview/$new_theme_name"."_preview"); FilesHelper::rename_if_exists("$theme_root/$theme_name", "$theme_root/$new_theme_name"); if (0 == $archive->create("$theme_root/$new_theme_name", PCLZIP_OPT_REMOVE_PATH, $theme_root)) throw new Exception("Create error : " . $archive->errorInfo(true)); } return true; } function theme_upload_rename($filename) { $base_upload_dir = wp_upload_dir(); $basedir = FilesHelper::normalize_path($base_upload_dir['basedir']); $archive_file = "$basedir/$filename"; $tmp_dir = "$basedir/theme-upload"; $result = theme_upload_rename_archive($archive_file, $tmp_dir); FilesHelper::empty_dir($tmp_dir, true); // remove temp directory return $result; } function theme_upload_theme_callback($args) { $filename = $args['filename']; $_GET['filename'] = $filename; unset($_FILES['chunk']); if (true === ($result = theme_upload_rename($filename))) { $file_upload = new File_Upload_Upgrader('', 'filename'); $upgrader = new Theme_Upgrader(new WP_Export_Theme_Installer_Skin(compact('type', 'title', 'nonce', 'url'))); $upload_result = $upgrader->install($file_upload->package); $result = array(); if ($upload_result === true) { $result['status'] = 'done'; } else if ($upload_result === false || $upload_result === null) { $result['status'] = 'error'; $result['message'] = $upgrader->skin->output; } else if (is_wp_error($upload_result)) { $result['status'] = 'error'; $result['message'] = $upload_result->get_error_message(); } } $upload_dir = wp_upload_dir(); $tmp_path = $upload_dir['basedir'] . '/' . $filename; FilesHelper::remove_file($tmp_path); // remove archive return $result; } function theme_upload_theme() { if (!current_user_can('upload_themes') && !current_user_can('install_themes')) { return array( 'status' => 'error', 'message' => 'You do not have sufficient permissions to install themes on this site.' ); } return ChunkedUploader::process_action('theme_upload_theme_callback'); } theme_add_export_action('theme_upload_theme'); function theme_fso_unzip_callback($args) { $filename = $args['filename']; $upload_dir = wp_upload_dir(); $archive_file = $upload_dir['basedir'] . '/' . $filename; $tmp_dir = $upload_dir['basedir'] . '/zip-data.tmp'; FilesHelper::empty_dir($tmp_dir, true); $archive = new PclZip($archive_file); if (0 == $archive->extract(PCLZIP_OPT_PATH, $tmp_dir)) { return array( 'status' => 'error', 'message' => "

    Invalid zip

    Extract error : " . $archive->errorInfo(true) ); } $fso = FilesHelper::generate_fso($tmp_dir); FilesHelper::remove_file($archive_file); FilesHelper::empty_dir($tmp_dir, true); return array( 'status' => 'done', 'fso' => $fso ); } function theme_fso_unzip() { return ChunkedUploader::process_action('theme_fso_unzip_callback'); } theme_add_export_action('theme_fso_unzip'); // TODO: use ChunkedUploader function theme_upload_image() { $base_upload_dir = wp_upload_dir(); if (false !== $base_upload_dir['error']) { return array( 'status' => 'error', 'message' => 'Upload folder error: ' . $base_upload_dir['error'] ); } $is_last = $_REQUEST['last']; $content_range = $_SERVER['HTTP_CONTENT_RANGE']; if (!isset($_FILES['chunk']) || !file_exists($_FILES['chunk']['tmp_name'])) { return array( 'status' => 'error', 'message' => 'Empty chunk data' ); } if (!$content_range && !$is_last) { return array( 'status' => 'error', 'message' => 'Empty Content-Range header' ); } $filename = $_REQUEST['filename']; if (!$filename) { return array( 'status' => 'error', 'message' => 'Empty file name' ); } $tmp_path = $base_upload_dir['basedir'] . '/' . $filename . '.tmp'; $range_begin = 0; if ($content_range) { list($range, $total) = explode('/', str_replace('bytes ', '', $content_range)); list($range_begin, $range_end) = explode('-', $range); } ProviderLog::start('Save chunk'); $file = fopen($tmp_path, 'a'); if (flock($file, LOCK_EX)) { fseek($file, (int)$range_begin); fwrite($file, file_get_contents($_FILES['chunk']['tmp_name'])); flock($file, LOCK_UN); } fclose($file); ProviderLog::end('Save chunk'); if (!$is_last) { return array( 'status' => 'processed' ); } $is_content = theme_get_array_value($_REQUEST, 'isContent') === 'true'; $images_dir = $is_content ? $base_upload_dir['path'] : FilesHelper::normalize_path(get_template_directory() . '_preview/images'); if (!file_exists($images_dir) && !mkdir($images_dir, 0776, true)) { return array( 'status' => 'error', 'message' => 'Failed to create a folder: ' . $images_dir, ); } FilesHelper::create_dir($images_dir); if ($is_content) { $filename = wp_unique_filename($images_dir, $filename); } $base_path = $images_dir . '/' . $filename; if (file_exists($base_path)) { return array( 'status' => 'error', 'message' => 'File already exists: ' . $base_path ); } FilesHelper::rename($tmp_path, $base_path); if ($is_content) { ProviderLog::start('add attachment'); $wp_filetype = wp_check_filetype($filename, null); $attachment = array( 'guid' => $base_upload_dir['url'] . '/' . $filename, 'post_mime_type' => $wp_filetype['type'], 'post_title' => preg_replace('/\.[^.]+$/', '', $filename), 'post_content' => '', ); $attach_id = wp_insert_attachment($attachment, $base_path); $attach_data = wp_generate_attachment_metadata($attach_id, $base_path); wp_update_attachment_metadata($attach_id, $attach_data); ProviderLog::end('add attachment'); $image_url = wp_get_attachment_url($attach_id); theme_data_json_put(theme_get_uploaded_images_json_path(), $image_url, $attach_id); return array( 'status' => 'done', 'url' => $image_url ); } else { $changed_files = theme_get_preview_changed_files(); $changed_files[] = $base_path; theme_set_preview_changed_files($changed_files); return array( 'status' => 'done', 'url' => get_template_directory_uri() . '_preview/images/' . $filename ); } } theme_add_export_action('theme_upload_image', true); // other actions: load_template($base_template_dir . '/export/project.php'); load_template($base_template_dir . '/export/posts-actions.php'); load_template($base_template_dir . '/export/import-actions.php'); function theme_get_editable_content() { if (!isset($_REQUEST['contentId'])) { throw new Exception('contentId required'); } $data = array( 'result' => 'done', 'content' => '', 'model' => (object)array() ); list($type, $id) = explode("-", $_REQUEST['contentId']); if ('post' === $type) { $post = get_post($id); if ($post) { $data['content'] = apply_filters('theme_the_content', $post->post_content); } } echo json_encode($data); } theme_add_export_action('theme_get_editable_content'); function theme_put_editable_content() { $info = theme_get_chunk_info(); $chunk = new Chunk(); if (!$chunk->save($info)) { header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request', true, 400); return; } if (!$chunk->last()) { return array('result' => 'processed'); } $data = json_decode($chunk->complete(), true); if (is_array($data) && count($data) > 0){ foreach($data as $value){ $contentId = theme_get_array_value($value, 'contentId'); if ($contentId) { list($type, $id) = explode("-", $contentId); $content = theme_get_array_value($value, 'content', ""); $images = theme_get_array_value($value, 'images'); $base_upload_dir = wp_upload_dir(); if (is_array($images ) && count($images) > 0 && false === $base_upload_dir['error']) { foreach ($images as $image_id => $image_data) { $images_dir = $base_upload_dir['path']; $filename = wp_unique_filename($images_dir, theme_get_image_name($image_id)); $base_path = $images_dir . '/' . $filename; if ($image_data) { ProviderLog::start('add attachment'); $file = fopen($base_path, 'w'); if (flock($file, LOCK_EX)) { fwrite($file, base64_decode($image_data)); flock($file, LOCK_UN); } fclose($file); $wp_filetype = wp_check_filetype($filename, null); $attachment = array( 'guid' => $base_upload_dir['url'] . '/' . $filename, 'post_mime_type' => $wp_filetype['type'], 'post_title' => preg_replace('/\.[^.]+$/', '', $filename), 'post_content' => '', ); $attach_id = wp_insert_attachment($attachment, $base_path); $attach_data = wp_generate_attachment_metadata($attach_id, $base_path); wp_update_attachment_metadata($attach_id, $attach_data); $content = str_replace($image_id, wp_get_attachment_url($attach_id), $content); ProviderLog::end('add attachment'); } } } ProviderLog::start('update post'); $content = preg_replace('#src=("|\')url\(([^\)]+)\)#', 'src=$1$2', $content); if ('post' === $type) { $post = get_post($id); if ($post) { $post->post_content = $content; $meta_options = apply_filters('theme_' . $post->post_type . '_meta_options', array()); foreach ($meta_options as $meta_option) { if ($meta_option['id'] === 'theme_use_wpautop') { theme_set_meta_option($id, 'theme_use_wpautop', '0'); break; } } wp_update_post($post); } } ProviderLog::end('update post'); } } } return array('result' => 'done'); } theme_add_export_action('theme_put_editable_content', true); function theme_get_posts_fields_filter($fields) { global $wpdb; $fields = array( 'ID', 'post_title', 'post_type', 'post_name', 'post_status', 'post_date', 'post_date_gmt', 'post_modified', 'post_modified_gmt', 'post_author', 'guid', 'post_parent', ); $result = ''; foreach($fields as $field) { $result .= ($result ? ', ' : '') . "$wpdb->posts.$field"; } return $result; } function theme_get_posts() { $pagenum = isset($_REQUEST['pagenum']) ? absint($_REQUEST['pagenum']) : 1; $pts = get_post_types(array('public' => true), 'objects'); $post_type = isset($_REQUEST['post_type']) ? $_REQUEST['post_type'] : array_keys($pts); $sort_type = isset($_REQUEST['sort_type']) ? $_REQUEST['sort_type'] : ''; $posts_per_page = isset($_REQUEST['posts_per_page']) ? absint($_REQUEST['posts_per_page']) : 20; $search_string = isset($_REQUEST['s']) ? wp_unslash($_REQUEST['s']) : ''; ProviderLog::start('evaluate wp_query'); add_filter('posts_fields', 'theme_get_posts_fields_filter'); $query = new WP_Query; $posts = $query->query(array( 'post_type' => $post_type, 'update_post_term_cache' => false, 'update_post_meta_cache' => false, 'post_status' => 'publish', 'posts_per_page' => $posts_per_page, 's' => $search_string, 'offset' => $pagenum > 1 ? $posts_per_page * ($pagenum - 1) : 0, 'orderby' => $sort_type ? $sort_type : 'title' )); remove_filter('posts_fields', 'theme_get_posts_fields_filter'); ProviderLog::end('evaluate wp_query'); ProviderLog::start('generate result'); $results = array(); if ($query->post_count) { foreach ($posts as $post) { $results[] = array( 'name' => $post->ID, 'id' => $post->ID, 'caption' => trim(esc_html(strip_tags(get_the_title($post)))), 'url' => theme_get_preview_link(get_permalink($post)) ); } } ProviderLog::end('generate result'); return array( 'result' => 'done', 'data' => $results ); } theme_add_export_action('theme_get_posts');