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.18
Disabled: pcntl_fork
Upload Files
File: /wordpress/mu-plugins/atomic-cli-dereferenced.php
<?php

/**
 * Helper utilities for working with dereferenced (development mode) sites.
 */
class Atomic_Dereferenced {

	private $freshen_timestamp = null;

	/**
	 * Update dereferenced code to the current latest managed version. the results will continue to be dereferenced.
	 * existing code will be moved into /tmp/ so that you may retrieve any modified code from them before removing
	 * the old copies.
	 *
	 * ## OPTIONS
	 *
	 * [--core]
	 * : Update WordPress. Use will default other types of code to false unless also specified
	 *
	 * [--drop-ins]
	 * : Update drop-ins. Use will default other types of code to false unless also specified
	 *
	 * [--plugins]
	 * : Update plugins. Use will default other types of code to false unless also specified
	 *
	 * [--mu-plugins]
	 * : Update mu-plugins. Use will default other types of code to false unless also specified
	 *
	 * [--themes]
	 * : Update themes. Use will default other types of code to false unless also specified
	 *
	 * [--no-core]
	 * : Do not update WordPress. Only effective when none of [ --core, --drop-ins, --plugins, --mu-plugins, --themes ] have been used
	 *
	 * [--no-drop-ins]
	 * : Do not update drop-ins. Only effective when none of [ --core, --drop-ins, --plugins, --mu-plugins, --themes ] have been used
	 *
	 * [--no-plugins]
	 * : Do not update plugins. Only effective when none of [ --core, --drop-ins, --plugins, --mu-plugins, --themes ] have been used
	 *
	 * [--no-mu-plugins]
	 * : Do not update mu-plugins. Only effective when none of [ --core, --drop-ins, --plugins, --mu-plugins, --themes ] have been used
	 *
	 * [--no-themes]
	 * : Do not update themes. Only effective when none of [ --core, --drop-ins, --plugins, --mu-plugins, --themes ] have been used
	 *
	 * [--prefer-premium-themes]
	 * : Prefer to use premium themes over public and core themes
	 *
	 * [--prefer-pub-themes]
	 * : Prefer to use pub themes over premium ( unless --prefer-premium-themes is used ) and core themes
	 *
	 * [--prefer-core-themes]
	 * :Prefer to use core themes over premium ( unless --prefer-premium-themes is used ) and pub themes ( unless --prefer-pub-themes is used )
	 */
	public function freshen( $args, $assoc_args ) {
		$this->freshen_timestamp = time();

		$defaults = array(
			'core'                  => null,
			'drop-ins'              => null,
			'mu-plugins'            => null,
			'plugins'               => null,
			'themes'                => null,
			'prefer-premium-themes' => false,
			'prefer-pub-themes'     => false,
			'prefer-core-themes'    => false,
		);

		$flags = wp_parse_args( $assoc_args, $defaults );

		$yes_found = false;
		foreach( array_keys( $defaults ) as $flag ) {
			switch ( $flag ) {
				case 'prefer-premium-themes':
				case 'prefer-pub-themes':
				case 'prefer-core-themes':
					break;
				default:
					if ( true === $flags[ $flag ] ) {
						$yes_found = true;
					}
			}
			if ( true === $yes_found ) {
				break;
			}
		}

		foreach( array_keys( $defaults ) as $flag ) {
			switch ( $flag ) {
				case 'prefer-premium-themes':
				case 'prefer-pub-themes':
				case 'prefer-core-themes':
					break;
				default:
				if ( null === $flags[ $flag ] ) {
					if ( true === $yes_found ) {
						$flags[ $flag ] = false;
					} else {
						$flags[ $flag ] = true;
					}
				}
			}
		}

		if ( true === $flags['core'] ) {
			chdir( dirname( WP_CONTENT_DIR ) );
			if ( is_link( '__wp__' ) ) {
				WP_CLI::log('	__wp__ is a symlink, skipping' );
			} else {
				WP_CLI::success( "Updating WordPress" );
				$this->freshen_replace( '__wp__', '/wordpress/core/latest/' );
			}
		}

		if ( true === $flags['drop-ins'] ) {
			WP_CLI::success( "Scanning drop-ins" );
			chdir( WP_CONTENT_DIR );
			foreach( glob( '*' ) as $dropin ) {
				if ( in_array( $dropin, array( 'plugins', 'mu-plugins', 'uploads', 'themes' ) ) ) {
					continue;
				}
				if ( true === is_link( $dropin ) ) {
					WP_CLI::log( sprintf( ' %s is a symlink, skipping', $dropin) );
					continue;
				}
				$possible_source = sprintf( '/wordpress/drop-ins/%s', $dropin );
				if ( true !== file_exists( $possible_source ) ) {
					WP_CLI::log( sprintf( ' %s is not a platform managed drop-in', $dropin ) );
					continue;
				}
				$this->freshen_replace( $dropin, $possible_source );
			}
		}

		if ( true === $flags['mu-plugins'] ) {
			WP_CLI::success( "Scanning mu-plugins" );
			chdir( WP_CONTENT_DIR . '/mu-plugins' );
			foreach( glob( '*' ) as $plugin ) {
				if ( true === is_link( $plugin ) ) {
					WP_CLI::log( sprintf( '	%s is a symlink, skipping', $plugin ) );
					continue;
				}

				$possible_source = sprintf( '/wordpress/mu-plugins/%s/latest/', $plugin );

				// special cases
				switch( $plugin ) {
					case 'wpcomsh-loader.php':
						$possible_source = sprintf( '/wordpress/plugins/wpcomsh/latest/%s', $plugin );
						break;
					case 'wpcomsh':
						$possible_source = sprintf( '/wordpress/plugins/%s/latest/', $plugin );
						break;
				}

				if ( true !== file_exists( $possible_source ) ) {
					WP_CLI::log( sprintf( '	%s is not a platform managed plugin', $plugin ) );
					continue;
				}

				$this->freshen_replace( $plugin, $possible_source );
			}
		}

		if ( true === $flags['plugins'] ) {
			WP_CLI::success( "Scanning plugins" );
			chdir( WP_CONTENT_DIR . '/plugins' );
			foreach( glob( '*' ) as $plugin ) {
				if ( true === is_link( $plugin ) ) {
					WP_CLI::log( sprintf( '	%s is a symlink, skipping', $plugin ) );
					continue;
				}

				$possible_source = sprintf( '/wordpress/plugins/%s/latest/', $plugin );
				if ( true !== file_exists( $possible_source ) ) {
					WP_CLI::log( sprintf( '	%s is not a platform managed plugin', $plugin ) );
					continue;
				}

				$this->freshen_replace( $plugin, $possible_source );
			}
		}

		if ( true === $flags['themes'] ) {
			WP_CLI::success( "Scanning themes" );
			chdir( WP_CONTENT_DIR . '/themes' );
			foreach( glob( '*' ) as $theme ) {
				if ( true === is_link( $theme ) ) {
					WP_CLI::log( sprintf( '	%s is a symlink, skipping', $theme ) );
					continue;
				}

				// Order of precedence
				$possible_sources = array(
					sprintf( '/wordpress/themes/premium/%s/', $theme ),
					sprintf( '/wordpress/themes/pub/%s/', $theme ),
					sprintf( '/wordpress/themes/%s/latest/', $theme ),
				);
				if ( true === $flags['prefer-core-themes'] ) {
					array_unshift( $possible_sources, sprintf( '/wordpress/themes/%s/latest/', $theme ) );
				}
				if ( true === $flags['prefer-pub-themes'] ) {
					array_unshift( $possible_sources, sprintf( '/wordpress/themes/pub/%s/', $theme ) );
				}
				if ( true === $flags['prefer-premium-themes'] ) {
					array_unshift( $possible_sources, sprintf( '/wordpress/themes/premium/%s/', $theme ) );
				}

				$found_source = null;
				foreach( $possible_sources as $possible_source ) {
					if ( true !== file_exists( $possible_source ) ) {
						continue;
					}
					$found_source = $possible_source;
					break;
				}
				if ( null === $found_source ) {
					WP_CLI::log( sprintf( '	%s is not a platform managed theme', $theme ) );
					continue;
				}
				$this->freshen_replace( $theme, $found_source );
			}
		}

		$this->freshen_maybe_warn();
	}

