%PDF- %PDF-
Direktori : /var/www/knwn/wp-content/plugins/wpsynchro/includes/Files/ |
Current File : /var/www/knwn/wp-content/plugins/wpsynchro/includes/Files/PopulateListHandler.php |
<?php /** * Class for populating section file lists * @since 1.0.3 */ namespace WPSynchro\Files; use WPSynchro\Files\SyncList; use WPSynchro\Installation; use WPSynchro\Job; use WPSynchro\CommonFunctions; use WPSynchro\Logger\LoggerTrait; class PopulateListHandler { // Traits use LoggerTrait; // Constants const STATUS_EVERY_X_REQUEST = 3; // Data objects public $job = null; public $installation = null; public $sync_list = null; public $timer = null; /** * Constructor * @since 1.0.3 */ public function __construct() { } /** * Initialize class * @since 1.0.3 */ public function init(SyncList &$sync_list, Installation &$installation, Job &$job) { $this->sync_list = $sync_list; $this->installation = $installation; $this->job = $job; } /** * Populate File List * @since 1.0.3 */ public function populateFilelist() { // Timer global $wpsynchro_container; $this->timer = $wpsynchro_container->get('class.SyncTimerList'); /** * Validate file sections (for overlapping sections etc.) */ if (!$this->job->files_population_sections_validated) { $this->job->files_population_sections_validated = true; if (!$this->validateFileSections()) { return; } } /** * Run populate on both sites */ // Find the current section we are working on $current_section = null; foreach ($this->job->files_sections as $key => &$section) { if (!$section->source_files_population_complete) { $current_section = $section; break; } if (!$section->target_files_population_complete) { $current_section = $section; break; } } // If all sections are done for both source and target if ($current_section == null) { $this->job->files_population_source = true; $this->job->files_population_target = true; $this->job->request_full_timeframe = true; return; } // Do source population if (!$current_section->source_files_population_complete) { $current_section->source_request_count++; $this->doSectionPopulate( 'source', $current_section, $current_section->source_request_count, $current_section->source_is_remote_complete ); } // Do target populate if (!$current_section->target_files_population_complete) { $current_section->target_request_count++; $this->doSectionPopulate( 'target', $current_section, $current_section->target_request_count, $current_section->target_is_remote_complete ); } $this->job->request_full_timeframe = true; return; } /** * Figure out if we are doing status request or just kick the remote into action * @since 1.6.0 */ public function doSectionPopulate($type, $section, $request_count, $is_remote_complete) { $do_status_request = false; if ( $is_remote_complete === true || $request_count % self::STATUS_EVERY_X_REQUEST == 0 ) { $do_status_request = true; } // Do either status request or normal kick-into-action request $get_file_data_timer = $this->timer->startTimer('filessync', 'population', 'servicecall'); $this->log('INFO', sprintf( 'Call file populate on %s doing status request: %s and remote completed: %s on section with id: %s', $type, $do_status_request ? "yes" : "no", $is_remote_complete ? "yes" : "no", $section->id )); if ($do_status_request) { $this->updateSectionStatus($type, $section); } else { $this->triggerRemoteFilePopulation($type, $section); } $this->log('INFO', sprintf( 'Got response from remote file population in %f seconds', $this->timer->getElapsedTimeToNow($get_file_data_timer) )); // Wait a bit, to not hammer the remote constantly if still running. // If we are just doing status requests (when population is done), just smash away if (!$do_status_request) { sleep(1); } } /** * Validate file sections before starting population * @since 1.2.0 */ public function validateFileSections() { $valid = true; /** * Check if there is overlapping full paths */ $fullpath_sections = []; foreach ($this->job->files_sections as $key => $section) { foreach ($section->temp_locations_in_basepath as $basepath => $notused) { $fullpath_sections[] = trailingslashit(trailingslashit($section->source_basepath) . trim($basepath, '/')); } } foreach ($fullpath_sections as $fullpath1) { foreach ($fullpath_sections as $fullpath2) { if (substr($fullpath1, 0, strlen($fullpath2)) === $fullpath2 && $fullpath1 != $fullpath2) { $errormsg = sprintf(__('Found overlapping filepaths to synchronize: %s and %s. Please remove one of them before starting again.', 'wpsynchro'), $fullpath2, $fullpath1); $this->job->errors[] = $errormsg; $this->log('CRITICAL', $errormsg); $valid = false; break; } } } return $valid; } /** * Handle the population of a section with a type, that can be source or target * @since 1.2.0 */ public function updateSectionStatus($type, $section) { // Determine URL if ($type == 'source') { $url = $this->job->from_rest_base_url . 'wpsynchro/v1/populatefileliststatus/'; } else { $url = $this->job->to_rest_base_url . 'wpsynchro/v1/populatefileliststatus/'; } $response = $this->getFileDataFromSource($type, $section, $url, true); if (!isset($response->state)) { return; } // Set files found if ($type == 'source') { $section->files_population_source_count = $response->state->files_found; } else { $section->files_population_target_count = $response->state->files_found; } // Check if REST service returned a complete state or is still populating data if ($response->state->state == 'completed') { if ($type == 'source') { $section->source_is_remote_complete = true; } else { $section->target_is_remote_complete = true; } } // If there is files if (isset($response->filelist)) { // If set is empty, just set completed on this section if (count($response->filelist) == 0) { if ($type == 'source' && $section->source_is_remote_complete) { $this->log('DEBUG', 'No more files from source - Setting source file population to completed'); $section->source_files_population_complete = true; } elseif ($type == 'target' && $section->target_is_remote_complete) { { $this->log('DEBUG', 'No more files from target - Setting target file population to completed'); $section->target_files_population_complete = true; } } } else { // If not empty, handle the file list and add to database $sql_insert_result = $this->sync_list->addUpdateFilelistFromPopulation($type, $section->id, $response->filelist); if ($sql_insert_result) { $this->log('INFO', 'Populated section ' . $section->name . ' on ' . $type . ' with ' . count($response->filelist) . ' files'); } } } } /** * Handle the population of a section with a type, that can be source or target * @since 1.2.0 */ public function triggerRemoteFilePopulation($type, $section) { // Determine URL if ($type == 'source') { $url = $this->job->from_rest_base_url . 'wpsynchro/v1/populatefilelist/'; } else { $url = $this->job->to_rest_base_url . 'wpsynchro/v1/populatefilelist/'; } // Call the remote url $this->getFileDataFromSource($type, $section, $url, false); } /** * Get file list data from source installation * @since 1.0.3 */ public function getFileDataFromSource($type, $section, $url, $blocking) { global $wpsynchro_container; // Gather exclusions $exclusions = []; if (strlen(trim($this->installation->files_exclude_files_match)) > 0) { $exclusions = array_merge($exclusions, explode(',', $this->installation->files_exclude_files_match)); } if (strlen(trim($section->exclusions)) > 0) { $exclusions = array_merge($exclusions, explode(',', $section->exclusions)); } $exclusions = array_merge($exclusions, $this->getFilePopulationExclusions($type)); // To prevent moving WP Synchro plugin, uploads folder and the likes // Do some fixy fixy magic on the paths $common = new CommonFunctions(); array_walk($exclusions, function (&$value, $key) use ($common) { $value = trim($value, ' '); $value = $common->fixPath($value); }); // Genereate request $body = new \stdClass(); $body->exclusions = $exclusions; $body->section = $section; $body->type = $type; $body->allotted_time = $this->timer->getRemainingSyncTime(); $body->requestid = $this->job->id; // Get remote transfer object $remotetransport = $wpsynchro_container->get('class.RemoteTransfer'); $remotetransport->init(); $remotetransport->setUrl($url); $remotetransport->setDataObject($body); // Set if blocking or not if (!$blocking) { $remotetransport->setNonBlocking(); } $remote_filedata_result = $remotetransport->remotePOST(); // If not blocking, we just return true if (!$blocking) { return true; } // If blocking, we return the data. if ($remote_filedata_result->isSuccess()) { $result_body = $remote_filedata_result->getBody(); if (is_object($result_body)) { return $result_body; } else { $this->job->errors[] = __('Data returned during file population is invalid, which means we can not continue the synchronization.', 'wpsynchro'); return false; } } else { $this->job->errors[] = __('File population failed, which means we can not continue the synchronization.', 'wpsynchro'); return false; } } /** * Get file exclusion paths * @since 1.2.0 */ public function getFilePopulationExclusions($type) { $exclusion_arr = []; // Add wp-admin, wp-includes if ($type == 'source') { $files_wp_dir_b1 = basename($this->job->from_files_wp_dir); } else { $files_wp_dir_b1 = basename($this->job->to_files_wp_dir); } $exclusion_arr[] = $files_wp_dir_b1 . '/wp-admin'; $exclusion_arr[] = $files_wp_dir_b1 . '/wp-includes'; // Add plugin location if ($type == 'source') { $plugin_basename = basename($this->job->from_files_plugins_dir); $wpcontent_basename = basename($this->job->from_files_wp_content_dir); } else { $plugin_basename = basename($this->job->to_files_plugins_dir); $wpcontent_basename = basename($this->job->to_files_wp_content_dir); } $exclusion_arr[] = $wpcontent_basename . '/' . $plugin_basename . '/wpsynchro'; // Add uploads location if ($type == 'source') { $uploads_basename = basename($this->job->from_files_uploads_dir); } else { $uploads_basename = basename($this->job->to_files_uploads_dir); } $exclusion_arr[] = $wpcontent_basename . '/' . $uploads_basename . '/wpsynchro'; // Add .htaccess in web root, to prevent troubles with https redirects and other stuff if ($type == 'source') { $exclusion_arr[] = basename($this->job->from_files_home_dir) . '/.htaccess'; } else { $exclusion_arr[] = basename($this->job->to_files_home_dir) . '/.htaccess'; } // Add system generated source exclusions if ($type === 'source') { $exclusion_arr = array_merge($exclusion_arr, $this->job->files_population_source_excludes); } else { $exclusion_arr = array_merge($exclusion_arr, $this->job->files_population_target_excludes); } return $exclusion_arr; } }