/** * Fixes environment once event occurs * * @param W3_Config $config * @param string $event * @param W3_Config|null $old_config * @throws SelfTestExceptions **/ public function fix_on_event($config, $event, $old_config = null) { if ($config->get_boolean('cdn.enabled') && !w3_is_cdn_mirror($config->get_string('cdn.engine'))) { if ($old_config != null && $config->get_integer('cdn.queue.interval') != $old_config->get_integer('cdn.queue.interval')) { $this->unschedule_queue_process(); } if (!wp_next_scheduled('w3_cdn_cron_queue_process')) { wp_schedule_event(current_time('timestamp'), 'w3_cdn_cron_queue_process', 'w3_cdn_cron_queue_process'); } } else { $this->unschedule_queue_process(); } if ($config->get_boolean('cdn.enabled') && $config->get_boolean('cdn.autoupload.enabled') && !w3_is_cdn_mirror($config->get_string('cdn.engine'))) { if ($old_config != null && $config->get_integer('cdn.autoupload.interval') != $old_config->get_integer('cdn.autoupload.interval')) { $this->unschedule_upload(); } if (!wp_next_scheduled('w3_cdn_cron_upload')) { wp_schedule_event(current_time('timestamp'), 'w3_cdn_cron_upload', 'w3_cdn_cron_upload'); } } else { $this->unschedule_upload(); } $exs = new SelfTestExceptions(); if ($config->get_boolean('cdn.enabled')) { try { $this->table_create($event == 'activate'); } catch (Exception $ex) { $exs->push($ex); } } if (count($exs->exceptions()) > 0) { throw $exs; } }
/** * Fixes environment after plugin deactivation * @throws SelfTestExceptions * @return array */ public function fix_after_deactivation() { $exs = new SelfTestExceptions(); try { $this->delete_addin(); } catch (FilesystemOperationException $ex) { $exs->push($ex); } $this->unschedule(); if (count($exs->exceptions()) > 0) { throw $exs; } }
/** * Fixes environment after plugin deactivation * @param W3_Config $config * @throws SelfTestExceptions */ public function fix_after_deactivation($config) { $exs = new SelfTestExceptions(); // call plugin-related handlers foreach ($this->get_handlers($config) as $h) { try { $h->fix_after_deactivation(); } catch (SelfTestExceptions $ex) { $exs->push($ex); } } if (count($exs->exceptions()) > 0) { throw $exs; } }
/** * Writes directives to WP .htaccess * * @param W3_Config $config * @param SelfTestExceptions $exs * @throws FilesystemOperationException with S/FTP form if it can't get the required filesystem credentials * @throws FileOperationException */ private function rules_core_add($config, $exs) { $path = w3_get_pgcache_rules_core_path(); if ($path === false) { return; } $original_data = @file_get_contents($path); if ($original_data === false) { $original_data = ''; } $data = $original_data; $new_data = w3_erase_rules($data, W3TC_MARKER_BEGIN_PGCACHE_LEGACY, W3TC_MARKER_END_PGCACHE_LEGACY); $has_legacy = strlen($new_data) < strlen($data); $data = $new_data; $new_data = w3_erase_rules($data, W3TC_MARKER_BEGIN_PGCACHE_WPSC, W3TC_MARKER_END_PGCACHE_WPSC); $has_wpsc = strlen($new_data) < strlen($data); $data = $new_data; $rules = $this->rules_core_generate($config); $rules_missing = strstr(w3_clean_rules($data), w3_clean_rules($rules)) === false; if (!$has_legacy && !$has_wpsc && !$rules_missing) { return; } // modification of file not required $replace_start = strpos($data, W3TC_MARKER_BEGIN_PGCACHE_CORE); $replace_end = strpos($data, W3TC_MARKER_END_PGCACHE_CORE); if ($replace_start !== false && $replace_end !== false && $replace_start < $replace_end) { $replace_length = $replace_end - $replace_start + strlen(W3TC_MARKER_END_PGCACHE_CORE) + 1; } else { $replace_start = false; $replace_length = 0; $search = array(W3TC_MARKER_BEGIN_BROWSERCACHE_NO404WP => 0, W3TC_MARKER_BEGIN_WORDPRESS => 0, W3TC_MARKER_END_MINIFY_CORE => strlen(W3TC_MARKER_END_MINIFY_CORE) + 1, W3TC_MARKER_END_BROWSERCACHE_CACHE => strlen(W3TC_MARKER_END_BROWSERCACHE_CACHE) + 1, W3TC_MARKER_END_PGCACHE_CACHE => strlen(W3TC_MARKER_END_PGCACHE_CACHE) + 1, W3TC_MARKER_END_MINIFY_CACHE => strlen(W3TC_MARKER_END_MINIFY_CACHE) + 1); foreach ($search as $string => $length) { $replace_start = strpos($data, $string); if ($replace_start !== false) { $replace_start += $length; break; } } } if ($replace_start !== false) { $data = w3_trim_rules(substr_replace($data, $rules, $replace_start, $replace_length)); } else { $data = w3_trim_rules($data . $rules); } try { w3_wp_write_to_file($path, $data); } catch (FilesystemOperationException $ex) { if ($has_legacy) { $exs->push(new FilesystemModifyException($ex->getMessage(), $ex->credentials_form(), sprintf(__('Edit file <strong>%s</strong> and remove all lines between and including <strong> %s</strong> and <strong>%s</strong> markers.', 'w3-total-cache'), $path, W3TC_MARKER_BEGIN_PGCACHE_LEGACY, W3TC_MARKER_END_PGCACHE_LEGACY), $path)); } if ($has_wpsc) { $exs->push(new FilesystemModifyException($ex->getMessage(), $ex->credentials_form(), sprintf(__('Edit file <strong>%s</strong> and remove all lines between and including <strong>%s</strong> and <strong>%s</strong> markers.', 'w3-total-cache'), $path, W3TC_MARKER_BEGIN_PGCACHE_WPSC, W3TC_MARKER_END_PGCACHE_WPSC), $path)); } if ($rules_missing) { if ($replace_start !== false) { $exs->push(new FilesystemModifyException($ex->getMessage(), $ex->credentials_form(), sprintf(__('Edit file <strong>%s</strong> and replace all lines between and including <strong>%s</strong> and <strong>%s</strong> markers with:', 'w3-total-cache'), $path, W3TC_MARKER_BEGIN_PGCACHE_CORE, W3TC_MARKER_END_PGCACHE_CORE), $path, $rules)); } else { $exs->push(new FilesystemModifyException($ex->getMessage(), $ex->credentials_form(), sprintf(__('Edit file <strong>%s</strong> and add the following rules above the WordPress directives:'), $path), $path, $rules)); } } } }
/** * Minifiers availability error handling * * @param W3_Config $config * @param SelfTestExceptions $exs */ private function verify_engine_working($config, $exs) { $minifiers_errors = array(); if ($config->get_string('minify.js.engine') == 'yuijs') { $path_java = $config->get_string('minify.yuijs.path.java'); $path_jar = $config->get_string('minify.yuijs.path.jar'); if (!file_exists($path_java)) { $minifiers_errors[] = sprintf('YUI Compressor (JS): JAVA executable path was not found. The default minifier JSMin will be used instead.'); } elseif (!file_exists($path_jar)) { $minifiers_errors[] = sprintf('YUI Compressor (JS): JAR file path was not found. The default minifier JSMin will be used instead.'); } } if ($config->get_string('minify.css.engine') == 'yuicss') { $path_java = $config->get_string('minify.yuicss.path.java'); $path_jar = $config->get_string('minify.yuicss.path.jar'); if (!file_exists($path_java)) { $minifiers_errors[] = sprintf('YUI Compressor (CSS): JAVA executable path was not found. The default CSS minifier will be used instead.'); } elseif (!file_exists($path_jar)) { $minifiers_errors[] = sprintf('YUI Compressor (CSS): JAR file path was not found. The default CSS minifier will be used instead.'); } } if ($config->get_string('minify.js.engine') == 'ccjs') { $path_java = $config->get_string('minify.ccjs.path.java'); $path_jar = $config->get_string('minify.ccjs.path.jar'); if (!file_exists($path_java)) { $minifiers_errors[] = sprintf('Closure Compiler: JAVA executable path was not found. The default minifier JSMin will be used instead.'); } elseif (!file_exists($path_jar)) { $minifiers_errors[] = sprintf('Closure Compiler: JAR file path was not found. The default minifier JSMin will be used instead.'); } } if (count($minifiers_errors)) { $minify_error = 'The following minifiers cannot be found or are no longer working:</p><ul>'; foreach ($minifiers_errors as $minifiers_error) { $minify_error .= '<li>' . $minifiers_error . '</li>'; } $minify_error .= '</ul><p>This message will automatically disappear once the issue is resolved.'; $exs->push(new SelfTestFailedException($minify_error)); } }
/** * @param SelfTestExceptions $exs * @param string $path * @param string $start * @param string $end */ function w3_remove_rules($exs, $path, $start, $end) { if (!file_exists($path)) { return; } $data = @file_get_contents($path); if ($data === false) { return; } if (strstr($data, $start) === false) { return; } $data = w3_erase_rules($data, $start, $end); try { w3_wp_write_to_file($path, $data); } catch (FilesystemOperationException $ex) { $exs->push(new FilesystemModifyException($ex->getMessage(), $ex->credentials_form(), sprintf(__('Edit file <strong>%s</strong> and remove all lines between and including <strong>%s</strong> and <strong>%s</strong> markers.', 'w3-total-cache'), $path, $start, $end), $path)); } }
/** * Check config cache is in sync with config * @param W3_Config $config * @param SelfTestExceptions $exs **/ private function notify_config_cache_not_writeable($config, $exs) { try { $config->validate_cache_actual(); } catch (Exception $ex) { // we could just create cache folder, so try again $config->load(true); try { $config->validate_cache_actual(); } catch (Exception $ex) { $exs->push(new SelfTestFailedException('<strong>W3 Total Cache Error:</strong> ' . $ex->getMessage())); } } }
/** * Used to display SelfTestExceptions in UI * @param SelfTestExceptions $exs * @return array(before_errors = [], required_changes =>, later_errors => []) **/ function w3_parse_selftest_exceptions($exs) { $exceptions = $exs->exceptions(); $commands = ''; $required_changes = ''; $before_errors = array(); $later_errors = array(); $operation_error_already_shown = false; foreach ($exceptions as $ex) { if ($ex instanceof FilesystemOperationException) { if (!$operation_error_already_shown) { $m = $ex->getMessage(); if (strlen($m) > 0) { $before_errors[] = $m; // if multiple operations failed when // they tried to fix environment - show only first // otherwise can duplication information about // absense of permissions $operation_error_already_shown = true; } if ($ex instanceof FilesystemWriteException) { $required_changes .= sprintf(__('Create the <strong>%s</strong> file and paste the following text into it: <textarea>%s</textarea> <br />', 'w3-total-cache'), $ex->filename(), esc_textarea($ex->file_contents())); } else { if ($ex instanceof FilesystemModifyException) { $modification_content = $ex->file_contents(); if (strlen($modification_content) > 0) { $modification_content = '<textarea style="height: 100px; width: 100%;">' . esc_textarea($modification_content) . '</textarea>'; } $required_changes .= $ex->modification_description() . $modification_content . '<br />'; } else { if ($ex instanceof FilesystemCopyException) { $commands .= 'cp ' . $ex->source_filename() . ' ' . $ex->destination_filename() . '<br />'; } else { if ($ex instanceof FilesystemMkdirException) { $commands .= 'mkdir ' . $ex->folder() . '<br />'; $commands .= 'chmod 777 ' . $ex->folder() . '<br />'; } else { if ($ex instanceof FilesystemRmException) { $commands .= 'rm ' . $ex->filename() . '<br />'; } else { if ($ex instanceof FilesystemRmdirException) { $commands .= 'rm -rf ' . $ex->folder() . '<br />'; } else { if ($ex instanceof FilesystemChmodException) { $commands .= 'chmod 777 ' . $ex->filename() . '<br />'; } } } } } } } } } else { if ($ex instanceof SelfTestFailedException) { $t = $ex->technical_message(); if (strlen($t) > 0) { $t = '<br />' . '<a class="w3tc_read_technical_info" href="#">' . __('Technical info', 'w3-total-cache') . '</a>' . '<div class="w3tc_technical_info" style="display: none">' . $t . '</div>'; } $later_errors[] = $ex->getMessage() . $t; } else { // unknown command $later_errors[] = $ex->getMessage(); } } } if (strlen($commands) > 0) { $required_changes .= __('Execute next commands in a shell:', 'w3-total-cache') . '<br><strong>' . $commands . '</strong>'; } return array('before_errors' => $before_errors, 'required_changes' => $required_changes, 'later_errors' => $later_errors); }