Changeset 3257611
- Timestamp:
- 03/18/2025 08:51:26 AM (13 months ago)
- Location:
- watchful
- Files:
-
- 14 added
- 20 edited
- 1 copied
-
tags/v2.0.3 (copied) (copied from watchful/trunk)
-
tags/v2.0.3/lib/Backup (added)
-
tags/v2.0.3/lib/Backup/ChunkedUploader.php (added)
-
tags/v2.0.3/lib/Backup/Processor.php (added)
-
tags/v2.0.3/lib/Backup/StateManager.php (added)
-
tags/v2.0.3/lib/Backup/Utils.php (added)
-
tags/v2.0.3/lib/Controller/Backups.php (modified) (3 diffs)
-
tags/v2.0.3/lib/Controller/Logs.php (modified) (3 diffs)
-
tags/v2.0.3/lib/Controller/Plugins.php (modified) (4 diffs)
-
tags/v2.0.3/lib/Controller/Themes.php (modified) (2 diffs)
-
tags/v2.0.3/lib/Helpers/BackupPluginHelper.php (modified) (5 diffs)
-
tags/v2.0.3/lib/Helpers/BackupPlugins/WatchfulBackupPlugin.php (added)
-
tags/v2.0.3/lib/Helpers/LockFactory.php (added)
-
tags/v2.0.3/lib/Helpers/Logger.php (modified) (7 diffs)
-
tags/v2.0.3/lib/Helpers/PluginManager.php (modified) (14 diffs)
-
tags/v2.0.3/lib/Helpers/ThemeUpdater.php (modified) (7 diffs)
-
tags/v2.0.3/readme.txt (modified) (2 diffs)
-
tags/v2.0.3/watchful.php (modified) (1 diff)
-
trunk/lib/Backup (added)
-
trunk/lib/Backup/ChunkedUploader.php (added)
-
trunk/lib/Backup/Processor.php (added)
-
trunk/lib/Backup/StateManager.php (added)
-
trunk/lib/Backup/Utils.php (added)
-
trunk/lib/Controller/Backups.php (modified) (3 diffs)
-
trunk/lib/Controller/Logs.php (modified) (3 diffs)
-
trunk/lib/Controller/Plugins.php (modified) (4 diffs)
-
trunk/lib/Controller/Themes.php (modified) (2 diffs)
-
trunk/lib/Helpers/BackupPluginHelper.php (modified) (5 diffs)
-
trunk/lib/Helpers/BackupPlugins/WatchfulBackupPlugin.php (added)
-
trunk/lib/Helpers/LockFactory.php (added)
-
trunk/lib/Helpers/Logger.php (modified) (7 diffs)
-
trunk/lib/Helpers/PluginManager.php (modified) (14 diffs)
-
trunk/lib/Helpers/ThemeUpdater.php (modified) (7 diffs)
-
trunk/readme.txt (modified) (2 diffs)
-
trunk/watchful.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
watchful/tags/v2.0.3/lib/Controller/Backups.php
r3123686 r3257611 20 20 use Watchful\Helpers\Authentification; 21 21 use Watchful\Helpers\BackupPluginHelper; 22 use Watchful\Helpers\BackupPlugins\WatchfulBackupPlugin; 22 23 use Watchful\Helpers\BackupPlugins\XClonerBackupPlugin; 23 24 use WP_REST_Request; … … 193 194 ) 194 195 ); 196 register_rest_route( 197 'watchful/v1', 198 '/backup/watchful', 199 array( 200 array( 201 'methods' => WP_REST_Server::CREATABLE, 202 'callback' => array($this, 'execute_watchful_backup'), 203 'permission_callback' => array('Watchful\Routes', 'authentification'), 204 'args' => Authentification::get_arguments(), 205 ), 206 ) 207 ); 208 register_rest_route( 209 'watchful/v1', 210 '/backup/watchful/step', 211 array( 212 array( 213 'methods' => WP_REST_Server::CREATABLE, 214 'callback' => array($this, 'step_watchful_backup'), 215 'permission_callback' => array('Watchful\Routes', 'authentification'), 216 'args' => array_merge( 217 Authentification::get_arguments(), 218 array( 219 'archive' => array( 220 'default' => null, 221 ), 222 'priority' => array( 223 'default' => null, 224 ), 225 ) 226 ), 227 ), 228 ) 229 ); 230 register_rest_route( 231 'watchful/v1', 232 '/backup/watchful/list', 233 array( 234 array( 235 'methods' => WP_REST_Server::READABLE, 236 'callback' => array($this, 'list_watchful_backup'), 237 'permission_callback' => array('Watchful\Routes', 'authentification'), 238 'args' => array_merge( 239 Authentification::get_arguments(), 240 array( 241 'limit' => array( 242 'default' => null, 243 ), 244 ) 245 ), 246 ), 247 ) 248 ); 249 register_rest_route( 250 'watchful/v1', 251 '/backup/watchful/data', 252 array( 253 array( 254 'methods' => WP_REST_Server::READABLE, 255 'callback' => array($this, 'data_watchful'), 256 'permission_callback' => array('Watchful\Routes', 'authentification'), 257 'args' => array_merge( 258 Authentification::get_arguments(), 259 array( 260 'limit' => array( 261 'default' => null, 262 ), 263 ) 264 ), 265 ), 266 ) 267 ); 195 268 } 196 269 … … 338 411 ]; 339 412 } 413 414 /** 415 * @throws Exception 416 */ 417 public function execute_watchful_backup() 418 { 419 return rest_ensure_response( 420 (new WatchfulBackupPlugin())->start_backup() 421 ); 422 } 423 424 /** 425 * Continues previously started backup process 426 * 427 * @param WP_REST_Request $request 428 * @return array 429 * @throws Exception 430 */ 431 public function step_watchful_backup(WP_REST_Request $request) 432 { 433 $body = json_decode($request->get_body(), true); 434 if (json_last_error() !== JSON_ERROR_NONE) { 435 throw new Exception('Cannot decode request body'); 436 } 437 438 return (new WatchfulBackupPlugin())->step_backup($body); 439 } 440 441 /** 442 * 443 * @param WP_REST_Request $request 444 * @return array 445 * @throws Exception 446 */ 447 public function list_watchful_backup() 448 { 449 return $this->backupPluginHelper->get_backup_list('watchful'); 450 } 451 452 453 /** 454 * @param WP_REST_Request $request 455 * @return array 456 * @throws Exception 457 */ 458 public function data_watchful() 459 { 460 return []; 461 } 340 462 } -
watchful/tags/v2.0.3/lib/Controller/Logs.php
r3243697 r3257611 4 4 5 5 use Watchful\Helpers\Logger; 6 use WP_REST_Request; 6 7 use WP_REST_Response; 7 8 use WP_REST_Server; … … 34 35 'permission_callback' => array('Watchful\Routes', 'authentification'), 35 36 ), 37 array( 38 'methods' => WP_REST_Server::DELETABLE, 39 'callback' => array($this, 'clear_logs'), 40 'permission_callback' => array('Watchful\Routes', 'authentification'), 41 ), 36 42 ) 37 43 ); … … 41 47 * @return WP_REST_Response 42 48 */ 43 public function get_logs( )49 public function get_logs(WP_REST_Request $request) 44 50 { 45 return new WP_REST_Response($this->logger->get_logs(), 200); 51 $channel = $request->get_param('channel'); 52 $lines = $request->get_param('lines') ?? 0; 53 54 return new WP_REST_Response($this->logger->get_logs($lines, $channel), 200); 55 } 56 57 /** 58 * @return WP_REST_Response 59 */ 60 public function clear_logs(WP_REST_Request $request) 61 { 62 $channel = $request->get_param('channel'); 63 64 return new WP_REST_Response($this->logger->clear_logs($channel), 200); 46 65 } 47 66 } -
watchful/tags/v2.0.3/lib/Controller/Plugins.php
r3123686 r3257611 166 166 $params['zip'], 167 167 $params['enable_maintenance_mode'], 168 $params['handle_shutdown'] 168 $params['handle_shutdown'], 169 $params['use_lock'] 169 170 ); 170 171 … … 179 180 'enable_maintenance_mode' => false, 180 181 'handle_shutdown' => false, 182 'use_lock' => false, 181 183 ); 182 184 … … 196 198 if (!empty($post_data) && !empty($post_data->handle_shutdown)) { 197 199 $params['handle_shutdown'] = (bool)$post_data->handle_shutdown; 200 } 201 202 if (!empty($post_data) && !empty($post_data->use_lock)) { 203 $params['use_lock'] = (bool)$post_data->use_lock; 198 204 } 199 205 } … … 219 225 $params['zip'], 220 226 $params['enable_maintenance_mode'], 221 $params['handle_shutdown'] 227 $params['handle_shutdown'], 228 $params['use_lock'] 222 229 ) 223 230 ); -
watchful/tags/v2.0.3/lib/Controller/Themes.php
r3238406 r3257611 99 99 } 100 100 101 private function parse_install_update_request_params(WP_REST_Request $request)102 {103 $params = array(104 'slug' => $request->get_param('slug'),105 'zip' => $request->get_param('zip'),106 'enable_maintenance_mode' => false,107 'handle_shutdown' => false,108 'new_version' => null109 );110 111 $body = $request->get_body();112 113 if (!empty($body)) {114 $post_data = json_decode($body);115 116 if (!empty($post_data) && !empty($post_data->package)) {117 $params['zip'] = $post_data->package;118 }119 120 if (!empty($post_data) && !empty($post_data->maintenance_mode)) {121 $params['enable_maintenance_mode'] = (bool)$post_data->maintenance_mode;122 }123 124 if (!empty($post_data) && !empty($post_data->handle_shutdown)) {125 $params['handle_shutdown'] = (bool)$post_data->handle_shutdown;126 }127 128 if (!empty($post_data) && !empty($post_data->new_version)) {129 $params['new_version'] = $post_data->new_version;130 }131 }132 133 return $params;134 }135 136 101 /** 137 102 * Update a theme from his slug. … … 158 123 $params['enable_maintenance_mode'], 159 124 $params['handle_shutdown'], 125 $params['use_lock'], 160 126 $params['new_version'] 161 127 ) 162 128 ); 129 } 130 131 private function parse_install_update_request_params(WP_REST_Request $request) 132 { 133 $params = array( 134 'slug' => $request->get_param('slug'), 135 'zip' => $request->get_param('zip'), 136 'enable_maintenance_mode' => false, 137 'handle_shutdown' => false, 138 'new_version' => null, 139 ); 140 141 $body = $request->get_body(); 142 143 if (!empty($body)) { 144 $post_data = json_decode($body); 145 146 if (!empty($post_data) && !empty($post_data->package)) { 147 $params['zip'] = $post_data->package; 148 } 149 150 if (!empty($post_data) && !empty($post_data->maintenance_mode)) { 151 $params['enable_maintenance_mode'] = (bool)$post_data->maintenance_mode; 152 } 153 154 if (!empty($post_data) && !empty($post_data->handle_shutdown)) { 155 $params['handle_shutdown'] = (bool)$post_data->handle_shutdown; 156 } 157 158 if (!empty($post_data) && !empty($post_data->use_lock)) { 159 $params['use_lock'] = (bool)$post_data->use_lock; 160 } 161 162 if (!empty($post_data) && !empty($post_data->new_version)) { 163 $params['new_version'] = $post_data->new_version; 164 } 165 } 166 167 return $params; 163 168 } 164 169 -
watchful/tags/v2.0.3/lib/Helpers/BackupPluginHelper.php
r3123686 r3257611 5 5 use Watchful\Helpers\BackupPlugins\Ai1wmBackupPlugin; 6 6 use Watchful\Helpers\BackupPlugins\AkeebaBackupPlugin; 7 use Watchful\Helpers\BackupPlugins\WatchfulBackupPlugin; 7 8 use Watchful\Helpers\BackupPlugins\XClonerBackupPlugin; 8 9 … … 16 17 private $xclonerBackupPluginHelper; 17 18 19 /** @var WatchfulBackupPlugin|null */ 20 private $watchfulBackupPluginHelper; 21 18 22 public function __construct() 19 23 { … … 21 25 $this->ai1wmBackupPluginHelper = self::has_active_backup_plugin('ai1wm') ? new Ai1wmBackupPlugin() : null; 22 26 $this->xclonerBackupPluginHelper = self::has_active_backup_plugin('xcloner') ? new XClonerBackupPlugin() : null; 27 $this->watchfulBackupPluginHelper = new WatchfulBackupPlugin(); 23 28 } 24 29 … … 82 87 }); 83 88 89 $watchful_profiles = array_filter($site_backups_data, function ($profile) { 90 return $profile->plugin === 'watchful'; 91 }); 92 84 93 if ($this->akeebaBackupPluginHelper !== null && !empty($akeeba_profiles)) { 85 94 foreach ($akeeba_profiles as $akeeba_profile) { … … 96 105 if ($this->xclonerBackupPluginHelper !== null && !empty($xcloner_profiles)) { 97 106 $last_backup_dates[] = $this->xclonerBackupPluginHelper->get_last_backup_date(); 107 } 108 109 if (!empty($watchful_profiles)) { 110 $last_backup_dates[] = $this->watchfulBackupPluginHelper->get_last_backup_date(); 98 111 } 99 112 -
watchful/tags/v2.0.3/lib/Helpers/Logger.php
r3243697 r3257611 10 10 const DEBUG = 100; 11 11 const INFO = 200; 12 const NOTICE = 250;13 12 /** 14 13 * Exceptional occurrences that are not errors … … 20 19 const ERROR = 400; 21 20 21 /** @var string */ 22 22 private $log_dir; 23 24 /** @var string */ 23 25 private $log_file; 26 27 /** @var null | string */ 28 private $channel; 24 29 private $max_file_size = 5242880; 25 30 private $max_backup_files = 5; … … 27 32 private $filesystem; 28 33 29 public function __construct( )34 public function __construct(?string $channel = null) 30 35 { 31 36 $this->log_dir = WATCHFUL_PLUGIN_CONTENT_DIR; … … 36 41 global $wp_filesystem; 37 42 $this->filesystem = $wp_filesystem; 43 $this->channel = $channel; 44 } 45 46 public function get_logs(?int $lines = 0, ?string $channel = null): array 47 { 48 if (!$this->filesystem->exists($this->log_file)) { 49 return []; 50 } 51 52 $content = $this->filesystem->get_contents_array($this->log_file); 53 if (!$content) { 54 return []; 55 } 56 57 $logs = array_slice($content, 2); 58 59 if ($lines > 0) { 60 $logs = array_slice($logs, -$lines); 61 } 62 63 $logs = array_values( 64 array_filter($logs) 65 ); 66 67 if (!empty($channel)) { 68 $logs = array_values(array_filter($logs, function ($log) use ($channel) { 69 $log = json_decode($log, true); 70 71 return isset($log['channel']) && $log['channel'] === $channel; 72 })); 73 } 74 75 $map = array_map(function ($log) { 76 $log = json_decode($log, true); 77 78 if (json_last_error() !== JSON_ERROR_NONE) { 79 return null; 80 } 81 82 if (!isset($log['message'], $log['context'], $log['level'], $log['ts'])) { 83 return null; 84 } 85 86 switch ($log['level']) { 87 case self::DEBUG: 88 $log['level'] = 'DEBUG'; 89 break; 90 case self::INFO: 91 $log['level'] = 'INFO'; 92 break; 93 case self::WARNING: 94 $log['level'] = 'WARNING'; 95 break; 96 case self::ERROR: 97 $log['level'] = 'ERROR'; 98 break; 99 default: 100 $log['level'] = 'UNKNOWN'; 101 break; 102 } 103 104 $log['ts'] = gmdate('Y-m-d H:i:s', $log['ts'] ?: 0); 105 106 return $log; 107 }, $logs); 108 109 return array_values( 110 array_filter($map) 111 ); 112 } 113 114 public function clear_logs(?string $channel = null): void 115 { 116 if (!$this->filesystem->exists($this->log_file)) { 117 return; 118 } 119 120 $content = $this->filesystem->get_contents_array($this->log_file); 121 if (!$content) { 122 return; 123 } 124 125 $this->filesystem->put_contents($this->log_file, "<?php\nif (!defined('ABSPATH')) { exit; }\n", FS_CHMOD_FILE); 126 127 if (empty($channel)) { 128 return; 129 } 130 131 $logs = array_slice($content, 2); 132 $logs = array_values( 133 array_filter($logs) 134 ); 135 136 $logs = array_values(array_filter($logs, function ($log) use ($channel) { 137 $log = json_decode($log, true); 138 139 return isset($log['channel']) && $log['channel'] === $channel; 140 })); 141 142 foreach ($logs as $log) { 143 $log = json_decode($log, true); 144 $this->log($log['message'], $log['context'], $log['level']); 145 } 38 146 } 39 147 … … 58 166 ]; 59 167 168 if (!empty($this->channel)) { 169 $log_entry['channel'] = $this->channel; 170 } 171 60 172 $encoded_entry = wp_json_encode($log_entry)."\n"; 61 173 … … 72 184 } 73 185 74 p ublicfunction check_log_size()186 private function check_log_size() 75 187 { 76 188 if ( … … 110 222 } 111 223 112 public function get_logs($lines = 0) 113 { 114 if (!$this->filesystem->exists($this->log_file)) { 115 return []; 116 } 117 118 $content = $this->filesystem->get_contents_array($this->log_file); 119 if (!$content) { 120 return []; 121 } 122 123 $logs = array_slice($content, 2); 124 125 if ($lines > 0) { 126 $logs = array_slice($logs, -$lines); 127 } 128 129 $logs = array_values( 130 array_filter($logs) 131 ); 132 133 $map = array_map(function ($log) { 134 $log = json_decode($log, true); 135 136 if (json_last_error() !== JSON_ERROR_NONE) { 137 return null; 138 } 139 140 if (!isset($log['message'], $log['context'], $log['level'], $log['ts'])) { 141 return null; 142 } 143 144 switch ($log['level']) { 145 case self::DEBUG: 146 $log['level'] = 'DEBUG'; 147 break; 148 case self::INFO: 149 $log['level'] = 'INFO'; 150 break; 151 case self::NOTICE: 152 $log['level'] = 'NOTICE'; 153 break; 154 case self::WARNING: 155 $log['level'] = 'WARNING'; 156 break; 157 case self::ERROR: 158 $log['level'] = 'ERROR'; 159 break; 160 default: 161 $log['level'] = 'UNKNOWN'; 162 break; 163 } 164 165 $log['ts'] = gmdate('Y-m-d H:i:s', $log['ts'] ?: 0); 166 167 return $log; 168 }, $logs); 169 170 return array_values( 171 array_filter($map) 172 ); 224 public function error($message, $context = []) 225 { 226 return $this->log($message, $context, self::ERROR); 227 } 228 229 public function warning($message, $context = []) 230 { 231 return $this->log($message, $context, self::WARNING); 232 } 233 234 public function info($message, $context = []) 235 { 236 return $this->log($message, $context); 237 } 238 239 public function debug($message, $context = []) 240 { 241 return $this->log($message, $context, self::DEBUG); 173 242 } 174 243 } -
watchful/tags/v2.0.3/lib/Helpers/PluginManager.php
r3243697 r3257611 11 11 class PluginManager 12 12 { 13 private const LOCK_NAME = 'install_update_plugin'; 13 14 private $logger; 15 private $lock_factory; 14 16 15 17 public function __construct() 16 18 { 17 $this->logger = new Logger(); 19 $this->logger = new Logger('plugin_manager'); 20 $this->lock_factory = new LockFactory($this->logger); 18 21 } 19 22 … … 31 34 $zip = null, 32 35 $enable_maintenance_mode = false, 33 $handle_shutdown = false 36 $handle_shutdown = false, 37 $use_lock = false 34 38 ) { 35 39 include_once ABSPATH.'wp-admin/includes/admin.php'; … … 47 51 ]); 48 52 53 $lock = false; 54 55 if ($use_lock) { 56 $lock = $this->lock_factory->acquire(self::LOCK_NAME); 57 } 58 59 if ($use_lock && !$lock) { 60 $this->logger->log('Plugin installation already in progress', [], Logger::WARNING); 61 throw new Exception('Plugin installation already in progress', 409); 62 } 63 49 64 if (!$slug && !$zip) { 50 65 $this->logger->log('parameter is missing. slug or zip required', [ … … 52 67 'zip' => $zip, 53 68 ], Logger::WARNING); 69 70 if ($use_lock) { 71 $this->lock_factory->release(self::LOCK_NAME); 72 } 73 54 74 throw new Exception('parameter is missing. slug or zip required', 400); 55 75 } … … 57 77 if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) { 58 78 $this->logger->log('file modification is disabled (DISALLOW_FILE_MODS)', [], Logger::WARNING); 79 80 if ($use_lock) { 81 $this->lock_factory->release(self::LOCK_NAME); 82 } 83 59 84 throw new Exception('file modification is disabled (DISALLOW_FILE_MODS)', 403); 60 85 } 86 61 87 62 88 if ($zip) { … … 77 103 ]); 78 104 79 $this->update_plugin($slug, $zip, $enable_maintenance_mode, $handle_shutdown); 105 if ($use_lock) { 106 $this->lock_factory->release(self::LOCK_NAME); 107 } 108 109 $this->update_plugin($slug, $zip, $enable_maintenance_mode, $handle_shutdown, $use_lock); 80 110 81 111 return; … … 137 167 138 168 throw new Exception($e->getMessage(), 500); 169 } finally { 170 if ($use_lock) { 171 $this->lock_factory->release(self::LOCK_NAME); 172 } 139 173 } 140 174 … … 279 313 $zip = null, 280 314 $enable_maintenance_mode = false, 281 $handle_shutdown = false 315 $handle_shutdown = false, 316 $use_lock = false 282 317 ) { 283 318 $this->logger->log('Received request to update plugin', [ … … 296 331 } 297 332 333 $lock = false; 334 335 if ($use_lock) { 336 $lock = $this->lock_factory->acquire(self::LOCK_NAME); 337 } 338 339 if ($use_lock && !$lock) { 340 $this->logger->log('Plugin update already in progress', [], Logger::WARNING); 341 $this->lock_factory->release(self::LOCK_NAME); 342 throw new Exception('Plugin update already in progress', 409); 343 } 344 298 345 if (empty($plugin_path) && empty($zip)) { 299 346 $this->logger->log('parameter is missing. plugin_path or zip required', [], Logger::WARNING); 347 348 if ($use_lock) { 349 $this->lock_factory->release(self::LOCK_NAME); 350 } 351 300 352 throw new Exception('parameter is missing. plugin_path or zip required', 400); 301 353 } … … 303 355 if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) { 304 356 $this->logger->log('file modification is disabled (DISALLOW_FILE_MODS)', [], Logger::WARNING); 357 358 if ($use_lock) { 359 $this->lock_factory->release(self::LOCK_NAME); 360 } 361 305 362 throw new Exception('file modification is disabled (DISALLOW_FILE_MODS)', 403); 306 363 } … … 333 390 'current_version' => phpversion(), 334 391 ], Logger::ERROR); 392 393 if ($use_lock) { 394 $this->lock_factory->release(self::LOCK_NAME); 395 } 396 335 397 throw new Exception("The minimum required PHP version for this update is ".$min_php_version, 500); 336 398 } … … 375 437 $e->getMessage() 376 438 ); 439 } finally { 440 if ($use_lock) { 441 $this->lock_factory->release(self::LOCK_NAME); 442 } 377 443 } 378 444 … … 396 462 'plugin_path' => $plugin_path, 397 463 'error' => $skin->error->get_error_messages(), 398 'data' => $ result->get_all_error_data(),464 'data' => $skin->error->get_all_error_data(), 399 465 ], Logger::ERROR); 400 466 $this->handle_update_error( … … 482 548 } 483 549 484 throw new Exception($error_message, $error_code, [550 throw new Exception($error_message, (int)$error_code, [ 485 551 'plugin' => $slug, 486 552 'is_installed' => $this->is_installed($slug), -
watchful/tags/v2.0.3/lib/Helpers/ThemeUpdater.php
r3243697 r3257611 10 10 class ThemeUpdater 11 11 { 12 private const LOCK_NAME = 'install_update_theme'; 12 13 private $logger; 14 private $lock_factory; 13 15 14 16 public function __construct() 15 17 { 16 $this->logger = new Logger(); 18 $this->logger = new Logger('theme_updater'); 19 $this->lock_factory = new LockFactory($this->logger); 17 20 } 18 21 … … 31 34 $enable_maintenance_mode = false, 32 35 $handle_shutdown = false, 36 $use_lock = false, 33 37 $new_version = null 34 38 ) { … … 49 53 ]); 50 54 55 $lock = false; 56 57 if ($use_lock) { 58 $lock = $this->lock_factory->acquire(self::LOCK_NAME); 59 } 60 61 if ($use_lock && !$lock) { 62 $this->logger->log('Could not acquire lock', [ 63 'lock_name' => self::LOCK_NAME, 64 ], Logger::WARNING); 65 throw new Exception('Theme update is already in progress', 409); 66 } 67 51 68 if (empty($slug) && empty($zip)) { 52 69 $this->logger->log('parameter is missing. slug required or zip', [ … … 54 71 'zip' => $zip, 55 72 ], Logger::WARNING); 73 74 if ($use_lock) { 75 $this->lock_factory->release(self::LOCK_NAME); 76 } 77 56 78 throw new Exception('parameter is missing. slug required or zip', 400); 57 79 } … … 59 81 if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) { 60 82 $this->logger->log('file modification is disabled (DISALLOW_FILE_MODS)', [], Logger::WARNING); 83 84 if ($use_lock) { 85 $this->lock_factory->release(self::LOCK_NAME); 86 } 87 61 88 throw new Exception('file modification is disabled (DISALLOW_FILE_MODS)', 403); 62 89 } … … 91 118 'min_php_version' => $min_php_version, 92 119 ], Logger::WARNING); 120 121 if ($use_lock) { 122 $this->lock_factory->release(self::LOCK_NAME); 123 } 124 93 125 throw new Exception("The minimum required PHP version for this update is ".$min_php_version, 500); 94 126 } … … 128 160 $e->getMessage() 129 161 ); 162 } finally { 163 if ($use_lock) { 164 $this->lock_factory->release(self::LOCK_NAME); 165 } 130 166 } 131 167 -
watchful/tags/v2.0.3/readme.txt
r3243697 r3257611 2 2 Contributors: watchful 3 3 Tags: manage multiple sites, Wordpress Dashboard, backup, WordPress manager, WordPress management, site management, watchful, remote administration, multiple wordpress 4 Requires at least: 4. 44 Requires at least: 4.6 5 5 Tested up to: 6.7.2 6 Requires PHP: 5.66 Requires PHP: 7.2 7 7 Stable tag: 1.5.0 8 8 License: GPLv2 or later … … 83 83 84 84 == Changelog == 85 = v2.0.3 = 86 * Add logs to backup processor class 87 * ignore backup folders from other vendors 88 89 = v2.0.2 = 90 * Add a lock manager to prevent multiple update / install processes at the same time 91 92 = v2.0.1 = 93 * Filter DB tables to backup on WP related tables 94 95 = v2.0.0 = 96 * Change minimum PHP version to 7.2 97 * Implement site backups 98 85 99 = v1.8.2 = 86 100 * Add logs to update process to improve debug -
watchful/tags/v2.0.3/watchful.php
r3243697 r3257611 4 4 * Plugin URI: https://app.watchful.net 5 5 * Description: Remote Website Management Plugin by Watchful 6 * Version: 1.8.26 * Version: 2.0.3 7 7 * Author: watchful 8 8 * Author URI: https://watchful.net -
watchful/trunk/lib/Controller/Backups.php
r3123686 r3257611 20 20 use Watchful\Helpers\Authentification; 21 21 use Watchful\Helpers\BackupPluginHelper; 22 use Watchful\Helpers\BackupPlugins\WatchfulBackupPlugin; 22 23 use Watchful\Helpers\BackupPlugins\XClonerBackupPlugin; 23 24 use WP_REST_Request; … … 193 194 ) 194 195 ); 196 register_rest_route( 197 'watchful/v1', 198 '/backup/watchful', 199 array( 200 array( 201 'methods' => WP_REST_Server::CREATABLE, 202 'callback' => array($this, 'execute_watchful_backup'), 203 'permission_callback' => array('Watchful\Routes', 'authentification'), 204 'args' => Authentification::get_arguments(), 205 ), 206 ) 207 ); 208 register_rest_route( 209 'watchful/v1', 210 '/backup/watchful/step', 211 array( 212 array( 213 'methods' => WP_REST_Server::CREATABLE, 214 'callback' => array($this, 'step_watchful_backup'), 215 'permission_callback' => array('Watchful\Routes', 'authentification'), 216 'args' => array_merge( 217 Authentification::get_arguments(), 218 array( 219 'archive' => array( 220 'default' => null, 221 ), 222 'priority' => array( 223 'default' => null, 224 ), 225 ) 226 ), 227 ), 228 ) 229 ); 230 register_rest_route( 231 'watchful/v1', 232 '/backup/watchful/list', 233 array( 234 array( 235 'methods' => WP_REST_Server::READABLE, 236 'callback' => array($this, 'list_watchful_backup'), 237 'permission_callback' => array('Watchful\Routes', 'authentification'), 238 'args' => array_merge( 239 Authentification::get_arguments(), 240 array( 241 'limit' => array( 242 'default' => null, 243 ), 244 ) 245 ), 246 ), 247 ) 248 ); 249 register_rest_route( 250 'watchful/v1', 251 '/backup/watchful/data', 252 array( 253 array( 254 'methods' => WP_REST_Server::READABLE, 255 'callback' => array($this, 'data_watchful'), 256 'permission_callback' => array('Watchful\Routes', 'authentification'), 257 'args' => array_merge( 258 Authentification::get_arguments(), 259 array( 260 'limit' => array( 261 'default' => null, 262 ), 263 ) 264 ), 265 ), 266 ) 267 ); 195 268 } 196 269 … … 338 411 ]; 339 412 } 413 414 /** 415 * @throws Exception 416 */ 417 public function execute_watchful_backup() 418 { 419 return rest_ensure_response( 420 (new WatchfulBackupPlugin())->start_backup() 421 ); 422 } 423 424 /** 425 * Continues previously started backup process 426 * 427 * @param WP_REST_Request $request 428 * @return array 429 * @throws Exception 430 */ 431 public function step_watchful_backup(WP_REST_Request $request) 432 { 433 $body = json_decode($request->get_body(), true); 434 if (json_last_error() !== JSON_ERROR_NONE) { 435 throw new Exception('Cannot decode request body'); 436 } 437 438 return (new WatchfulBackupPlugin())->step_backup($body); 439 } 440 441 /** 442 * 443 * @param WP_REST_Request $request 444 * @return array 445 * @throws Exception 446 */ 447 public function list_watchful_backup() 448 { 449 return $this->backupPluginHelper->get_backup_list('watchful'); 450 } 451 452 453 /** 454 * @param WP_REST_Request $request 455 * @return array 456 * @throws Exception 457 */ 458 public function data_watchful() 459 { 460 return []; 461 } 340 462 } -
watchful/trunk/lib/Controller/Logs.php
r3243697 r3257611 4 4 5 5 use Watchful\Helpers\Logger; 6 use WP_REST_Request; 6 7 use WP_REST_Response; 7 8 use WP_REST_Server; … … 34 35 'permission_callback' => array('Watchful\Routes', 'authentification'), 35 36 ), 37 array( 38 'methods' => WP_REST_Server::DELETABLE, 39 'callback' => array($this, 'clear_logs'), 40 'permission_callback' => array('Watchful\Routes', 'authentification'), 41 ), 36 42 ) 37 43 ); … … 41 47 * @return WP_REST_Response 42 48 */ 43 public function get_logs( )49 public function get_logs(WP_REST_Request $request) 44 50 { 45 return new WP_REST_Response($this->logger->get_logs(), 200); 51 $channel = $request->get_param('channel'); 52 $lines = $request->get_param('lines') ?? 0; 53 54 return new WP_REST_Response($this->logger->get_logs($lines, $channel), 200); 55 } 56 57 /** 58 * @return WP_REST_Response 59 */ 60 public function clear_logs(WP_REST_Request $request) 61 { 62 $channel = $request->get_param('channel'); 63 64 return new WP_REST_Response($this->logger->clear_logs($channel), 200); 46 65 } 47 66 } -
watchful/trunk/lib/Controller/Plugins.php
r3123686 r3257611 166 166 $params['zip'], 167 167 $params['enable_maintenance_mode'], 168 $params['handle_shutdown'] 168 $params['handle_shutdown'], 169 $params['use_lock'] 169 170 ); 170 171 … … 179 180 'enable_maintenance_mode' => false, 180 181 'handle_shutdown' => false, 182 'use_lock' => false, 181 183 ); 182 184 … … 196 198 if (!empty($post_data) && !empty($post_data->handle_shutdown)) { 197 199 $params['handle_shutdown'] = (bool)$post_data->handle_shutdown; 200 } 201 202 if (!empty($post_data) && !empty($post_data->use_lock)) { 203 $params['use_lock'] = (bool)$post_data->use_lock; 198 204 } 199 205 } … … 219 225 $params['zip'], 220 226 $params['enable_maintenance_mode'], 221 $params['handle_shutdown'] 227 $params['handle_shutdown'], 228 $params['use_lock'] 222 229 ) 223 230 ); -
watchful/trunk/lib/Controller/Themes.php
r3238406 r3257611 99 99 } 100 100 101 private function parse_install_update_request_params(WP_REST_Request $request)102 {103 $params = array(104 'slug' => $request->get_param('slug'),105 'zip' => $request->get_param('zip'),106 'enable_maintenance_mode' => false,107 'handle_shutdown' => false,108 'new_version' => null109 );110 111 $body = $request->get_body();112 113 if (!empty($body)) {114 $post_data = json_decode($body);115 116 if (!empty($post_data) && !empty($post_data->package)) {117 $params['zip'] = $post_data->package;118 }119 120 if (!empty($post_data) && !empty($post_data->maintenance_mode)) {121 $params['enable_maintenance_mode'] = (bool)$post_data->maintenance_mode;122 }123 124 if (!empty($post_data) && !empty($post_data->handle_shutdown)) {125 $params['handle_shutdown'] = (bool)$post_data->handle_shutdown;126 }127 128 if (!empty($post_data) && !empty($post_data->new_version)) {129 $params['new_version'] = $post_data->new_version;130 }131 }132 133 return $params;134 }135 136 101 /** 137 102 * Update a theme from his slug. … … 158 123 $params['enable_maintenance_mode'], 159 124 $params['handle_shutdown'], 125 $params['use_lock'], 160 126 $params['new_version'] 161 127 ) 162 128 ); 129 } 130 131 private function parse_install_update_request_params(WP_REST_Request $request) 132 { 133 $params = array( 134 'slug' => $request->get_param('slug'), 135 'zip' => $request->get_param('zip'), 136 'enable_maintenance_mode' => false, 137 'handle_shutdown' => false, 138 'new_version' => null, 139 ); 140 141 $body = $request->get_body(); 142 143 if (!empty($body)) { 144 $post_data = json_decode($body); 145 146 if (!empty($post_data) && !empty($post_data->package)) { 147 $params['zip'] = $post_data->package; 148 } 149 150 if (!empty($post_data) && !empty($post_data->maintenance_mode)) { 151 $params['enable_maintenance_mode'] = (bool)$post_data->maintenance_mode; 152 } 153 154 if (!empty($post_data) && !empty($post_data->handle_shutdown)) { 155 $params['handle_shutdown'] = (bool)$post_data->handle_shutdown; 156 } 157 158 if (!empty($post_data) && !empty($post_data->use_lock)) { 159 $params['use_lock'] = (bool)$post_data->use_lock; 160 } 161 162 if (!empty($post_data) && !empty($post_data->new_version)) { 163 $params['new_version'] = $post_data->new_version; 164 } 165 } 166 167 return $params; 163 168 } 164 169 -
watchful/trunk/lib/Helpers/BackupPluginHelper.php
r3123686 r3257611 5 5 use Watchful\Helpers\BackupPlugins\Ai1wmBackupPlugin; 6 6 use Watchful\Helpers\BackupPlugins\AkeebaBackupPlugin; 7 use Watchful\Helpers\BackupPlugins\WatchfulBackupPlugin; 7 8 use Watchful\Helpers\BackupPlugins\XClonerBackupPlugin; 8 9 … … 16 17 private $xclonerBackupPluginHelper; 17 18 19 /** @var WatchfulBackupPlugin|null */ 20 private $watchfulBackupPluginHelper; 21 18 22 public function __construct() 19 23 { … … 21 25 $this->ai1wmBackupPluginHelper = self::has_active_backup_plugin('ai1wm') ? new Ai1wmBackupPlugin() : null; 22 26 $this->xclonerBackupPluginHelper = self::has_active_backup_plugin('xcloner') ? new XClonerBackupPlugin() : null; 27 $this->watchfulBackupPluginHelper = new WatchfulBackupPlugin(); 23 28 } 24 29 … … 82 87 }); 83 88 89 $watchful_profiles = array_filter($site_backups_data, function ($profile) { 90 return $profile->plugin === 'watchful'; 91 }); 92 84 93 if ($this->akeebaBackupPluginHelper !== null && !empty($akeeba_profiles)) { 85 94 foreach ($akeeba_profiles as $akeeba_profile) { … … 96 105 if ($this->xclonerBackupPluginHelper !== null && !empty($xcloner_profiles)) { 97 106 $last_backup_dates[] = $this->xclonerBackupPluginHelper->get_last_backup_date(); 107 } 108 109 if (!empty($watchful_profiles)) { 110 $last_backup_dates[] = $this->watchfulBackupPluginHelper->get_last_backup_date(); 98 111 } 99 112 -
watchful/trunk/lib/Helpers/Logger.php
r3243697 r3257611 10 10 const DEBUG = 100; 11 11 const INFO = 200; 12 const NOTICE = 250;13 12 /** 14 13 * Exceptional occurrences that are not errors … … 20 19 const ERROR = 400; 21 20 21 /** @var string */ 22 22 private $log_dir; 23 24 /** @var string */ 23 25 private $log_file; 26 27 /** @var null | string */ 28 private $channel; 24 29 private $max_file_size = 5242880; 25 30 private $max_backup_files = 5; … … 27 32 private $filesystem; 28 33 29 public function __construct( )34 public function __construct(?string $channel = null) 30 35 { 31 36 $this->log_dir = WATCHFUL_PLUGIN_CONTENT_DIR; … … 36 41 global $wp_filesystem; 37 42 $this->filesystem = $wp_filesystem; 43 $this->channel = $channel; 44 } 45 46 public function get_logs(?int $lines = 0, ?string $channel = null): array 47 { 48 if (!$this->filesystem->exists($this->log_file)) { 49 return []; 50 } 51 52 $content = $this->filesystem->get_contents_array($this->log_file); 53 if (!$content) { 54 return []; 55 } 56 57 $logs = array_slice($content, 2); 58 59 if ($lines > 0) { 60 $logs = array_slice($logs, -$lines); 61 } 62 63 $logs = array_values( 64 array_filter($logs) 65 ); 66 67 if (!empty($channel)) { 68 $logs = array_values(array_filter($logs, function ($log) use ($channel) { 69 $log = json_decode($log, true); 70 71 return isset($log['channel']) && $log['channel'] === $channel; 72 })); 73 } 74 75 $map = array_map(function ($log) { 76 $log = json_decode($log, true); 77 78 if (json_last_error() !== JSON_ERROR_NONE) { 79 return null; 80 } 81 82 if (!isset($log['message'], $log['context'], $log['level'], $log['ts'])) { 83 return null; 84 } 85 86 switch ($log['level']) { 87 case self::DEBUG: 88 $log['level'] = 'DEBUG'; 89 break; 90 case self::INFO: 91 $log['level'] = 'INFO'; 92 break; 93 case self::WARNING: 94 $log['level'] = 'WARNING'; 95 break; 96 case self::ERROR: 97 $log['level'] = 'ERROR'; 98 break; 99 default: 100 $log['level'] = 'UNKNOWN'; 101 break; 102 } 103 104 $log['ts'] = gmdate('Y-m-d H:i:s', $log['ts'] ?: 0); 105 106 return $log; 107 }, $logs); 108 109 return array_values( 110 array_filter($map) 111 ); 112 } 113 114 public function clear_logs(?string $channel = null): void 115 { 116 if (!$this->filesystem->exists($this->log_file)) { 117 return; 118 } 119 120 $content = $this->filesystem->get_contents_array($this->log_file); 121 if (!$content) { 122 return; 123 } 124 125 $this->filesystem->put_contents($this->log_file, "<?php\nif (!defined('ABSPATH')) { exit; }\n", FS_CHMOD_FILE); 126 127 if (empty($channel)) { 128 return; 129 } 130 131 $logs = array_slice($content, 2); 132 $logs = array_values( 133 array_filter($logs) 134 ); 135 136 $logs = array_values(array_filter($logs, function ($log) use ($channel) { 137 $log = json_decode($log, true); 138 139 return isset($log['channel']) && $log['channel'] === $channel; 140 })); 141 142 foreach ($logs as $log) { 143 $log = json_decode($log, true); 144 $this->log($log['message'], $log['context'], $log['level']); 145 } 38 146 } 39 147 … … 58 166 ]; 59 167 168 if (!empty($this->channel)) { 169 $log_entry['channel'] = $this->channel; 170 } 171 60 172 $encoded_entry = wp_json_encode($log_entry)."\n"; 61 173 … … 72 184 } 73 185 74 p ublicfunction check_log_size()186 private function check_log_size() 75 187 { 76 188 if ( … … 110 222 } 111 223 112 public function get_logs($lines = 0) 113 { 114 if (!$this->filesystem->exists($this->log_file)) { 115 return []; 116 } 117 118 $content = $this->filesystem->get_contents_array($this->log_file); 119 if (!$content) { 120 return []; 121 } 122 123 $logs = array_slice($content, 2); 124 125 if ($lines > 0) { 126 $logs = array_slice($logs, -$lines); 127 } 128 129 $logs = array_values( 130 array_filter($logs) 131 ); 132 133 $map = array_map(function ($log) { 134 $log = json_decode($log, true); 135 136 if (json_last_error() !== JSON_ERROR_NONE) { 137 return null; 138 } 139 140 if (!isset($log['message'], $log['context'], $log['level'], $log['ts'])) { 141 return null; 142 } 143 144 switch ($log['level']) { 145 case self::DEBUG: 146 $log['level'] = 'DEBUG'; 147 break; 148 case self::INFO: 149 $log['level'] = 'INFO'; 150 break; 151 case self::NOTICE: 152 $log['level'] = 'NOTICE'; 153 break; 154 case self::WARNING: 155 $log['level'] = 'WARNING'; 156 break; 157 case self::ERROR: 158 $log['level'] = 'ERROR'; 159 break; 160 default: 161 $log['level'] = 'UNKNOWN'; 162 break; 163 } 164 165 $log['ts'] = gmdate('Y-m-d H:i:s', $log['ts'] ?: 0); 166 167 return $log; 168 }, $logs); 169 170 return array_values( 171 array_filter($map) 172 ); 224 public function error($message, $context = []) 225 { 226 return $this->log($message, $context, self::ERROR); 227 } 228 229 public function warning($message, $context = []) 230 { 231 return $this->log($message, $context, self::WARNING); 232 } 233 234 public function info($message, $context = []) 235 { 236 return $this->log($message, $context); 237 } 238 239 public function debug($message, $context = []) 240 { 241 return $this->log($message, $context, self::DEBUG); 173 242 } 174 243 } -
watchful/trunk/lib/Helpers/PluginManager.php
r3243697 r3257611 11 11 class PluginManager 12 12 { 13 private const LOCK_NAME = 'install_update_plugin'; 13 14 private $logger; 15 private $lock_factory; 14 16 15 17 public function __construct() 16 18 { 17 $this->logger = new Logger(); 19 $this->logger = new Logger('plugin_manager'); 20 $this->lock_factory = new LockFactory($this->logger); 18 21 } 19 22 … … 31 34 $zip = null, 32 35 $enable_maintenance_mode = false, 33 $handle_shutdown = false 36 $handle_shutdown = false, 37 $use_lock = false 34 38 ) { 35 39 include_once ABSPATH.'wp-admin/includes/admin.php'; … … 47 51 ]); 48 52 53 $lock = false; 54 55 if ($use_lock) { 56 $lock = $this->lock_factory->acquire(self::LOCK_NAME); 57 } 58 59 if ($use_lock && !$lock) { 60 $this->logger->log('Plugin installation already in progress', [], Logger::WARNING); 61 throw new Exception('Plugin installation already in progress', 409); 62 } 63 49 64 if (!$slug && !$zip) { 50 65 $this->logger->log('parameter is missing. slug or zip required', [ … … 52 67 'zip' => $zip, 53 68 ], Logger::WARNING); 69 70 if ($use_lock) { 71 $this->lock_factory->release(self::LOCK_NAME); 72 } 73 54 74 throw new Exception('parameter is missing. slug or zip required', 400); 55 75 } … … 57 77 if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) { 58 78 $this->logger->log('file modification is disabled (DISALLOW_FILE_MODS)', [], Logger::WARNING); 79 80 if ($use_lock) { 81 $this->lock_factory->release(self::LOCK_NAME); 82 } 83 59 84 throw new Exception('file modification is disabled (DISALLOW_FILE_MODS)', 403); 60 85 } 86 61 87 62 88 if ($zip) { … … 77 103 ]); 78 104 79 $this->update_plugin($slug, $zip, $enable_maintenance_mode, $handle_shutdown); 105 if ($use_lock) { 106 $this->lock_factory->release(self::LOCK_NAME); 107 } 108 109 $this->update_plugin($slug, $zip, $enable_maintenance_mode, $handle_shutdown, $use_lock); 80 110 81 111 return; … … 137 167 138 168 throw new Exception($e->getMessage(), 500); 169 } finally { 170 if ($use_lock) { 171 $this->lock_factory->release(self::LOCK_NAME); 172 } 139 173 } 140 174 … … 279 313 $zip = null, 280 314 $enable_maintenance_mode = false, 281 $handle_shutdown = false 315 $handle_shutdown = false, 316 $use_lock = false 282 317 ) { 283 318 $this->logger->log('Received request to update plugin', [ … … 296 331 } 297 332 333 $lock = false; 334 335 if ($use_lock) { 336 $lock = $this->lock_factory->acquire(self::LOCK_NAME); 337 } 338 339 if ($use_lock && !$lock) { 340 $this->logger->log('Plugin update already in progress', [], Logger::WARNING); 341 $this->lock_factory->release(self::LOCK_NAME); 342 throw new Exception('Plugin update already in progress', 409); 343 } 344 298 345 if (empty($plugin_path) && empty($zip)) { 299 346 $this->logger->log('parameter is missing. plugin_path or zip required', [], Logger::WARNING); 347 348 if ($use_lock) { 349 $this->lock_factory->release(self::LOCK_NAME); 350 } 351 300 352 throw new Exception('parameter is missing. plugin_path or zip required', 400); 301 353 } … … 303 355 if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) { 304 356 $this->logger->log('file modification is disabled (DISALLOW_FILE_MODS)', [], Logger::WARNING); 357 358 if ($use_lock) { 359 $this->lock_factory->release(self::LOCK_NAME); 360 } 361 305 362 throw new Exception('file modification is disabled (DISALLOW_FILE_MODS)', 403); 306 363 } … … 333 390 'current_version' => phpversion(), 334 391 ], Logger::ERROR); 392 393 if ($use_lock) { 394 $this->lock_factory->release(self::LOCK_NAME); 395 } 396 335 397 throw new Exception("The minimum required PHP version for this update is ".$min_php_version, 500); 336 398 } … … 375 437 $e->getMessage() 376 438 ); 439 } finally { 440 if ($use_lock) { 441 $this->lock_factory->release(self::LOCK_NAME); 442 } 377 443 } 378 444 … … 396 462 'plugin_path' => $plugin_path, 397 463 'error' => $skin->error->get_error_messages(), 398 'data' => $ result->get_all_error_data(),464 'data' => $skin->error->get_all_error_data(), 399 465 ], Logger::ERROR); 400 466 $this->handle_update_error( … … 482 548 } 483 549 484 throw new Exception($error_message, $error_code, [550 throw new Exception($error_message, (int)$error_code, [ 485 551 'plugin' => $slug, 486 552 'is_installed' => $this->is_installed($slug), -
watchful/trunk/lib/Helpers/ThemeUpdater.php
r3243697 r3257611 10 10 class ThemeUpdater 11 11 { 12 private const LOCK_NAME = 'install_update_theme'; 12 13 private $logger; 14 private $lock_factory; 13 15 14 16 public function __construct() 15 17 { 16 $this->logger = new Logger(); 18 $this->logger = new Logger('theme_updater'); 19 $this->lock_factory = new LockFactory($this->logger); 17 20 } 18 21 … … 31 34 $enable_maintenance_mode = false, 32 35 $handle_shutdown = false, 36 $use_lock = false, 33 37 $new_version = null 34 38 ) { … … 49 53 ]); 50 54 55 $lock = false; 56 57 if ($use_lock) { 58 $lock = $this->lock_factory->acquire(self::LOCK_NAME); 59 } 60 61 if ($use_lock && !$lock) { 62 $this->logger->log('Could not acquire lock', [ 63 'lock_name' => self::LOCK_NAME, 64 ], Logger::WARNING); 65 throw new Exception('Theme update is already in progress', 409); 66 } 67 51 68 if (empty($slug) && empty($zip)) { 52 69 $this->logger->log('parameter is missing. slug required or zip', [ … … 54 71 'zip' => $zip, 55 72 ], Logger::WARNING); 73 74 if ($use_lock) { 75 $this->lock_factory->release(self::LOCK_NAME); 76 } 77 56 78 throw new Exception('parameter is missing. slug required or zip', 400); 57 79 } … … 59 81 if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) { 60 82 $this->logger->log('file modification is disabled (DISALLOW_FILE_MODS)', [], Logger::WARNING); 83 84 if ($use_lock) { 85 $this->lock_factory->release(self::LOCK_NAME); 86 } 87 61 88 throw new Exception('file modification is disabled (DISALLOW_FILE_MODS)', 403); 62 89 } … … 91 118 'min_php_version' => $min_php_version, 92 119 ], Logger::WARNING); 120 121 if ($use_lock) { 122 $this->lock_factory->release(self::LOCK_NAME); 123 } 124 93 125 throw new Exception("The minimum required PHP version for this update is ".$min_php_version, 500); 94 126 } … … 128 160 $e->getMessage() 129 161 ); 162 } finally { 163 if ($use_lock) { 164 $this->lock_factory->release(self::LOCK_NAME); 165 } 130 166 } 131 167 -
watchful/trunk/readme.txt
r3243697 r3257611 2 2 Contributors: watchful 3 3 Tags: manage multiple sites, Wordpress Dashboard, backup, WordPress manager, WordPress management, site management, watchful, remote administration, multiple wordpress 4 Requires at least: 4. 44 Requires at least: 4.6 5 5 Tested up to: 6.7.2 6 Requires PHP: 5.66 Requires PHP: 7.2 7 7 Stable tag: 1.5.0 8 8 License: GPLv2 or later … … 83 83 84 84 == Changelog == 85 = v2.0.3 = 86 * Add logs to backup processor class 87 * ignore backup folders from other vendors 88 89 = v2.0.2 = 90 * Add a lock manager to prevent multiple update / install processes at the same time 91 92 = v2.0.1 = 93 * Filter DB tables to backup on WP related tables 94 95 = v2.0.0 = 96 * Change minimum PHP version to 7.2 97 * Implement site backups 98 85 99 = v1.8.2 = 86 100 * Add logs to update process to improve debug -
watchful/trunk/watchful.php
r3243697 r3257611 4 4 * Plugin URI: https://app.watchful.net 5 5 * Description: Remote Website Management Plugin by Watchful 6 * Version: 1.8.26 * Version: 2.0.3 7 7 * Author: watchful 8 8 * Author URI: https://watchful.net
Note: See TracChangeset
for help on using the changeset viewer.