HEX
Server: nginx
System: Linux pool64-304-45.dca.atomicsites.net 5.10.0-31-amd64 #1 SMP Debian 5.10.221-1 (2024-07-14) x86_64
User: (0)
PHP: 8.4.19
Disabled: pcntl_fork
Upload Files
File: /wordpress/mu-plugins/atomic-cli-managed-software.php
<?php

if ( ! class_exists( 'Atomic_Platform_Managed_Software_Commands' ) ) {
	class Atomic_Platform_Managed_Software_Commands {
		/**
		 * Symlinks a managed plugin into the site's plugins directory.
		 *
		 * ## OPTIONS
		 *
		 * <plugin>
		 * : The name of the managed plugin to use.
		 *
		 * [--remove-existing]
		 * : If there is an existing directory or symlink in the way, remove it without asking.
		 *
		 * [--activate]
		 * : Indicates that the managed plugin should be activated
		 */
		public static function use_managed_plugin( $args, $assoc_args = array() ) {
			$plugin_to_symlink = $args[0];

			if ( 'wpcomsh' === $plugin_to_symlink ) {
				// wpcomsh is in the managed plugins directory, but it should not be symlinked into the plugins directory.
				WP_CLI::error( 'Cannot symlink wpcomsh' );
			}

			if ( false === chdir( WP_PLUGIN_DIR ) ) {
				WP_CLI::error( "Cannot switch to plugins directory '" . WP_PLUGIN_DIR . "'" );
			}

			$managed_plugin_relative_path = _atomic_platform_managed_symlink( 'plugin', $plugin_to_symlink, 'latest' );
			if ( false === realpath( $managed_plugin_relative_path ) ) {
				WP_CLI::error( "'$plugin_to_symlink' is not a managed plugin" );
			}

			$already_symlinked = false;
			if ( realpath( $plugin_to_symlink ) === realpath( $managed_plugin_relative_path ) ) {
				$already_symlinked = true;
			} elseif ( is_dir( $plugin_to_symlink ) ) {
				$permission_to_remove = false;
				if ( WP_CLI\Utils\get_flag_value( $assoc_args, 'remove-existing', false ) ) {
					$permission_to_remove = true;
				} elseif ( static::cli_confirm( "Plugin '$plugin_to_symlink' exists. Delete it and replace with symlink to managed plugin?" ) ) {
					$permission_to_remove = true;
				}
				if ( ! $permission_to_remove ) {
					exit( -1 );
				}

				if ( is_link( $plugin_to_symlink ) ) {
					if ( false === unlink( $plugin_to_symlink ) ) {
						WP_CLI::error( "Failed to remove conflicting symlink '$plugin_to_symlink'" );
						exit( -1 );
					}
				} else {
					WP_CLI::runcommand(
						"--skip-plugins --skip-themes plugin delete '$plugin_to_symlink'",
						array(
							'launch'     => false,
							'exit_error' => true,
						)
					);
				}
			}

			if ( $already_symlinked ) {
				WP_CLI::success( "Plugin '$plugin_to_symlink' is already symlinked" );
			} elseif ( symlink( $managed_plugin_relative_path, $plugin_to_symlink ) ) {
				// Delete the plugins cache so the symlinked plugin can be recognized
				wp_cache_delete( 'plugins', 'plugins' );

				WP_CLI::success( "Added symlink to managed plugin: $plugin_to_symlink" );
			} else {
				WP_CLI::error( "Failed to symlink managed plugin: $plugin_to_symlink" );
				exit( -1 );
			}

			$activate = WP_CLI\Utils\get_flag_value( $assoc_args, 'activate', false );
			if ( $activate ) {
				WP_CLI::runcommand(
					"--skip-plugins --skip-themes plugin activate '$plugin_to_symlink'",
					array(
						'launch'     => false,
						'exit_error' => true,
					)
				);
			}

			exit( 0 );
		}

		/**
		 * Installs an unmanaged plugin into the site's plugins directory. replacing a managed version if one exists.
		 *
		 * ## OPTIONS
		 *
		 * <plugin>
		 * : The name of the plugin.
		 *
		 * [--remove-existing]
		 * : If there is an existing directory or symlink in the way, remove it without asking.
		 *
		 * [--activate]
		 * : Indicates that the plugin should be activated.
		 *
		 * [--version]
		 * : The version to install.
		 */
		public static function use_unmanaged_plugin( $args, $assoc_args = array() ) {
			$plugin_to_install = $args[0];

			if ( false === chdir( WP_PLUGIN_DIR ) ) {
				WP_CLI::error( "Cannot switch to plugins directory '" . WP_PLUGIN_DIR . "'" );
			}

			$install_path = WP_PLUGIN_DIR . "/$plugin_to_install";
			$already_exists = is_link( $install_path ) || file_exists( $install_path );

			$previous_version_path = false;
			if ( $already_exists ) {
				$permission_to_remove = false;
				if ( WP_CLI\Utils\get_flag_value( $assoc_args, 'remove-existing', false ) ) {
					$permission_to_remove = true;
				} elseif ( static::cli_confirm( "Plugin '$plugin_to_install' exists. Delete it and replace with an unmanaged plugin?" ) ) {
					$permission_to_remove = true;
				}
				if ( ! $permission_to_remove ) {
					exit( -1 );
				}

				WP_CLI::log( "Setting previous version aside until new install succeeds" );

				$uuid = wp_generate_uuid4();
				$previous_version_path = WP_PLUGIN_DIR . "/.previous-version-$plugin_to_install-$uuid";
				if ( ! rename( $install_path, $previous_version_path ) ) {
					WP_CLI::error( "Failed to move previous version to $previous_version_path" );
				}
			}

			$command = "--skip-plugins --skip-themes plugin install $plugin_to_install --force";

			$version = WP_CLI\Utils\get_flag_value( $assoc_args, 'version', false );
			if ( false !== $version ) {
				$command = "$command --version=$version";
			}

			$result = WP_CLI::runcommand(
				$command,
				array(
					'return' => 'all',
					'launch' => true,
					'exit_error' => false,
				)
			);

			if ( 0 !== $result->return_code ) {
				WP_CLI::error( 'There was an error installing the plugin', false );
				WP_CLI::log( $result->stderr );

				if ( $previous_version_path ) {
					WP_CLI::log( 'Restoring previous version...' );
					if ( ! rename( $previous_version_path, $install_path ) ) {
						WP_CLI::error(
							"Failed to restore previous version from $previous_version_path to $install_path",
							false
						);
					}
					WP_CLI::log( 'Done' );
				}


				exit( -1 );
			}

			WP_CLI::success( "Installed unmanaged plugin: $plugin_to_install" );

			$activate = WP_CLI\Utils\get_flag_value( $assoc_args, 'activate', false );
			if ( $activate ) {
				WP_CLI::runcommand(
					"--skip-plugins --skip-themes plugin activate '$plugin_to_install'",
					array(
						'launch'     => false,
						'exit_error' => true,
					)
				);
			}

			if ( $previous_version_path ) {
				WP_CLI::log( 'Cleaning up previous version...' );

				$removal_shell_command = 'rm -r ' . escapeshellarg( $previous_version_path );
				$removal_result_code = 0;
				passthru( $removal_shell_command, $removal_result_code );

				if ( 0 !== $removal_result_code ) {
					WP_CLI::error( "Unable to clean up previous version: $previous_version_path" );
				}

				WP_CLI::log( 'Done' );
			}

			exit( 0 );
		}

		/**
		 * Symlinks a managed theme into the site's themes directory.
		 *
		 * ## OPTIONS
		 *
		 * <theme>
		 * : The managed theme to symlink.
		 *
		 * [--remove-existing]
		 * : If there is an existing directory or different symlink in the way, remove it without asking.
		 *
		 * [--activate]
		 * : Indicates that the symlinked theme should be activated
		 */
		public static function use_managed_theme( $args, $assoc_args = array() ) {
			$theme_to_symlink = $args[0];

			$themes_dir = get_theme_root();
			if ( false === chdir( $themes_dir ) ) {
				WP_CLI::error( "Cannot switch to themes directory '$themes_dir'" );
			}

			$candidate_managed_theme_paths = array_unique(
				array(
					// NOTE: pub and premium themes don't have nested `latest`and version directories.
					_atomic_platform_managed_symlink( 'theme', $theme_to_symlink, 'pub' ),
					_atomic_platform_managed_symlink( 'theme', $theme_to_symlink, 'premium' ),
					// Consider root themes dir last because we want to favor WPCOM-managed things on WPCOM
					// See https://wp.me/p9o2xV-1LC#comment-5417
					_atomic_platform_managed_symlink( 'theme', $theme_to_symlink, 'latest' ),
				)
			);

			$managed_theme_path = false;
			foreach ( $candidate_managed_theme_paths as $candidate_path ) {
				if ( false !== realpath( $candidate_path ) ) {
					$managed_theme_path = $candidate_path;
					break;
				}
			}

			if ( false === $managed_theme_path ) {
				WP_CLI::error( "'$theme_to_symlink' is not a managed theme" );
			}

			$already_symlinked = false;
			if ( realpath( $theme_to_symlink ) === realpath( $managed_theme_path ) ) {
				$already_symlinked = true;
			} elseif ( is_dir( $theme_to_symlink ) ) {
				$permission_to_remove = false;
				if ( WP_CLI\Utils\get_flag_value( $assoc_args, 'remove-existing', false ) ) {
					$permission_to_remove = true;
				} elseif ( static::cli_confirm( "Theme '$theme_to_symlink' exists. Delete it and replace with symlink to managed theme?" ) ) {
					$permission_to_remove = true;
				}
				if ( ! $permission_to_remove ) {
					exit( -1 );
				}

				if ( is_link( $theme_to_symlink ) ) {
					if ( false === unlink( $theme_to_symlink ) ) {
						WP_CLI::error( "Failed to remove conflicting symlink '$theme_to_symlink'" );
						exit( -1 );
					}
				} else {
					WP_CLI::runcommand(
						"--skip-plugins --skip-themes theme delete '$theme_to_symlink' --force",
						array(
							'launch'     => false,
							'exit_error' => true,
						)
					);
				}
			}

			if ( $already_symlinked ) {
				WP_CLI::success( "Managed theme '$theme_to_symlink' is already symlinked" );
			} elseif ( symlink( $managed_theme_path, $theme_to_symlink ) ) {
				WP_CLI::success( "Added symlink to managed theme: $theme_to_symlink" );
			} else {
				WP_CLI::error( "Failed to symlink managed plugin: $theme_to_symlink" );
				exit( -1 );
			}

			$activate = WP_CLI\Utils\get_flag_value( $assoc_args, 'activate', false );
			if ( $activate ) {
				WP_CLI::runcommand(
					"--skip-plugins --skip-themes theme activate '$theme_to_symlink'",
					array(
						'launch'     => true,
						'exit_error' => true,
					)
				);
			}

			exit( 0 );
		}

		/**
		 * Installs an unmanaged theme into the site's themes directory, potentially replacing an existing version.
		 *
		 * ## OPTIONS
		 *
		 * <theme>
		 * : The name of the theme.
		 *
		 * [--remove-existing]
		 * : If there is an existing directory or symlink in the way, remove it without asking.
		 *
		 * [--activate]
		 * : Indicates that the theme should be activated.
		 *
		 * [--version]
		 * : The version to install.
		 */
		public static function use_unmanaged_theme( $args, $assoc_args = array() ) {
			$theme_to_install = $args[0];

			if ( get_stylesheet() === $theme_to_install ) {
				WP_CLI::error( "Theme '$theme_to_install' cannot be converted while it is active" );
			}

			$themes_dir = get_theme_root();
			if ( false === chdir( $themes_dir ) ) {
				WP_CLI::error( "Cannot switch to themes directory '$themes_dir'" );
			}

			$install_path = "$themes_dir/$theme_to_install";
			$already_exists = is_link( $install_path ) || file_exists( $install_path );

			$previous_version_path = false;
			if ( $already_exists ) {
				$permission_to_remove = false;
				if ( WP_CLI\Utils\get_flag_value( $assoc_args, 'remove-existing', false ) ) {
					$permission_to_remove = true;
				} elseif ( static::cli_confirm( "Plugin '$theme_to_install' exists. Delete it and replace with an unmanaged theme?" ) ) {
					$permission_to_remove = true;
				}
				if ( ! $permission_to_remove ) {
					exit( -1 );
				}

				WP_CLI::log( "Setting previous version aside until new install succeeds" );

				$uuid = wp_generate_uuid4();
				$previous_version_path = "$themes_dir/.previous-version-$theme_to_install-$uuid";
				if ( ! rename( $install_path, $previous_version_path ) ) {
					WP_CLI::error( "Failed to move previous version to $previous_version_path" );
				}
			}

			$command = "--skip-plugins --skip-themes theme install $theme_to_install --force";

			$version = WP_CLI\Utils\get_flag_value( $assoc_args, 'version', false );
			if ( false !== $version ) {
				$command = "$command --version=$version";
			}

			$result = WP_CLI::runcommand(
				$command,
				array(
					'return' => 'all',
					'launch' => true,
					'exit_error' => false,
				)
			);

			if ( 0 !== $result->return_code ) {
				WP_CLI::error( 'There was an error installing the theme', false );
				WP_CLI::log( $result->stderr );

				if ( $previous_version_path ) {
					WP_CLI::log( 'Restoring previous version...' );
					if ( ! rename( $previous_version_path, $install_path ) ) {
						WP_CLI::error(
							"Failed to restore previous version from $previous_version_path to $install_path",
							false
						);
					}
					WP_CLI::log( 'Done' );
				}


				exit( -1 );
			}

			WP_CLI::success( "Installed unmanaged theme: $theme_to_install" );

			$activate = WP_CLI\Utils\get_flag_value( $assoc_args, 'activate', false );
			if ( $activate ) {
				WP_CLI::runcommand(
					"--skip-plugins --skip-themes theme activate '$theme_to_install'",
					array(
						'launch'     => false,
						'exit_error' => true,
					)
				);
			}

			if ( $previous_version_path ) {
				WP_CLI::log( 'Cleaning up previous version...' );

				$removal_shell_command = 'rm -r ' . escapeshellarg( $previous_version_path );
				$removal_result_code = 0;
				passthru( $removal_shell_command, $removal_result_code );

				if ( 0 !== $removal_result_code ) {
					WP_CLI::error( "Unable to clean up previous version: $previous_version_path" );
				}

				WP_CLI::log( 'Done' );
			}

			exit( 0 );
		}

		/**
		 * Ask the user to confirm a yes/no question.
		 *
		 * @param  string $question The yes/no question to ask the user.
		 * @return boolean Whether the user confirmed or not.
		 */
		public static function cli_confirm( $question ) {
			fwrite( STDOUT, $question . ' [Y/n] ' );
			$answer = strtolower( trim( fgets( STDIN ) ) );
			return 'y' === $answer || ! $answer;
		}
	}

	if ( defined( 'WP_CLI' ) && WP_CLI ) {
		WP_CLI::add_command(
			'atomic plugin use-managed',
			array( 'Atomic_Platform_Managed_Software_Commands', 'use_managed_plugin' ) 
		);
		WP_CLI::add_command(
			'atomic plugin use-unmanaged',
			array( 'Atomic_Platform_Managed_Software_Commands', 'use_unmanaged_plugin' ) 
		);
		WP_CLI::add_command(
			'atomic theme use-managed',
			array( 'Atomic_Platform_Managed_Software_Commands', 'use_managed_theme' ) 
		);
		WP_CLI::add_command(
			'atomic theme use-unmanaged',
			array( 'Atomic_Platform_Managed_Software_Commands', 'use_unmanaged_theme' ) 
		);
	}
}