	private function freshen_maybe_remove( $filesystem_location ) {
		if ( file_exists( $filesystem_location ) ) {
			WP_CLI::warning( sprintf( '%s already exists. removing', $filesystem_location ) );
			if ( is_dir( $filesystem_location ) ) {
				if ( true !== $this->freshen_rmdir( $filesystem_location ) ) {
					WP_CLI::error( sprintf( 'Unable to rmdir %s, aborting', $filesystem_location ) );
					exit( 2 );
				}
				WP_CLI::log( sprintf( '	Successfully removed %s', $filesystem_location ) );
			} else {
				if ( true !== unlink( $filesystem_location ) ) {
					WP_CLI::error( sprintf( 'Unable to unlink %s, aborting', $filesystem_location ) );
					exit( 2 );
				}
				WP_CLI::log( sprintf( '	Successfully removed %s', $filesystem_location ) );
			}
		}
	}

	private function freshen_maybe_warn() {
		exec( 'du -hs /tmp/* | grep -E "/tmp/old-"', $output, $error );
		if ( count( $output ) < 1 ) {
			return;
		}
		WP_CLI::log( '' );
		WP_CLI::warning( 'You now have backup files stored in /tmp as follows:' );
		WP_CLI::log( '' );
		foreach( $output as $line ) {
			WP_CLI::warning( sprintf( "\t%s", trim( $line ) ) );
		}
		WP_CLI::log( '' );
		WP_CLI::log( 'These files and directories have been placed here in case you needed to retrieve any changes from' );
		WP_CLI::log( 'them it is your responsibility to remove these files once you have done so, or decided that there' );
		WP_CLI::log( 'is no need for them any longer. If you run out of space it will be your fault.' );
	}

