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' );
}