/home/sylamedg/www/wp-content/plugins/templately/includes/Core/Importer/Runners/Dependencies.php
<?php
namespace Templately\Core\Importer\Runners;
use Exception;
use Templately\Core\Importer\Exception\NonRetirableErrorException;
use Templately\Core\Importer\Form;
use Templately\Core\Importer\Runners\BaseRunner;
use Templately\Core\Importer\Utils\Utils;
use Templately\Utils\Helper;
use Templately\Utils\Installer;
class Dependencies extends BaseRunner {
public function get_name(): string {
return 'dependencies';
}
public function get_label(): string {
return __( 'Download Dependencies', 'templately' );
}
public function should_log(): bool {
return true;
}
public function get_action(): string {
return 'eventLog';
}
public function log_message(): string {
return __( 'Downloading Dependencies', 'templately' );
}
public function should_run( $data, $imported_data = [] ): bool {
return ! empty( $data['theme'] ) || ! empty( $data['plugins'] );
}
public function import( $data, $imported_data ): array {
$dependency_data = [];
$progress = $data['progress'] ?? [];
/**
* Checking & Installing Plugin Dependencies
*/
$dependency_data['theme'] = $this->install_themes($data);
$dependency_data['plugins'] = $this->install_plugins($data);
/**
* Exit current request to allow WordPress to load newly activated plugins
* On the next AJAX call, WordPress will have loaded all active plugins
*/
if ( empty( $progress['plugins_installed'] ) ) {
// Mark plugins as installed
$progress['plugins_installed'] = true;
$this->update_session_data( [
'progress' => $progress,
] );
// Exit current request and continue in new AJAX call where WordPress has loaded the plugins
$this->sse_message( [
'type' => 'continue',
'action' => 'continue',
'info' => 'plugins_installed',
'results' => __METHOD__ . '::' . __LINE__,
] );
exit;
}
// /**
// * Verify that required plugins are active and their classes are loaded
// * This runs in the new AJAX call after WordPress has loaded the plugins
// */
// $this->verify_required_plugins_active( $data );
return ['dependency_data' => $dependency_data];
}
private function install_plugins($request_params) {
$progress = $request_params['progress'] ?? [];
$results = [];
if ( ! empty( $request_params['plugins'] ) && is_array( $request_params['plugins'] ) ) {
// $this->sse_log( 'plugin', 'Installing Plugins', 1 );
$total_plugin = count($request_params['plugins']);
// $total_plugin_installed = $total_plugin;
// $_installed_plugins = $request_params['dependency_data']['plugins']['_installed_plugins'] ?? 0;
$progress['plugin_dependency'] = $progress['plugin_dependency'] ?? [];
// $this->before_install_hook();
// error_log(print_r($request_params['plugins'], true), 3, ABSPATH . 'wp-content/debug.log');
// Sort plugins to ensure pro plugins are activated after free versions
$plugin_order = [
'elementor/elementor.php',
'elementor-pro/elementor-pro.php',
'essential-addons-for-elementor-lite/essential_adons_elementor.php',
'essential-addons-elementor/essential_adons_elementor.php'
];
usort($request_params['plugins'], function($a, $b) use ($plugin_order) {
$pos_a = array_search($a['plugin_file'], $plugin_order);
$pos_b = array_search($b['plugin_file'], $plugin_order);
// If both plugins are in the order array, sort by their position
if ($pos_a !== false && $pos_b !== false) {
return $pos_a - $pos_b;
}
// If only one plugin is in the order array, prioritize it
if ($pos_a !== false) {
return -1;
}
if ($pos_b !== false) {
return 1;
}
// If neither plugin is in the order array, maintain original order
return 0;
});
$results = $this->loop( $request_params['plugins'], function( $key, $dependency, $results ) use(&$_installed_plugins, $total_plugin) {
error_log(print_r([$key, $dependency['name']], true), 3, ABSPATH . 'wp-content/debug.log');
$_installed_plugins = $results['_installed_plugins'] ?? 0;
// $result = [];
$this->sse_log( 'plugin', 'Installing Required Plugins: ' . $dependency['name'], floor( ( 100 * $_installed_plugins / $total_plugin ) ) );
$dependency['slug'] = $dependency['plugin_original_slug'];
$plugin_status = Installer::get_instance()->install($dependency);
if (!$plugin_status['success']) {
$error_message = 'Installation Failed: ' . $dependency['name'];
if (!empty($plugin_status['message'])) {
$error_message .= ' (' . $plugin_status['message'] . ')';
}
$this->sse_message([
'position' => 'plugin',
'action' => 'updateLog',
'status' => 'error',
'message' => $error_message,
'type' => "plugin_{$dependency['plugin_original_slug']}",
'progress' => 0
]);
if (isset($dependency['mustHave']) && $dependency['mustHave']) {
$this->removeLog('plugin');
throw new NonRetirableErrorException($error_message);
}
$results['failed'][] = [
'name' => $dependency['name'],
'slug' => $dependency['slug'],
'link' => $dependency['link'],
'message' => $plugin_status['message'] ?? ''
];
} else {
$_installed_plugins++;
// $total_plugin_installed--;
}
$results['_installed_plugins'] = $_installed_plugins;
$this->sse_log( 'plugin', 'Installed Required Plugins: ' . $dependency['name'], floor( ( 100 * $_installed_plugins / $total_plugin ) ) );
return $results;
}, null, true);
// $this->after_install_hook();
$this->sse_message([
'action' => 'updateLog',
'status' => 'complete',
'message' => "Installed Required Plugins ({$results['_installed_plugins']}/$total_plugin)",
'type' => "plugin",
'progress' => 100
]);
$results['total'] = $total_plugin;
$results['succeed'] = $results['_installed_plugins'];
} else {
$this->removeLog('plugin');
}
return $results;
}
/**
* Verify that required plugins are active and their classes are loaded
*
* This method checks if the required plugins (Elementor or Gutenberg) are properly
* activated and their classes are available. This is crucial because WordPress doesn't
* automatically load newly installed plugins until the next request.
*
* @param array $data Request parameters containing plugin information
* @throws NonRetirableErrorException If required plugin classes are not loaded
*/
private function verify_required_plugins_active( $data ) {
// Get the platform from manifest
$platform = $data['manifest']['platform'] ?? '';
// Check for Elementor platform
if ( $platform === 'elementor' ) {
// Check if Elementor core classes are loaded
if ( ! class_exists( 'Elementor\Plugin' ) && ! class_exists( 'Elementor\Core\Base\Document' ) ) {
$error_message = __( 'Elementor plugin is not properly activated. Please refresh the page and try again.', 'templately' );
throw new NonRetirableErrorException( $error_message );
}
}
// Check for Gutenberg/Essential Blocks platform
if ( $platform === 'gutenberg' ) {
// Check if Essential Blocks plugin is active
if ( ! defined( 'ESSENTIAL_BLOCKS_FILE' ) ) {
$error_message = __( 'Essential Blocks plugin is not properly activated. Please refresh the page and try again.', 'templately' );
throw new NonRetirableErrorException( $error_message );
}
}
// Additional verification: Check if installed plugins are actually active
if ( ! empty( $data['plugins'] ) && is_array( $data['plugins'] ) ) {
foreach ( $data['plugins'] as $plugin ) {
// Only check mustHave plugins
if ( isset( $plugin['mustHave'] ) && $plugin['mustHave'] ) {
if ( ! is_plugin_active( $plugin['plugin_file'] ) ) {
$error_message = sprintf(
__( 'Required plugin "%s" is not active. Please refresh the page and try again.', 'templately' ),
$plugin['name']
);
throw new NonRetirableErrorException( $error_message );
}
}
}
}
}
private function install_themes($request_params) {
$themes = [];
if ( ! empty( $request_params['theme'] ) && is_array( $request_params['theme'] ) ) {
$themes = [$request_params['theme']];
}
else {
$this->removeLog( 'theme' );
}
// $this->before_install_hook();
$results = $this->loop($themes, function($key, $theme) {
$result = [];
if (isset($theme['stylesheet'])) {
$stylesheet = get_option('stylesheet');
// do_action('before_theme_activation', $theme); // Trigger action before theme activation
$this->sse_log('theme', 'Installing and Activating Theme: ' . $theme['name'], 0);
if (!get_option("__templately_stylesheet")) {
add_option("__templately_stylesheet", $stylesheet, '', 'no');
}
$plugin_status = Installer::get_instance()->install_and_activate_theme($theme['stylesheet']);
if (!$plugin_status['success']) {
$this->sse_message([
'action' => 'updateLog',
'status' => 'error',
'message' => "Failed to activate theme: " . $theme['name'],
'type' => "theme",
'progress' => 0
]);
$result = [
'success' => false,
'name' => $theme['name'],
'slug' => $theme['stylesheet'],
'message' => $plugin_status['message'] ?? ''
];
} else {
// do_action('after_theme_activation', $theme); // Trigger action after theme activation
$this->sse_message([
'action' => 'updateLog',
'status' => 'complete',
'message' => "Activated theme: " . $theme['name'],
'type' => "theme",
'progress' => 100
]);
$result = [
'success' => true,
'name' => $theme['name'],
'slug' => $theme['stylesheet'],
'message' => $plugin_status['message'] ?? ''
];
$progress['theme_dependency'] = true;
}
}
return $result;
});
return $results;
}
}