	private function freshen_copy( $from, $to ) {
		$command = sprintf(
			'/bin/cp -dR --preserve=timestamps %s %s',
			escapeshellarg( $from ),
			escapeshellarg( $to )
		);
		WP_CLI::log( "\t\t$command" );
		exec( $command, $output, $error );
		if ( 0 !== $error ) {
			WP_CLI::error( sprintf( 'Unable to copy %s to %s: %d', $from, $to, $error ) );
			exit( 3 );
		}
	}

	private function freshen_rmdir( $slug ) {
		$command = sprintf( '/bin/rm -fr %s', escapeshellarg( $slug ) );
		WP_CLI::log( "\t\t$command" );

		exec( $command, $output, $error );
		if ( 0 !== $error ) {
			WP_CLI::error( sprintf( 'Unable to rm -r %s %d', $slug, $error ) );
			exit( 3 );
		}
	}

	private function freshen_replace( $slug, $source ) {
		WP_CLI::success( sprintf( 'Found %s managed at %s', $slug, $source ) );

		$temp_new = sprintf( '.tmp-Atomic_Dereferenced-%s', $slug );
		$temp_old = sprintf( '/tmp/old-%d-%s', $this->freshen_timestamp, $slug );

		WP_CLI::log( sprintf( '	Backing up %s to %s', $slug, $temp_old ) );
		$this->freshen_copy( $slug, $temp_old );

		WP_CLI::log( sprintf( '	Copying %s to %s', $source, $temp_new ) );
		$this->freshen_maybe_remove( $temp_new );
		$this->freshen_copy( $source, $temp_new );

		WP_CLI::log( sprintf( '	Replacing %s with %s', $slug, $temp_new ) );
		$this->freshen_rmdir( $slug );
		WP_CLI::log( sprintf( '		rename %s %s', $temp_new, $slug ) );
		rename( $temp_new, $slug );

		WP_CLI::success( sprintf( '%s updated successfully', $slug ) );
	}
}

if ( class_exists( 'WP_CLI' ) ) {
	WP_CLI::add_command( 'dereferenced', 'Atomic_Dereferenced' );
}