| Server IP : 192.241.186.36 / Your IP : 216.73.216.164 Web Server : Apache/2.4.29 (Ubuntu) System : Linux webserver7 4.15.0-194-generic #205-Ubuntu SMP Fri Sep 16 19:49:27 UTC 2022 x86_64 User : root ( 0) PHP Version : 7.4.32 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /var/www/html/adsonicdigital/wp-content/themes/xstore/framework/ |
Upload File : |
<?php
/**
* Description
*
* @package patcher.php
* @since 9.1
* @author stas
* @link http://xstore.8theme.com
* @license Themeforest Split Licence
*/
if (!defined('ETHEME_FW')) {
exit('No direct script access allowed');
}
class Etheme_Patcher
{
public static $instance = null;
private $patcher_api_url = 'https://8theme.com/patcher/';
private $patcher_token = null;
private $patcher_transient_key = 'xstore_patches';
private $patcher_test_mode = false;
private $patcher_api_connected = true;
private $writable_files = true;
public function __construct()
{
add_action('wp_ajax_xstore_refresh_patches', array($this, 'refresh_patches'));
add_action('wp_ajax_nopriv_xstore_refresh_patches', array($this, 'refresh_patches'));
add_action('wp_ajax_xstore_apply_patch', array($this, 'apply_patch'));
add_action('wp_ajax_nopriv_xstore_apply_patch', array($this, 'apply_patch'));
add_action('wp_ajax_xstore_apply_patch_all', array($this, 'apply_all_patches'));
add_action('wp_ajax_nopriv_xstore_apply_patch_all', array($this, 'apply_all_patches'));
add_action('after_switch_theme', array($this, 'reset_patches_cache'));
add_filter('pre_set_site_transient_update_themes', array($this, 'set_update_transient'));
$this->patcher_test_mode = isset($_GET['xstore-patches-test-mode']);
$activated_data = get_option( 'etheme_activated_data' );
$this->patcher_token = ( isset( $activated_data['purchase'] ) && ! empty( $activated_data['purchase'] ) ) ? $activated_data['purchase'] : '';
}
public function refresh_patches()
{
check_ajax_referer('refresh-patches', 'security');
$this->reset_available_patches();
$this->reset_patches_cache();
echo wp_json_encode(
array(
'success' => true,
)
);
exit;
}
/**
* Reset patches caches site transient
* @return void
*/
public function reset_patches_cache()
{
delete_site_transient($this->patcher_transient_key);
}
/**
* Reset available patches caches site transient
*/
public function reset_available_patches()
{
delete_site_transient($this->patcher_transient_key . '_available');
}
/**
* Reset applied patches caches site transient
*/
public function reset_applied_patches()
{
delete_site_transient($this->patcher_transient_key . '_done');
}
/**
* Reset patches caches on theme update
* @param $transient
* @return mixed
*/
public function set_update_transient($transient)
{
$this->reset_patches_cache();
$this->reset_available_patches();
if ( apply_filters($this->patcher_transient_key . '_done_reset_on_update_themes', true) )
$this->reset_applied_patches();
return $transient;
}
public function get_available_patches($theme_version) {
$available_patches = get_site_transient($this->patcher_transient_key . '_available', array());
if ( $available_patches )
return $available_patches;
$all_patches = $this->get_patches($theme_version);
if ( !$all_patches )
$all_patches = array();
else {
// if there are patches according to current version
if ( array_key_exists($theme_version, $all_patches) )
$all_patches = array_keys($all_patches[$theme_version]);
else
$all_patches = array();
}
$available_patches = array_diff($all_patches, $this->get_applied_patches());
set_site_transient($this->patcher_transient_key . '_available', $available_patches, DAY_IN_SECONDS);
return $available_patches;
}
public function get_applied_patches() {
$applied_patches = get_site_transient($this->patcher_transient_key . '_done', array());
$applied_patches = !$applied_patches ? array() : json_decode($applied_patches, true);
return !empty($applied_patches) ? array_merge(...array_values($applied_patches)) : $applied_patches;
}
/**
* Getter for available patches
* @param $theme_version
* @return array
*/
public function get_patches($theme_version, $on_test = false)
{
$test_mode = $on_test || $this->patcher_test_mode;
if ( !$test_mode ) {
$cached_patches = get_site_transient($this->patcher_transient_key, array());
if ($cached_patches) {
return $cached_patches;
}
}
$patches_list = array();
$patches = wp_remote_get(
add_query_arg(array(
'action' => 'get',
'min_version' => $theme_version
), $this->patcher_api_url));
$code = wp_remote_retrieve_response_code($patches);
if ($code!=200){
$this->patcher_api_connected = false;
return array();
}
$patches = wp_remote_retrieve_body($patches);
$patches = json_decode($patches, true);
if ($patches['status'] == 'success') {
$patches_list = $patches['data'];
}
$ready_patches = array();
// sort patches according to upload date/time
usort($patches_list, function ($a, $b) {
return new DateTime($a['last_update']) <=> new DateTime($b['last_update']);
});
foreach ($patches_list as $key => $value) {
// if ( version_compare( $value['version'], $theme_version, '<' ) ) continue;
if ( !$test_mode && in_array($value['status'], array('inactive', 'delete')) ) continue;
$files = json_decode($value['file_path'], true);
if (!array_key_exists($value['version'], $ready_patches))
$ready_patches[$value['version']] = array();
$ready_files = array();
foreach ($files as $file_id => $file_path) {
$project = $file_path['base'];
if (!array_key_exists($project, $ready_files))
$ready_files[$project] = array();
$ready_files[$project][$file_id] = $file_path['path'];
}
unset($value['file_path']);
$patch_info = $value;
$patch_info['files'] = $ready_files;
$ready_patches[$value['version']][$patch_info['code']] = $patch_info;
}
// sort patches by theme versions
ksort($ready_patches);
set_site_transient($this->patcher_transient_key, $ready_patches, DAY_IN_SECONDS);
return $ready_patches;
}
/**
* Patches html for XStore Control panel -> Patcher tab
* @param $theme_version
* @return void
*/
public function get_patches_list($theme_version = '1.0.0')
{
$patches = $this->get_patches($theme_version);
if ( !$this->patcher_api_connected ) {
echo '<p class="et-message et-error">'.esc_html__('We are unable to connect to the XStore API with the XStore theme. Please check your SSL certificate or white lists.', 'xstore').'</p>';
return;
}
if (!count($patches)) {
echo '<p class="et-message et-info">' . sprintf(esc_html__('Currently, you have installed the most recent version. There are no updates or patches available at this time. In the unlikely event that you encounter any bugs, please reach out to our support team through the provided %slink%s and we will work to resolve the issue promptly.', 'xstore'), '<a href="https://www.8theme.com/forums/xstore-wordpress-support-forum/" rel="nofollow" target="_blank">', '</a>') . '</p>';
?>
<p>
<span class="et-button et-button-dark-grey refresh-patches"
data-nonce="<?php echo wp_create_nonce('refresh-patches'); ?>">
<span class="et-loader">
<svg class="loader-circular" viewBox="25 25 50 50">
<circle class="loader-path" cx="50" cy="50" r="12" fill="none" stroke-width="2"
stroke-miterlimit="10"></circle>
</svg>
</span>
<span class="dashicons dashicons-image-rotate"></span>
<?php esc_html_e('Check for updates', 'xstore'); ?>
</span>
</p>
<?php
return;
}
echo '<p>' .
sprintf(esc_html__('Unleash the full potential of your website with The Parcher! With its unique ability to apply small fixes between XStore releases, you can now keep your site up-to-date and running smoothly. In the unlikely event that you encounter any bugs, please reach out to our support team through the provided %slink%s and we will work to resolve the issue promptly.', 'xstore'),
'<a href="https://www.8theme.com/forums/xstore-wordpress-support-forum/" rel="nofollow" target="_blank">', '</a>') .
'</p>';
echo '<p class="et-message et-info">' .
esc_html__('We recommend that you make backups of your website before making any changes. After applying patches, please remember to clear your website caches and CDN in order to see the changes take effect.', 'xstore') .
'</p>';
$this->patches_info = $this->get_patches_info($patches);
$limit = 15;
$info_alert = '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path d="M12 0.024c-6.6 0-11.976 5.376-11.976 11.976s5.376 11.976 11.976 11.976 11.976-5.376 11.976-11.976-5.376-11.976-11.976-11.976zM12 22.056c-5.544 0-10.056-4.512-10.056-10.056s4.512-10.056 10.056-10.056 10.056 4.512 10.056 10.056-4.512 10.056-10.056 10.056zM12.24 4.656h-0.48c-0.48 0-0.84 0.264-0.84 0.624v8.808c0 0.336 0.36 0.624 0.84 0.624h0.48c0.48 0 0.84-0.264 0.84-0.624v-8.808c0-0.336-0.36-0.624-0.84-0.624zM12.24 16.248h-0.48c-0.456 0-0.84 0.384-0.84 0.84v1.44c0 0.456 0.384 0.84 0.84 0.84h0.48c0.456 0 0.84-0.384 0.84-0.84v-1.44c0-0.456-0.384-0.84-0.84-0.84z"></path></svg>';
ob_start();
?>
<p>
<span class="et-button et-button-dark-grey refresh-patches"
data-nonce="<?php echo wp_create_nonce('refresh-patches'); ?>">
<span class="et-loader">
<svg class="loader-circular" viewBox="25 25 50 50">
<circle class="loader-path" cx="50" cy="50" r="12" fill="none" stroke-width="2"
stroke-miterlimit="10"></circle>
</svg>
</span>
<span class="dashicons dashicons-image-rotate"></span>
<?php esc_html_e('Refresh patches', 'xstore'); ?>
</span>
</p>
<div class="etheme-patcher-table-wrapper">
<table>
<thead>
<tr>
<th class="patch-id">
<?php esc_html_e('Patch ID', 'xstore'); ?>
</th>
<th class="patch-description">
<?php esc_html_e('Description', 'xstore'); ?>
</th>
<th class="patch-date">
<?php esc_html_e('Data', 'xstore'); ?>
</th>
<th class="patch-action">
{{apply_all_patches_button}}
</th>
</tr>
</thead>
<tbody>
<?php
$available_patches_count = 0;
foreach ($this->patches_info as $patch_info) {
$description = html_entity_decode($patch_info['description']);
$description_tooltip = strlen($description) > 100;
$description_class = $description_tooltip ? ' mtips mtips-lg' : '';
if ( $description_tooltip ) {
$description_title = substr($description,0,30) . '... (<span class="patch-more-details">' . esc_html__('More details', 'xstore') . '</span>)';
$description = $description_title . '<span class="mt-mes">' . $description . '</span>';
}
$classes = array();
if ( !$patch_info['active_status'] )
$classes[] = 'patch-test-mode';
if ( $limit < 1 )
$classes[] = 'hidden'; ?>
<tr class="<?php echo implode(' ', $classes); ?>">
<?php echo '<td class="patch-id">#' . $patch_info['patch_id'] . '</td>'; ?>
<?php echo '<td class="patch-description"><span class="patch-description-content'.$description_class.'">' . $description . '</span></td>'; ?>
<?php echo '<td class="patch-date"><span class="patch-date-info">' . $patch_info['last_update'][0] . '</span><span class="patch-time-info">' . $patch_info['last_update'][1] . '</span></td>'; ?>
<td class="patch-action">
<?php
if ($patch_info['applied']) {
echo '<span class="patch-unavailable success">' .
'<svg width="1em" height="1em" viewBox="0 0 9 9" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.5 0C2.01911 0 0 2.01911 0 4.5C0 6.98089 2.01911 9 4.5 9C6.98089 9 9 6.98089 9 4.5C9 2.01911 6.98089 0 4.5 0ZM4.5 8.2666C2.41751 8.2666 0.7334 6.5825 0.7334 4.5C0.7334 2.41751 2.41751 0.7334 4.5 0.7334C6.5825 0.7334 8.2666 2.41751 8.2666 4.5C8.2666 6.5825 6.5825 8.2666 4.5 8.2666ZM6.80885 2.85211C6.70926 2.84306 6.6006 2.87928 6.52817 2.95171L3.85714 5.54125L2.47183 4.11972C2.3994 4.04728 2.2998 4.01107 2.19115 4.01107C2.0825 4.01107 1.9829 4.05634 1.92857 4.14688C1.86519 4.22837 1.82897 4.33702 1.83803 4.43662C1.84708 4.51811 1.8833 4.5996 1.94668 4.64487L3.58551 6.33803C3.65795 6.41046 3.74849 6.44668 3.84809 6.44668C3.93863 6.44668 4.02918 6.41046 4.10161 6.33803L7.02616 3.48592C7.09859 3.41348 7.13481 3.31388 7.13481 3.20523C7.13481 3.11469 7.09859 3.02414 7.03521 2.96982C6.98089 2.89738 6.8994 2.86117 6.80885 2.85211Z" fill="currentColor"/>
</svg>' . esc_html__('Applied', 'xstore') . '</span>';
} elseif (count($patch_info['requirements'])) {
echo '<span class="patch-unavailable mtips mtips-lg mtips-left">' . $info_alert . esc_html__('Read details', 'xstore') .
'<span class="mt-mes">' . implode("\n", $patch_info['requirements']) . '</span></span>';
}
else {
$files_from_previous_patches = array();
$all_patches = $this->patches_info;
$all_patches = array_reverse($all_patches);
$prev_patch_id = false;
$patch_same_files = array();
foreach ($all_patches as $patch_local_info) {
// skip patches which were already applied
if ($patch_local_info['applied']) continue;
if ($patch_local_info['patch_id'] === $patch_info['patch_id']) break;
// showing which patches should be applied first
if (count(array_intersect($patch_local_info['files_inline'], $patch_info['files_inline'])))
$patch_same_files[] = $patch_local_info['patch_id'];
}
// showing which patches should be applied first
if (!$this->patcher_test_mode && count($patch_same_files) && $prev_patch_id = $patch_same_files[array_key_first($patch_same_files)]) {
echo
(!$patch_info['active_status'] ? '<sub>'.esc_html__('Test mode', 'xstore').'</sub> ' : '') .
'<span class="et-button et-button-grey2 mtips mtips-left required-patch no-transform no-loader no-hover" data-patch_id="' . $patch_info['patch_id'] . '" data-required_patch="' . $prev_patch_id . '">' .
esc_html__('Apply', 'xstore') .
'<span class="mt-mes">' . sprintf(esc_html__('Apply %s patch first', 'xstore'), '#' . $prev_patch_id) . ( !$patch_info['active_status'] ? '. ' . sprintf(esc_html__(' %s patch should have active status first', 'xstore'), '#' . $prev_patch_id) : '' ) . '</span></span>';
}
// check if current theme version is ok for patch's theme version
// could work without this condition also but better to check to prevent global changes in files
elseif ( !$this->patcher_test_mode && version_compare($patch_info['theme_version'], $theme_version, '>') ) {
echo '<span class="et-button et-button-grey2 mtips mtips-left mtips-lg required-version no-transform no-loader no-hover" data-required_theme_version="' . $patch_info['theme_version'] . '">' .
esc_html__('Apply', 'xstore') .
'<span class="mt-mes">' . sprintf(__('This patch is available for XStore theme version %1s or later. Please update your %2s before proceeding.', 'xstore'), $patch_info['theme_version'], '<a href="https://www.youtube.com/watch?v=kPo0fiNY4to" rel="nofollow" target="_blank">'.esc_html__('XStore theme', 'xstore').'</a>') . '</span></span>';
}
else {
// data-files will be shown in alert before applied -> These files will be overwritten on your server ...
$files_info_attributes = array();
foreach ($patch_info['files'] as $files_project => $patch_project_file) {
if (!array_key_exists($files_project, $files_info_attributes))
$files_info_attributes[$files_project] = array();
$files_info_attributes[$files_project][] = $patch_project_file;
}
// strange patch with no files changed but let's better leave this condition here
// could be useful as fix for some cases when patch was added for update but no files added for this patch
if (!count($files_info_attributes))
echo '<span class="patch-unavailable mtips mtips-left">' . $info_alert . esc_html__('Read details', 'xstore') .
'<span class="mt-mes">' . esc_html__('This patch is currently unavailable. Please ignore it.', 'xstore') . '</span></span>';
else {
$available_patches_count++;
echo (!$patch_info['active_status'] ? '<sub>'.esc_html__('Test mode', 'xstore').'</sub> ' : '') .
'<button class="et-button et-button-green no-transform apply-patch et-button-arrow" data-patch_id="' . $patch_info['patch_id'] . '" data-theme_version="' . $patch_info['theme_version'] . '" data-files=\'' . json_encode($files_info_attributes) . '\'>' .
'<span class="et-loader">
<svg class="loader-circular" viewBox="25 25 50 50">
<circle class="loader-path" cx="50" cy="50" r="12" fill="none" stroke-width="2" stroke-miterlimit="10"></circle>
</svg>
</span>' .
esc_html__('Apply', 'xstore') .
'<svg class="arrow-icon" xmlns="http://www.w3.org/2000/svg" width="1.3em" height="1.3em" viewBox="0 0 32 32">
<g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round" stroke-miterlimit="10">
<circle class="arrow-icon--circle" cx="16" cy="16" r="15.12"></circle>
<path class="arrow-icon--arrow" d="M16.14 9.93L22.21 16l-6.07 6.07M8.23 16h13.98"></path>
</g>
</svg>' .
'</button>';
}
}
}
?>
</td>
</tr>
<?php
$limit--;
}
?>
</tbody>
</table>
</div>
<?php
if ($limit < 1) { ?>
<p class="text-center">
<span class="et-button load-patches">
<span class="et-loader">
<svg class="loader-circular" viewBox="25 25 50 50">
<circle class="loader-path" cx="50" cy="50" r="12" fill="none" stroke-width="2"
stroke-miterlimit="10"></circle>
</svg>
</span>
<?php esc_html_e('Load more', 'xstore'); ?>
</span>
</p>
<?php }
$apply_all_button = esc_html__('Action', 'xstore');
if ( $available_patches_count > 0 ) {
$apply_all_button =
'<button class="et-button apply-patch no-transform" data-patch_id="all" data-files="all" data-theme_version="' . $theme_version . '">' .
'<span class="et-loader">
<svg class="loader-circular" viewBox="25 25 50 50">
<circle class="loader-path" cx="50" cy="50" r="12" fill="none" stroke-width="2" stroke-miterlimit="10"></circle>
</svg>
</span>' .
esc_html__('Apply all patches', 'xstore') .
'</button>';
}
echo str_replace('{{apply_all_patches_button}}', $apply_all_button, ob_get_clean());
}
/**
* Generate information data for each patches set from args
* @param $patches
* @return array
*/
public function get_patches_info($patches, $on_test = false)
{
$patch_index = array();
$ready_patches = array();
$test_mode = $on_test || $this->patcher_test_mode;
$all_applied_patches_keys = $this->get_applied_patches();
foreach ($patches as $patches_theme_version => $theme_version_patches_list) {
$patch_index[$patches_theme_version] = 0;
foreach ($theme_version_patches_list as $patch) {
if ( !$test_mode && $patch['status'] == 'inactive') continue;
// hide patches for the lower theme versions than current theme version, useful for cached patches
if ( !$test_mode && version_compare($patches_theme_version, ETHEME_THEME_VERSION, '<')) continue;
$patch_index[$patches_theme_version]++;
$files = $patch['files'];
$patch_id = $patch['code'];
$patch_details = array(
'theme_version' => $patches_theme_version,
'patch_id' => $patch_id,
'patch_index' => $patch_index[$patches_theme_version],
'active_status' => $patch['status'] == 'active',
'files' => array(),
'files_inline' => array(),
'description' => $patch['description'],
'last_update' => explode(' ', $patch['last_update']),
'requirements' => array(),
'applied' => false
);
if (in_array($patch_id, $all_applied_patches_keys)) {
$patch_details['applied'] = true;
}
foreach ($files as $project_key => $project_files) {
$patch_details['files'][$project_key] = $project_files;
foreach ($project_files as $project_file_id => $project_file_path) {
$patch_details['files_inline'][$project_file_id] = $project_key . '/' . $project_file_path;
}
}
$patch_details['files_inline'] = array_unique($patch_details['files_inline']);
if (isset($patch['requirements'])) {
foreach ($patch['requirements'] as $req_project_key => $project_requirements) {
if (isset($project_requirements['min_version'])) {
$project_name = false;
$project_version = false;
$project_type = 'plugin';
switch ($req_project_key) {
case 'theme':
$project_name = 'XStore';
$project_version = ETHEME_THEME_VERSION;
$project_type = 'theme';
break;
case 'et-core-plugin':
if (defined('ET_CORE_VERSION')) {
$project_name = 'XStore Core';
$project_version = ET_CORE_VERSION;
}
break;
case 'xstore-advanced-sticky-header':
if (defined('XStore_Advanced_Sticky_Header_Version')) {
$project_name = 'XStore Advanced Sticky Header';
$project_version = XStore_Advanced_Sticky_Header_Version;
}
break;
}
if ($project_name && $project_version) {
if (version_compare($project_version, $project_requirements['min_version'], '<')) {
if ($project_type == 'theme')
$patch_details['requirements'][$req_project_key] = sprintf(esc_html__('You are using %s version of %s theme but for this patch you need to have at least %s version', 'xstore'), $project_version, '<a href="' . admin_url('update-core.php') . '">' . $project_name . '</a>', $project_requirements['min_version']);
else
$patch_details['requirements'][$req_project_key] = sprintf(esc_html__('You are using %s version of %s plugin but for this patch you need to have at least %s version', 'xstore'), $project_version, '<a href="' . admin_url('update-core.php') . '">' . $project_name . '</a>', $project_requirements['min_version']);
}
}
}
}
}
array_unshift($ready_patches, $patch_details);
}
}
return $ready_patches;
}
/**
* Getter of patch file's content
* @param $patch_id
* @param $file_id
* @return mixed|string
*/
public function get_patch_file_from_server($patch_id, $file_id)
{
$url = add_query_arg(array(
'action' => 'file-get',
'code' => $patch_id,
'token' => $this->patcher_token,
'fid' => $file_id
), $this->patcher_api_url);
$response = wp_remote_get($url);
if (is_wp_error($response)) {
return array(
'message' => $response->get_error_message(),
'status' => 'error',
);
}
if (!isset($response['body'])) {
return array(
'message' => $response['response']['code'] . ': ' . $response['response']['message'],
'status' => 'error',
);
}
$response = json_decode(html_entity_decode($response['body']), true);
if (isset($response['status']) && $response['status'] == 'error' && isset($response['data'])) {
return array(
'message' => $response['data'],
'status' => 'error',
);
}
if (!isset($response['content'])) {
return array(
'message' => esc_html__('Error', 'xstore') . ': ' . sprintf(esc_html__('We would like to inform you that the file you have downloaded has no content. Please kindly inform us via our contact page %1s so that we can fix the issue immediately.', 'xstore'), 'https://www.8theme.com/contact-us/'),
'status' => 'error',
);
}
return array(
'content' => $response['content'],
'status' => 'success',
);
}
/**
* Applier of the patch
* @return void
*/
public function apply_patch($patch_local_id = null, $patch_files = [], $multiple = false, $on_test = false)
{
$patch_id = isset($_POST['patch_id']) ? $_POST['patch_id'] : $patch_local_id;
$files = isset($_POST['files']) ? $_POST['files'] : $patch_files;
$test_mode = isset($_POST['test_mode']) ? $_POST['test_mode'] : $on_test;
$errors = array();
if (!$patch_id && !$multiple) {
echo wp_json_encode(
array(
'success' => false,
'errors_text' => __('This patch does not exist or was removed. Please try again later.', 'xstore'),
'errors' => $errors
)
);
exit;
}
foreach ($files as $project => $project_files) {
// in some cases it returns array in array
$project_files = isset($project_files[0]) ? $project_files[0] : $project_files;
foreach ($project_files as $project_files_key => $project_file_path) {
$content = $this->get_patch_file_from_server($patch_id, $project_files_key);
if ( $content['status'] != 'success' ) {
$this->writable_files = false;
if (!array_key_exists('server_errors', $errors))
$errors['server_errors'] = array();
$errors['server_errors'][] = $content['message'];
continue;
}
if (!$content['content']) {
$this->writable_files = false;
continue;
}
if (!$this->write_file($project, $project_file_path, $content['content'])) {
if (!array_key_exists($project, $errors))
$errors[$project] = array();
$errors[$project][] = $project_file_path;
}
}
}
if (count($errors) < 1 && !$test_mode) {
$theme_version = $_POST['theme_version'];
$applied_patches = get_site_transient('xstore_patches_done', array());
$applied_patches = !$applied_patches ? array() : json_decode($applied_patches, true);
if (!array_key_exists($theme_version, $applied_patches)) {
$applied_patches[$theme_version] = array();
}
$applied_patches[$theme_version][] = $patch_id;
set_site_transient('xstore_patches_done', json_encode($applied_patches));
$this->reset_available_patches();
}
if ($multiple) {
return $errors;
} else {
echo wp_json_encode(
array(
'success' => count($errors) < 1,
'errors_text' => __('Some files were unable to be modified on your server. Please check your "Server Requirements" page or try again later.', 'xstore'),
'server_errors_text' => __('There seems to be an issue with the server request. Please ensure that your theme has a valid purchase code.', 'xstore'),
'system_requirements_link' => add_query_arg(array('page' => 'et-panel-system-requirements'), admin_url('admin.php')),
'errors' => $errors
)
);
exit;
}
}
public function apply_all_patches()
{
$test_mode = $_POST['test_mode'];
$patches = $this->get_patches($_POST['theme_version'], $test_mode);
$patches_info = array_reverse($this->get_patches_info($patches, $test_mode));
$success_patches = array();
$broken_patches = array();
$broken_patches_files = array();
foreach ($patches_info as $patch_info) {
// check if current theme version is ok for patch's theme version
// could work without this condition also but better to check to prevent global changes in files
if ( !$test_mode && version_compare($patch_info['theme_version'], $_POST['theme_version'], '>') )
continue;
// there are no sense to re-apply already applied patches
if ($patch_info['applied'])
continue;
// don't apply patches with inactive status
if (!$test_mode && !$patch_info['active_status'])
continue;
// if some files from previous patches were broken then prevent next patches action to rewrite same files
if (count(array_intersect($broken_patches_files, $patch_info['files_inline']))) {
continue;
}
$test = $this->apply_patch($patch_info['patch_id'], $patch_info['files'], true, $test_mode);
if (count($test)) {
$broken_patches[] = '#' . $patch_info['patch_id'];
$broken_patches_files = array_unique(array_merge($broken_patches_files, $patch_info['files_inline']));
}
else {
$success_patches[] = $patch_info['patch_id'];
}
}
$this->reset_available_patches();
echo wp_json_encode(
array(
'success' => count($broken_patches) < 1,
'success_text' => __('Congratulations, all patches have been successfully applied.', 'xstore'),
'success_patches' => $success_patches,
'server_errors_text' => __('There is a problem with the request to get files\' content. Please ensure that your theme has a valid purchase code.', 'xstore'),
'errors_text' => __('We apologize for the inconvenience, but it seems that some patches could not be applied. Please make sure to check your "Server Requirements" page or try again later. Thank you.', 'xstore'),
'system_requirements_link' => add_query_arg(array('page' => 'et-panel-system-requirements'), admin_url('admin.php')),
'errors' => $broken_patches
)
);
exit;
}
/**
* Write file content on server with the content from patch's file
* @param $project_type
* @param $file_path
* @param $content
* @return bool
*/
public function write_file($project_type, $file_path, $content)
{
global $wp_filesystem;
if (function_exists('WP_Filesystem')) {
WP_Filesystem();
}
$target = $project_type == 'xstore' ? get_template_directory() . wp_normalize_path('/' . $file_path) :
WP_PLUGIN_DIR . wp_normalize_path('/' . $project_type . '/' . $file_path);
// create folders if the ones didn't exist yet
if (!$wp_filesystem->exists($target)) {
$pos = strripos($target, '/');
if (!wp_mkdir_p(substr($target, 0, $pos))) {
return false;
}
}
$status_write_file = $wp_filesystem->put_contents($target, $content);
if (!$status_write_file) {
$this->successful_write_files = false;
return false;
}
return true;
}
/**
* Returns the instance.
*
* @return object
* @since 9.1.1
*/
public static function get_instance( $shortcodes = array() ) {
if ( null == self::$instance ) {
self::$instance = new self( $shortcodes );
}
return self::$instance;
}
}
$patcher = new Etheme_Patcher();