@@ -659,21 +659,7 @@ function wp_new_blog_notification() {
659659 add_filter ( 'send_site_admin_email_change_email ' , '__return_false ' );
660660 }
661661
662- $ upgrade_file = ABSPATH . 'wp-admin/includes/upgrade.php ' ;
663- if ( ! file_exists ( $ upgrade_file ) ) {
664- WP_CLI ::error ( "WordPress installation is incomplete. The file ' {$ upgrade_file }' is missing. " );
665- }
666-
667- // Suppress errors from require_once and catch them for better error messages.
668- // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Intentional to provide better error messages.
669- if ( ! @require_once $ upgrade_file ) {
670- $ error = error_get_last ();
671- if ( $ error ) {
672- WP_CLI ::error ( "Failed to load WordPress installation file ' {$ upgrade_file }': {$ error ['message ' ]}" );
673- } else {
674- WP_CLI ::error ( "Failed to load WordPress installation file ' {$ upgrade_file }'. " );
675- }
676- }
662+ $ this ->require_upgrade_file ( 'WordPress installation ' );
677663
678664 $ defaults = [
679665 'title ' => '' ,
@@ -729,21 +715,7 @@ function wp_new_blog_notification() {
729715 private function multisite_convert_ ( $ assoc_args ) {
730716 global $ wpdb ;
731717
732- $ upgrade_file = ABSPATH . 'wp-admin/includes/upgrade.php ' ;
733- if ( ! file_exists ( $ upgrade_file ) ) {
734- WP_CLI ::error ( "WordPress installation is incomplete. The file ' {$ upgrade_file }' is missing. " );
735- }
736-
737- // Suppress errors from require_once and catch them for better error messages.
738- // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Intentional to provide better error messages.
739- if ( ! @require_once $ upgrade_file ) {
740- $ error = error_get_last ();
741- if ( $ error ) {
742- WP_CLI ::error ( "Failed to load WordPress installation file ' {$ upgrade_file }': {$ error ['message ' ]}" );
743- } else {
744- WP_CLI ::error ( "Failed to load WordPress installation file ' {$ upgrade_file }'. " );
745- }
746- }
718+ $ this ->require_upgrade_file ( 'multisite conversion ' );
747719
748720 $ domain = self ::get_clean_basedomain ();
749721 if ( 'localhost ' === $ domain && ! empty ( $ assoc_args ['subdomains ' ] ) ) {
@@ -1239,21 +1211,7 @@ public function update( $args, $assoc_args ) {
12391211 && ( $ update ->version !== $ wp_version
12401212 || Utils \get_flag_value ( $ assoc_args , 'force ' ) ) ) {
12411213
1242- $ upgrade_file = ABSPATH . 'wp-admin/includes/upgrade.php ' ;
1243- if ( ! file_exists ( $ upgrade_file ) ) {
1244- WP_CLI ::error ( "WordPress installation is incomplete. The file ' {$ upgrade_file }' is missing. " );
1245- }
1246-
1247- // Suppress errors from require_once and catch them for better error messages.
1248- // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Intentional to provide better error messages.
1249- if ( ! @require_once $ upgrade_file ) {
1250- $ error = error_get_last ();
1251- if ( $ error ) {
1252- WP_CLI ::error ( "Failed to load WordPress installation file ' {$ upgrade_file }': {$ error ['message ' ]}" );
1253- } else {
1254- WP_CLI ::error ( "Failed to load WordPress installation file ' {$ upgrade_file }'. " );
1255- }
1256- }
1214+ $ this ->require_upgrade_file ( 'WordPress core update ' );
12571215
12581216 if ( $ update ->version ) {
12591217 WP_CLI ::log ( "Updating to version {$ update ->version } ( {$ update ->locale })... " );
@@ -1413,21 +1371,7 @@ public function update_db( $args, $assoc_args ) {
14131371 }
14141372 WP_CLI ::success ( "WordPress database upgraded on {$ success }/ {$ total } sites. " );
14151373 } else {
1416- $ upgrade_file = ABSPATH . 'wp-admin/includes/upgrade.php ' ;
1417- if ( ! file_exists ( $ upgrade_file ) ) {
1418- WP_CLI ::error ( "WordPress installation is incomplete. The file ' {$ upgrade_file }' is missing. " );
1419- }
1420-
1421- // Suppress errors from require_once and catch them for better error messages.
1422- // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Intentional to provide better error messages.
1423- if ( ! @require_once $ upgrade_file ) {
1424- $ error = error_get_last ();
1425- if ( $ error ) {
1426- WP_CLI ::error ( "Failed to load WordPress installation file ' {$ upgrade_file }': {$ error ['message ' ]}" );
1427- } else {
1428- WP_CLI ::error ( "Failed to load WordPress installation file ' {$ upgrade_file }'. " );
1429- }
1430- }
1374+ $ this ->require_upgrade_file ( 'WordPress database update ' );
14311375
14321376 /**
14331377 * @var string $wp_current_db_version
@@ -1719,4 +1663,49 @@ function () use ( $new_zip_file ) {
17191663 WP_CLI ::error ( 'ZipArchive failed to open ZIP file. ' );
17201664 }
17211665 }
1666+
1667+ /**
1668+ * Safely requires the WordPress upgrade.php file with error handling.
1669+ *
1670+ * This method checks for file existence and readability before requiring,
1671+ * and registers a shutdown function to catch fatal errors during file loading
1672+ * (e.g., missing PHP extensions or other runtime issues).
1673+ *
1674+ * @param string $context Context for error messages (e.g., 'installation', 'upgrade', 'database update').
1675+ */
1676+ private function require_upgrade_file ( $ context = 'WordPress operation ' ) {
1677+ $ upgrade_file = ABSPATH . 'wp-admin/includes/upgrade.php ' ;
1678+
1679+ if ( ! file_exists ( $ upgrade_file ) ) {
1680+ WP_CLI ::error ( "WordPress installation is incomplete. The file ' {$ upgrade_file }' is missing. " );
1681+ }
1682+
1683+ if ( ! is_readable ( $ upgrade_file ) ) {
1684+ WP_CLI ::error ( "Cannot read WordPress installation file ' {$ upgrade_file }'. Check file permissions. " );
1685+ }
1686+
1687+ // Register a shutdown function to catch fatal errors during require_once.
1688+ $ shutdown_handler = function () use ( $ upgrade_file , $ context ) {
1689+ $ error = error_get_last ();
1690+ if ( null !== $ error && in_array ( $ error ['type ' ], [ E_ERROR , E_PARSE , E_CORE_ERROR , E_COMPILE_ERROR ], true ) ) {
1691+ // Check if error occurred in the upgrade file or files it includes.
1692+ if ( false !== strpos ( $ error ['file ' ], 'wp-admin/includes/ ' ) || false !== strpos ( $ error ['file ' ], 'wp-includes/ ' ) ) {
1693+ WP_CLI ::error (
1694+ sprintf (
1695+ "Failed to load WordPress files for %s. This often indicates a missing PHP extension or a corrupted WordPress installation. \n\nError: %s in %s on line %d \n\nPlease check that all required PHP extensions are installed and that your WordPress installation is complete. " ,
1696+ $ context ,
1697+ $ error ['message ' ],
1698+ $ error ['file ' ],
1699+ $ error ['line ' ]
1700+ )
1701+ );
1702+ }
1703+ }
1704+ };
1705+
1706+ register_shutdown_function ( $ shutdown_handler );
1707+
1708+ // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable -- Path comes from WordPress itself.
1709+ require_once $ upgrade_file ;
1710+ }
17221711}
0 commit comments