74 * {@see 'upgrader_post_install'} filter. In that case, the WP_Error will be assigned to |
74 * {@see 'upgrader_post_install'} filter. In that case, the WP_Error will be assigned to |
75 * it. |
75 * it. |
76 * |
76 * |
77 * @since 2.8.0 |
77 * @since 2.8.0 |
78 * |
78 * |
79 * @var WP_Error|array $result { |
79 * @var array|WP_Error $result { |
80 * @type string $source The full path to the source the files were installed from. |
80 * @type string $source The full path to the source the files were installed from. |
81 * @type string $source_files List of all the files in the source directory. |
81 * @type string $source_files List of all the files in the source directory. |
82 * @type string $destination The full path to the installation destination folder. |
82 * @type string $destination The full path to the installation destination folder. |
83 * @type string $destination_name The name of the destination folder, or empty if `$destination` |
83 * @type string $destination_name The name of the destination folder, or empty if `$destination` |
84 * and `$local_destination` are the same. |
84 * and `$local_destination` are the same. |
85 * @type string $local_destination The full local path to the destination folder. This is usually |
85 * @type string $local_destination The full local path to the destination folder. This is usually |
86 * the same as `$destination`. |
86 * the same as `$destination`. |
87 * @type string $remote_destination The full remote path to the destination folder |
87 * @type string $remote_destination The full remote path to the destination folder |
88 * (i.e., from `$wp_filesystem`). |
88 * (i.e., from `$wp_filesystem`). |
89 * @type bool $clear_destination Whether the destination folder was cleared. |
89 * @type bool $clear_destination Whether the destination folder was cleared. |
90 * } |
90 * } |
91 */ |
91 */ |
92 public $result = array(); |
92 public $result = array(); |
93 |
93 |
94 /** |
94 /** |
151 $this->strings['fs_error'] = __( 'Filesystem error.' ); |
151 $this->strings['fs_error'] = __( 'Filesystem error.' ); |
152 $this->strings['fs_no_root_dir'] = __( 'Unable to locate WordPress root directory.' ); |
152 $this->strings['fs_no_root_dir'] = __( 'Unable to locate WordPress root directory.' ); |
153 $this->strings['fs_no_content_dir'] = __( 'Unable to locate WordPress content directory (wp-content).' ); |
153 $this->strings['fs_no_content_dir'] = __( 'Unable to locate WordPress content directory (wp-content).' ); |
154 $this->strings['fs_no_plugins_dir'] = __( 'Unable to locate WordPress plugin directory.' ); |
154 $this->strings['fs_no_plugins_dir'] = __( 'Unable to locate WordPress plugin directory.' ); |
155 $this->strings['fs_no_themes_dir'] = __( 'Unable to locate WordPress theme directory.' ); |
155 $this->strings['fs_no_themes_dir'] = __( 'Unable to locate WordPress theme directory.' ); |
156 /* translators: %s: directory name */ |
156 /* translators: %s: Directory name. */ |
157 $this->strings['fs_no_folder'] = __( 'Unable to locate needed folder (%s).' ); |
157 $this->strings['fs_no_folder'] = __( 'Unable to locate needed folder (%s).' ); |
158 |
158 |
159 $this->strings['download_failed'] = __( 'Download failed.' ); |
159 $this->strings['download_failed'] = __( 'Download failed.' ); |
160 $this->strings['installing_package'] = __( 'Installing the latest version…' ); |
160 $this->strings['installing_package'] = __( 'Installing the latest version…' ); |
161 $this->strings['no_files'] = __( 'The package contains no files.' ); |
161 $this->strings['no_files'] = __( 'The package contains no files.' ); |
173 * |
173 * |
174 * @since 2.8.0 |
174 * @since 2.8.0 |
175 * |
175 * |
176 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. |
176 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. |
177 * |
177 * |
178 * @param array $directories Optional. A list of directories. If any of these do |
178 * @param string[] $directories Optional. Array of directories. If any of these do |
179 * not exist, a WP_Error object will be returned. |
179 * not exist, a WP_Error object will be returned. |
180 * Default empty array. |
180 * Default empty array. |
181 * @param bool $allow_relaxed_file_ownership Whether to allow relaxed file ownership. |
181 * @param bool $allow_relaxed_file_ownership Whether to allow relaxed file ownership. |
182 * Default false. |
182 * Default false. |
183 * @return bool|WP_Error True if able to connect, false or a WP_Error otherwise. |
183 * @return bool|WP_Error True if able to connect, false or a WP_Error otherwise. |
184 */ |
184 */ |
185 public function fs_connect( $directories = array(), $allow_relaxed_file_ownership = false ) { |
185 public function fs_connect( $directories = array(), $allow_relaxed_file_ownership = false ) { |
186 global $wp_filesystem; |
186 global $wp_filesystem; |
187 |
187 |
188 if ( false === ( $credentials = $this->skin->request_filesystem_credentials( false, $directories[0], $allow_relaxed_file_ownership ) ) ) { |
188 $credentials = $this->skin->request_filesystem_credentials( false, $directories[0], $allow_relaxed_file_ownership ); |
|
189 if ( false === $credentials ) { |
189 return false; |
190 return false; |
190 } |
191 } |
191 |
192 |
192 if ( ! WP_Filesystem( $credentials, $directories[0], $allow_relaxed_file_ownership ) ) { |
193 if ( ! WP_Filesystem( $credentials, $directories[0], $allow_relaxed_file_ownership ) ) { |
193 $error = true; |
194 $error = true; |
194 if ( is_object( $wp_filesystem ) && $wp_filesystem->errors->has_errors() ) { |
195 if ( is_object( $wp_filesystem ) && $wp_filesystem->errors->has_errors() ) { |
195 $error = $wp_filesystem->errors; |
196 $error = $wp_filesystem->errors; |
196 } |
197 } |
197 // Failed to connect, Error and request again |
198 // Failed to connect. Error and request again. |
198 $this->skin->request_filesystem_credentials( $error, $directories[0], $allow_relaxed_file_ownership ); |
199 $this->skin->request_filesystem_credentials( $error, $directories[0], $allow_relaxed_file_ownership ); |
199 return false; |
200 return false; |
200 } |
201 } |
201 |
202 |
202 if ( ! is_object( $wp_filesystem ) ) { |
203 if ( ! is_object( $wp_filesystem ) ) { |
235 } |
236 } |
236 break; |
237 break; |
237 } |
238 } |
238 } |
239 } |
239 return true; |
240 return true; |
240 } //end fs_connect(); |
241 } |
241 |
242 |
242 /** |
243 /** |
243 * Download a package. |
244 * Download a package. |
244 * |
245 * |
245 * @since 2.8.0 |
246 * @since 2.8.0 |
|
247 * @since 5.5.0 Added the `$hook_extra` parameter. |
246 * |
248 * |
247 * @param string $package The URI of the package. If this is the full path to an |
249 * @param string $package The URI of the package. If this is the full path to an |
248 * existing local file, it will be returned untouched. |
250 * existing local file, it will be returned untouched. |
249 * @param bool $check_signatures Whether to validate file signatures. Default false. |
251 * @param bool $check_signatures Whether to validate file signatures. Default false. |
|
252 * @param array $hook_extra Extra arguments to pass to the filter hooks. Default empty array. |
250 * @return string|WP_Error The full path to the downloaded package file, or a WP_Error object. |
253 * @return string|WP_Error The full path to the downloaded package file, or a WP_Error object. |
251 */ |
254 */ |
252 public function download_package( $package, $check_signatures = false ) { |
255 public function download_package( $package, $check_signatures = false, $hook_extra = array() ) { |
253 |
|
254 /** |
256 /** |
255 * Filters whether to return the package. |
257 * Filters whether to return the package. |
256 * |
258 * |
257 * @since 3.7.0 |
259 * @since 3.7.0 |
258 * |
260 * @since 5.5.0 Added the `$hook_extra` parameter. |
259 * @param bool $reply Whether to bail without returning the package. |
261 * |
260 * Default false. |
262 * @param bool $reply Whether to bail without returning the package. |
261 * @param string $package The package file name. |
263 * Default false. |
262 * @param WP_Upgrader $this The WP_Upgrader instance. |
264 * @param string $package The package file name. |
|
265 * @param WP_Upgrader $this The WP_Upgrader instance. |
|
266 * @param array $hook_extra Extra arguments passed to hooked filters. |
263 */ |
267 */ |
264 $reply = apply_filters( 'upgrader_pre_download', false, $package, $this ); |
268 $reply = apply_filters( 'upgrader_pre_download', false, $package, $this, $hook_extra ); |
265 if ( false !== $reply ) { |
269 if ( false !== $reply ) { |
266 return $reply; |
270 return $reply; |
267 } |
271 } |
268 |
272 |
269 if ( ! preg_match( '!^(http|https|ftp)://!i', $package ) && file_exists( $package ) ) { //Local file or remote? |
273 if ( ! preg_match( '!^(http|https|ftp)://!i', $package ) && file_exists( $package ) ) { // Local file or remote? |
270 return $package; //must be a local file.. |
274 return $package; // Must be a local file. |
271 } |
275 } |
272 |
276 |
273 if ( empty( $package ) ) { |
277 if ( empty( $package ) ) { |
274 return new WP_Error( 'no_package', $this->strings['no_package'] ); |
278 return new WP_Error( 'no_package', $this->strings['no_package'] ); |
275 } |
279 } |
302 |
306 |
303 $this->skin->feedback( 'unpack_package' ); |
307 $this->skin->feedback( 'unpack_package' ); |
304 |
308 |
305 $upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/'; |
309 $upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/'; |
306 |
310 |
307 //Clean up contents of upgrade directory beforehand. |
311 // Clean up contents of upgrade directory beforehand. |
308 $upgrade_files = $wp_filesystem->dirlist( $upgrade_folder ); |
312 $upgrade_files = $wp_filesystem->dirlist( $upgrade_folder ); |
309 if ( ! empty( $upgrade_files ) ) { |
313 if ( ! empty( $upgrade_files ) ) { |
310 foreach ( $upgrade_files as $file ) { |
314 foreach ( $upgrade_files as $file ) { |
311 $wp_filesystem->delete( $upgrade_folder . $file['name'], true ); |
315 $wp_filesystem->delete( $upgrade_folder . $file['name'], true ); |
312 } |
316 } |
313 } |
317 } |
314 |
318 |
315 // We need a working directory - Strip off any .tmp or .zip suffixes |
319 // We need a working directory - strip off any .tmp or .zip suffixes. |
316 $working_dir = $upgrade_folder . basename( basename( $package, '.tmp' ), '.zip' ); |
320 $working_dir = $upgrade_folder . basename( basename( $package, '.tmp' ), '.zip' ); |
317 |
321 |
318 // Clean up working directory |
322 // Clean up working directory. |
319 if ( $wp_filesystem->is_dir( $working_dir ) ) { |
323 if ( $wp_filesystem->is_dir( $working_dir ) ) { |
320 $wp_filesystem->delete( $working_dir, true ); |
324 $wp_filesystem->delete( $working_dir, true ); |
321 } |
325 } |
322 |
326 |
323 // Unzip package to working directory |
327 // Unzip package to working directory. |
324 $result = unzip_file( $package, $working_dir ); |
328 $result = unzip_file( $package, $working_dir ); |
325 |
329 |
326 // Once extracted, delete the package if required. |
330 // Once extracted, delete the package if required. |
327 if ( $delete_package ) { |
331 if ( $delete_package ) { |
328 unlink( $package ); |
332 unlink( $package ); |
329 } |
333 } |
330 |
334 |
331 if ( is_wp_error( $result ) ) { |
335 if ( is_wp_error( $result ) ) { |
332 $wp_filesystem->delete( $working_dir, true ); |
336 $wp_filesystem->delete( $working_dir, true ); |
333 if ( 'incompatible_archive' == $result->get_error_code() ) { |
337 if ( 'incompatible_archive' === $result->get_error_code() ) { |
334 return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], $result->get_error_data() ); |
338 return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], $result->get_error_data() ); |
335 } |
339 } |
336 return $result; |
340 return $result; |
337 } |
341 } |
338 |
342 |
343 * Flatten the results of WP_Filesystem::dirlist() for iterating over. |
347 * Flatten the results of WP_Filesystem::dirlist() for iterating over. |
344 * |
348 * |
345 * @since 4.9.0 |
349 * @since 4.9.0 |
346 * @access protected |
350 * @access protected |
347 * |
351 * |
348 * @param array $nested_files Array of files as returned by WP_Filesystem::dirlist() |
352 * @param array $nested_files Array of files as returned by WP_Filesystem::dirlist(). |
349 * @param string $path Relative path to prepend to child nodes. Optional. |
353 * @param string $path Relative path to prepend to child nodes. Optional. |
350 * @return array $files A flattened array of the $nested_files specified. |
354 * @return array A flattened array of the $nested_files specified. |
351 */ |
355 */ |
352 protected function flatten_dirlist( $nested_files, $path = '' ) { |
356 protected function flatten_dirlist( $nested_files, $path = '' ) { |
353 $files = array(); |
357 $files = array(); |
354 |
358 |
355 foreach ( $nested_files as $name => $details ) { |
359 foreach ( $nested_files as $name => $details ) { |
356 $files[ $path . $name ] = $details; |
360 $files[ $path . $name ] = $details; |
357 |
361 |
358 // Append children recursively |
362 // Append children recursively. |
359 if ( ! empty( $details['files'] ) ) { |
363 if ( ! empty( $details['files'] ) ) { |
360 $children = $this->flatten_dirlist( $details['files'], $path . $name . '/' ); |
364 $children = $this->flatten_dirlist( $details['files'], $path . $name . '/' ); |
361 |
365 |
362 // Merge keeping possible numeric keys, which array_merge() will reindex from 0..n |
366 // Merge keeping possible numeric keys, which array_merge() will reindex from 0..n. |
363 $files = $files + $children; |
367 $files = $files + $children; |
364 } |
368 } |
365 } |
369 } |
366 |
370 |
367 return $files; |
371 return $files; |
385 // False indicates that the $remote_destination doesn't exist. |
389 // False indicates that the $remote_destination doesn't exist. |
386 if ( false === $files ) { |
390 if ( false === $files ) { |
387 return true; |
391 return true; |
388 } |
392 } |
389 |
393 |
390 // Flatten the file list to iterate over |
394 // Flatten the file list to iterate over. |
391 $files = $this->flatten_dirlist( $files ); |
395 $files = $this->flatten_dirlist( $files ); |
392 |
396 |
393 // Check all files are writable before attempting to clear the destination. |
397 // Check all files are writable before attempting to clear the destination. |
394 $unwritable_files = array(); |
398 $unwritable_files = array(); |
395 |
399 |
396 // Check writability. |
400 // Check writability. |
397 foreach ( $files as $filename => $file_details ) { |
401 foreach ( $files as $filename => $file_details ) { |
398 if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) ) { |
402 if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) ) { |
399 // Attempt to alter permissions to allow writes and try again. |
403 // Attempt to alter permissions to allow writes and try again. |
400 $wp_filesystem->chmod( $remote_destination . $filename, ( 'd' == $file_details['type'] ? FS_CHMOD_DIR : FS_CHMOD_FILE ) ); |
404 $wp_filesystem->chmod( $remote_destination . $filename, ( 'd' === $file_details['type'] ? FS_CHMOD_DIR : FS_CHMOD_FILE ) ); |
401 if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) ) { |
405 if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) ) { |
402 $unwritable_files[] = $filename; |
406 $unwritable_files[] = $filename; |
403 } |
407 } |
404 } |
408 } |
405 } |
409 } |
447 */ |
451 */ |
448 public function install_package( $args = array() ) { |
452 public function install_package( $args = array() ) { |
449 global $wp_filesystem, $wp_theme_directories; |
453 global $wp_filesystem, $wp_theme_directories; |
450 |
454 |
451 $defaults = array( |
455 $defaults = array( |
452 'source' => '', // Please always pass this |
456 'source' => '', // Please always pass this. |
453 'destination' => '', // and this |
457 'destination' => '', // ...and this. |
454 'clear_destination' => false, |
458 'clear_destination' => false, |
455 'clear_working' => false, |
459 'clear_working' => false, |
456 'abort_if_destination_exists' => true, |
460 'abort_if_destination_exists' => true, |
457 'hook_extra' => array(), |
461 'hook_extra' => array(), |
458 ); |
462 ); |
487 |
491 |
488 if ( is_wp_error( $res ) ) { |
492 if ( is_wp_error( $res ) ) { |
489 return $res; |
493 return $res; |
490 } |
494 } |
491 |
495 |
492 //Retain the Original source and destinations |
496 // Retain the original source and destinations. |
493 $remote_source = $args['source']; |
497 $remote_source = $args['source']; |
494 $local_destination = $destination; |
498 $local_destination = $destination; |
495 |
499 |
496 $source_files = array_keys( $wp_filesystem->dirlist( $remote_source ) ); |
500 $source_files = array_keys( $wp_filesystem->dirlist( $remote_source ) ); |
497 $remote_destination = $wp_filesystem->find_folder( $local_destination ); |
501 $remote_destination = $wp_filesystem->find_folder( $local_destination ); |
498 |
502 |
499 //Locate which directory to copy to the new folder, This is based on the actual folder holding the files. |
503 // Locate which directory to copy to the new folder. This is based on the actual folder holding the files. |
500 if ( 1 == count( $source_files ) && $wp_filesystem->is_dir( trailingslashit( $args['source'] ) . $source_files[0] . '/' ) ) { //Only one folder? Then we want its contents. |
504 if ( 1 === count( $source_files ) && $wp_filesystem->is_dir( trailingslashit( $args['source'] ) . $source_files[0] . '/' ) ) { |
|
505 // Only one folder? Then we want its contents. |
501 $source = trailingslashit( $args['source'] ) . trailingslashit( $source_files[0] ); |
506 $source = trailingslashit( $args['source'] ) . trailingslashit( $source_files[0] ); |
502 } elseif ( count( $source_files ) == 0 ) { |
507 } elseif ( count( $source_files ) == 0 ) { |
503 return new WP_Error( 'incompatible_archive_empty', $this->strings['incompatible_archive'], $this->strings['no_files'] ); // There are no files? |
508 // There are no files? |
504 } else { // It's only a single file, the upgrader will use the folder name of this file as the destination folder. Folder name is based on zip filename. |
509 return new WP_Error( 'incompatible_archive_empty', $this->strings['incompatible_archive'], $this->strings['no_files'] ); |
|
510 } else { |
|
511 // It's only a single file, the upgrader will use the folder name of this file as the destination folder. |
|
512 // Folder name is based on zip filename. |
505 $source = trailingslashit( $args['source'] ); |
513 $source = trailingslashit( $args['source'] ); |
506 } |
514 } |
507 |
515 |
508 /** |
516 /** |
509 * Filters the source file location for the upgrade package. |
517 * Filters the source file location for the upgrade package. |
554 /** |
562 /** |
555 * Filters whether the upgrader cleared the destination. |
563 * Filters whether the upgrader cleared the destination. |
556 * |
564 * |
557 * @since 2.8.0 |
565 * @since 2.8.0 |
558 * |
566 * |
559 * @param mixed $removed Whether the destination was cleared. true on success, WP_Error on failure |
567 * @param true|WP_Error $removed Whether the destination was cleared. true upon success, WP_Error on failure. |
560 * @param string $local_destination The local package destination. |
568 * @param string $local_destination The local package destination. |
561 * @param string $remote_destination The remote package destination. |
569 * @param string $remote_destination The remote package destination. |
562 * @param array $hook_extra Extra arguments passed to hooked filters. |
570 * @param array $hook_extra Extra arguments passed to hooked filters. |
563 */ |
571 */ |
564 $removed = apply_filters( 'upgrader_clear_destination', $removed, $local_destination, $remote_destination, $args['hook_extra'] ); |
572 $removed = apply_filters( 'upgrader_clear_destination', $removed, $local_destination, $remote_destination, $args['hook_extra'] ); |
565 |
573 |
566 if ( is_wp_error( $removed ) ) { |
574 if ( is_wp_error( $removed ) ) { |
567 return $removed; |
575 return $removed; |
568 } |
576 } |
569 } elseif ( $args['abort_if_destination_exists'] && $wp_filesystem->exists( $remote_destination ) ) { |
577 } elseif ( $args['abort_if_destination_exists'] && $wp_filesystem->exists( $remote_destination ) ) { |
570 //If we're not clearing the destination folder and something exists there already, Bail. |
578 // If we're not clearing the destination folder and something exists there already, bail. |
571 //But first check to see if there are actually any files in the folder. |
579 // But first check to see if there are actually any files in the folder. |
572 $_files = $wp_filesystem->dirlist( $remote_destination ); |
580 $_files = $wp_filesystem->dirlist( $remote_destination ); |
573 if ( ! empty( $_files ) ) { |
581 if ( ! empty( $_files ) ) { |
574 $wp_filesystem->delete( $remote_source, true ); //Clear out the source files. |
582 $wp_filesystem->delete( $remote_source, true ); // Clear out the source files. |
575 return new WP_Error( 'folder_exists', $this->strings['folder_exists'], $remote_destination ); |
583 return new WP_Error( 'folder_exists', $this->strings['folder_exists'], $remote_destination ); |
576 } |
584 } |
577 } |
585 } |
578 |
586 |
579 //Create destination if needed |
587 // Create destination if needed. |
580 if ( ! $wp_filesystem->exists( $remote_destination ) ) { |
588 if ( ! $wp_filesystem->exists( $remote_destination ) ) { |
581 if ( ! $wp_filesystem->mkdir( $remote_destination, FS_CHMOD_DIR ) ) { |
589 if ( ! $wp_filesystem->mkdir( $remote_destination, FS_CHMOD_DIR ) ) { |
582 return new WP_Error( 'mkdir_failed_destination', $this->strings['mkdir_failed'], $remote_destination ); |
590 return new WP_Error( 'mkdir_failed_destination', $this->strings['mkdir_failed'], $remote_destination ); |
583 } |
591 } |
584 } |
592 } |
|
593 |
585 // Copy new version of item into place. |
594 // Copy new version of item into place. |
586 $result = copy_dir( $source, $remote_destination ); |
595 $result = copy_dir( $source, $remote_destination ); |
587 if ( is_wp_error( $result ) ) { |
596 if ( is_wp_error( $result ) ) { |
588 if ( $args['clear_working'] ) { |
597 if ( $args['clear_working'] ) { |
589 $wp_filesystem->delete( $remote_source, true ); |
598 $wp_filesystem->delete( $remote_source, true ); |
590 } |
599 } |
591 return $result; |
600 return $result; |
592 } |
601 } |
593 |
602 |
594 //Clear the Working folder? |
603 // Clear the working folder? |
595 if ( $args['clear_working'] ) { |
604 if ( $args['clear_working'] ) { |
596 $wp_filesystem->delete( $remote_source, true ); |
605 $wp_filesystem->delete( $remote_source, true ); |
597 } |
606 } |
598 |
607 |
599 $destination_name = basename( str_replace( $local_destination, '', $destination ) ); |
608 $destination_name = basename( str_replace( $local_destination, '', $destination ) ); |
600 if ( '.' == $destination_name ) { |
609 if ( '.' === $destination_name ) { |
601 $destination_name = ''; |
610 $destination_name = ''; |
602 } |
611 } |
603 |
612 |
604 $this->result = compact( 'source', 'source_files', 'destination', 'destination_name', 'local_destination', 'remote_destination', 'clear_destination' ); |
613 $this->result = compact( 'source', 'source_files', 'destination', 'destination_name', 'local_destination', 'remote_destination', 'clear_destination' ); |
605 |
614 |
651 * WP_Upgrader::header() and WP_Upgrader::footer() |
660 * WP_Upgrader::header() and WP_Upgrader::footer() |
652 * aren't called. Default false. |
661 * aren't called. Default false. |
653 * @type array $hook_extra Extra arguments to pass to the filter hooks called by |
662 * @type array $hook_extra Extra arguments to pass to the filter hooks called by |
654 * WP_Upgrader::run(). |
663 * WP_Upgrader::run(). |
655 * } |
664 * } |
656 * @return array|false|WP_error The result from self::install_package() on success, otherwise a WP_Error, |
665 * @return array|false|WP_Error The result from self::install_package() on success, otherwise a WP_Error, |
657 * or false if unable to connect to the filesystem. |
666 * or false if unable to connect to the filesystem. |
658 */ |
667 */ |
659 public function run( $options ) { |
668 public function run( $options ) { |
660 |
669 |
661 $defaults = array( |
670 $defaults = array( |
662 'package' => '', // Please always pass this. |
671 'package' => '', // Please always pass this. |
663 'destination' => '', // And this |
672 'destination' => '', // ...and this. |
664 'clear_destination' => false, |
673 'clear_destination' => false, |
665 'abort_if_destination_exists' => true, // Abort if the Destination directory exists, Pass clear_destination as false please |
674 'abort_if_destination_exists' => true, // Abort if the destination directory exists. Pass clear_destination as false please. |
666 'clear_working' => true, |
675 'clear_working' => true, |
667 'is_multi' => false, |
676 'is_multi' => false, |
668 'hook_extra' => array(), // Pass any extra $hook_extra args here, this will be passed to any hooked filters. |
677 'hook_extra' => array(), // Pass any extra $hook_extra args here, this will be passed to any hooked filters. |
669 ); |
678 ); |
670 |
679 |
700 * } |
709 * } |
701 * } |
710 * } |
702 */ |
711 */ |
703 $options = apply_filters( 'upgrader_package_options', $options ); |
712 $options = apply_filters( 'upgrader_package_options', $options ); |
704 |
713 |
705 if ( ! $options['is_multi'] ) { // call $this->header separately if running multiple times |
714 if ( ! $options['is_multi'] ) { // Call $this->header separately if running multiple times. |
706 $this->skin->header(); |
715 $this->skin->header(); |
707 } |
716 } |
708 |
717 |
709 // Connect to the Filesystem first. |
718 // Connect to the filesystem first. |
710 $res = $this->fs_connect( array( WP_CONTENT_DIR, $options['destination'] ) ); |
719 $res = $this->fs_connect( array( WP_CONTENT_DIR, $options['destination'] ) ); |
711 // Mainly for non-connected filesystem. |
720 // Mainly for non-connected filesystem. |
712 if ( ! $res ) { |
721 if ( ! $res ) { |
713 if ( ! $options['is_multi'] ) { |
722 if ( ! $options['is_multi'] ) { |
714 $this->skin->footer(); |
723 $this->skin->footer(); |
729 |
738 |
730 /* |
739 /* |
731 * Download the package (Note, This just returns the filename |
740 * Download the package (Note, This just returns the filename |
732 * of the file if the package is a local file) |
741 * of the file if the package is a local file) |
733 */ |
742 */ |
734 $download = $this->download_package( $options['package'], true ); |
743 $download = $this->download_package( $options['package'], true, $options['hook_extra'] ); |
735 |
744 |
736 // Allow for signature soft-fail. |
745 // Allow for signature soft-fail. |
737 // WARNING: This may be removed in the future. |
746 // WARNING: This may be removed in the future. |
738 if ( is_wp_error( $download ) && $download->get_error_data( 'softfail-filename' ) ) { |
747 if ( is_wp_error( $download ) && $download->get_error_data( 'softfail-filename' ) ) { |
739 |
748 |
740 // Don't output the 'no signature could be found' failure message for now. |
749 // Don't output the 'no signature could be found' failure message for now. |
741 if ( 'signature_verification_no_signature' != $download->get_error_code() || WP_DEBUG ) { |
750 if ( 'signature_verification_no_signature' !== $download->get_error_code() || WP_DEBUG ) { |
742 // Outout the failure error as a normal feedback, and not as an error: |
751 // Output the failure error as a normal feedback, and not as an error. |
743 $this->skin->feedback( $download->get_error_message() ); |
752 $this->skin->feedback( $download->get_error_message() ); |
744 |
753 |
745 // Report this failure back to WordPress.org for debugging purposes. |
754 // Report this failure back to WordPress.org for debugging purposes. |
746 wp_version_check( |
755 wp_version_check( |
747 array( |
756 array( |
854 public function maintenance_mode( $enable = false ) { |
866 public function maintenance_mode( $enable = false ) { |
855 global $wp_filesystem; |
867 global $wp_filesystem; |
856 $file = $wp_filesystem->abspath() . '.maintenance'; |
868 $file = $wp_filesystem->abspath() . '.maintenance'; |
857 if ( $enable ) { |
869 if ( $enable ) { |
858 $this->skin->feedback( 'maintenance_start' ); |
870 $this->skin->feedback( 'maintenance_start' ); |
859 // Create maintenance file to signal that we are upgrading |
871 // Create maintenance file to signal that we are upgrading. |
860 $maintenance_string = '<?php $upgrading = ' . time() . '; ?>'; |
872 $maintenance_string = '<?php $upgrading = ' . time() . '; ?>'; |
861 $wp_filesystem->delete( $file ); |
873 $wp_filesystem->delete( $file ); |
862 $wp_filesystem->put_contents( $file, $maintenance_string, FS_CHMOD_FILE ); |
874 $wp_filesystem->put_contents( $file, $maintenance_string, FS_CHMOD_FILE ); |
863 } elseif ( ! $enable && $wp_filesystem->exists( $file ) ) { |
875 } elseif ( ! $enable && $wp_filesystem->exists( $file ) ) { |
864 $this->skin->feedback( 'maintenance_end' ); |
876 $this->skin->feedback( 'maintenance_end' ); |