Skip to content
Snippets Groups Projects
civicrm.php 40.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • Kevin Cristiano's avatar
    Kevin Cristiano committed
    <?php
    
    /*
     +--------------------------------------------------------------------+
    
     | CiviCRM version 5                                                  |
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     +--------------------------------------------------------------------+
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     | Copyright CiviCRM LLC (c) 2004-2018                                |
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     +--------------------------------------------------------------------+
     | This file is a part of CiviCRM.                                    |
     |                                                                    |
     | CiviCRM is free software; you can copy, modify, and distribute it  |
     | under the terms of the GNU Affero General Public License           |
     | Version 3, 19 November 2007 and the CiviCRM Licensing Exception.   |
     |                                                                    |
     | CiviCRM is distributed in the hope that it will be useful, but     |
     | WITHOUT ANY WARRANTY; without even the implied warranty of         |
     | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               |
     | See the GNU Affero General Public License for more details.        |
     |                                                                    |
     | You should have received a copy of the GNU Affero General Public   |
     | License and the CiviCRM Licensing Exception along                  |
     | with this program; if not, contact CiviCRM LLC                     |
     | at info[AT]civicrm[DOT]org. If you have questions about the        |
     | GNU Affero General Public License or the licensing of CiviCRM,     |
     | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
     +--------------------------------------------------------------------+
     */
    
    if ( ! defined( 'CIVICRM_WPCLI_LOADED' ) ) {
    	define( 'CIVICRM_WPCLI_LOADED', 1 );
    
    	/**
    	 * WP-CLI port of drush-civicrm integration
    	 * andyw@circle, 08/03/2014
    	 *
    	 * Distributed under the GNU Affero General Public License, version 3
    	 * http://www.gnu.org/licenses/agpl-3.0.html
    	 */
    
    	class CiviCRM_Command extends WP_CLI_Command {
    
    		private $args, $assoc_args;
    
    		/**
    		 * WP-CLI integration with CiviCRM.
    		 *
    		 * wp civicrm api
    		 * ===============
    		 * Command for accessing CiviCRM APIs. Syntax is identical to drush cvap.
    		 *
    		 * wp civicrm cache-clear
    		 * ===============
    		 * Command for accessing clearing cache.  Equivilant of running civicrm/admin/setting/updateConfigBackend&reset=1
    		 *
    		 * wp civicrm enable-debug
    		 * ===============
    		 * Command for to turn debug on.
    		 *
    		 * wp civicrm disable-debug
    		 * ===============
    		 * Command for to turn debug off.
    		 *
    		 * wp civicrm member-records
    		 * ===============
    		 * Run the CiviMember UpdateMembershipRecord cron ( civicrm member-records ).
    		 *
    		 * wp civicrm process-mail-queue
    		 * ===============
    		 * Process pending CiviMail mailing jobs.
    		 * Example:
    		 * wp civicrm process-mail-queue -u admin
    		 *
    		 * wp civicrm rest
    		 * ===============
    		 * Rest interface for accessing CiviCRM APIs. It can return xml or json formatted data.
    		 *
    		 * wp civicrm restore
    		 * ==================
    		 * Restore CiviCRM codebase and database back from the specified backup directory
    		 *
    		 * wp civicrm sql-conf
    		 * ===================
    		 * Show civicrm database connection details.
    		 *
    		 * wp civicrm sql-connect
    		 * ======================
    		 * A string which connects to the civicrm database.
    		 *
    		 * wp civicrm sql-cli
    		 * ==================
    		 * Quickly enter the mysql command line.
    		 *
    		 * wp civicrm sql-dump
    		 * ===================
    		 * Prints the whole CiviCRM database to STDOUT or save to a file.
    		 *
    		 * wp civicrm sql-query
    		 * ====================
    		 * Usage: wp civicrm sql-query <query> <options>...
    		 * <query> is a SQL statement, which can alternatively be passed via STDIN. Any additional arguments are passed to the mysql command directly.";
    		 *
    		 * wp civicrm update-cfg
    		 * =====================
    		 * Update config_backend to correct config settings, especially when the CiviCRM site has been cloned / migrated.
    		 *
    		 * wp civicrm upgrade
    		 * ==================
    		 * Take backups, replace CiviCRM codebase with new specified tarfile and upgrade database by executing the CiviCRM upgrade process - civicrm/upgrade?reset=1. Use civicrm-restore to revert to previous state in case anything goes wrong.
    		 *
    		 * wp civicrm upgrade-db
    		 * =====================
    		 * Run civicrm/upgrade?reset=1 just as a web browser would.
    		 *
    		 * wp civicrm install
    		 * ===============
    		 * Command for to install CiviCRM.  The install command requires that you have downloaded a tarball or zip file first.
    		 * Options:
    		 * --dbhost            MySQL host for your WordPress/CiviCRM database. Defaults to localhost.
    		 * --dbname            MySQL database name of your WordPress/CiviCRM database.
    		 * --dbpass            MySQL password for your WordPress/CiviCRM database.
    		 * --dbuser            MySQL username for your WordPress/CiviCRM database.
    		 * --lang              Default language to use for installation.
    		 * --langtarfile       Path to your l10n tar.gz file.
    		 * --site_url          Base Url for your WordPress/CiviCRM website without http ( e.g. mysite.com )
    		 * --ssl               Using ssl for your WordPress/CiviCRM website if set to on ( e.g. --ssl=on )
    		 * --tarfile           Path to your CiviCRM tar.gz file.
    		 *
    		 */
    
    		public function __invoke( $args, $assoc_args ) {
    
    			$this->args       = $args;
    			$this->assoc_args = $assoc_args;
    
    			# define command router
    			$command_router = array(
    				'api'                => 'api',
    				'cache-clear'        => 'cacheClear',
    				'enable-debug'       => 'enableDebug',
    				'disable-debug'       => 'disableDebug',
    				'install'            => 'install',
    				'member-records'     => 'memberRecords',
    				'process-mail-queue' => 'processMailQueue',
    				'rest'               => 'rest',
    				'restore'            => 'restore',
    				'sql-cli'            => 'sqlCLI',
    				'sql-conf'           => 'sqlConf',
    				'sql-connect'        => 'sqlConnect',
    				'sql-dump'           => 'sqlDump',
    				'sql-query'          => 'sqlQuery',
    				'update-cfg'         => 'updateConfig',
    				'upgrade'            => 'upgrade',
    				'upgrade-db'         => 'upgradeDB',
    			 );
    
    			# get command
    			$command = array_shift( $args );
    
    			# check for existence of Civi ( except for command 'install' )
    			if ( ! function_exists( 'civicrm_initialize' ) and 'install' != $command ) {
    				return WP_CLI::error( 'Unable to find CiviCRM install.' );
    			}
    
    			# check existence of router entry / handler method
    			if ( ! isset( $command_router[ $command ] ) or ! method_exists( $this, $command_router[ $command ] ) ) {
    				return WP_CLI::error( "Unrecognized command - '$command'" );
    			}
    
    			# run command
    			return $this->{$command_router[ $command ]}();
    
    		}
    
    		/**
    		 * Implementation of command 'api'
    		 */
    		private function api() {
    
    			$defaults = array( 'version' => 3 );
    
    			array_shift( $this->args );
    			list( $entity, $action ) = explode( '.', $this->args[0] );
    
    			array_shift( $this->args );
    
    			$format = $this->getOption( 'in', 'args' );
    			switch ( $format ) {
    
    
    				# input params supplied via args ..
    				case 'args':
    					$params = $defaults;
    					foreach ( $this->args as $arg ) {
    
    						preg_match( '/^([^=]+)=(.*)$/', $arg, $matches );
    
    						$params[ $matches[1] ] = $matches[2];
    					}
    					break;
    
    				# input params supplied via json ..
    				case 'json':
    					$json   = stream_get_contents( STDIN );
    					$params = ( empty( $json ) ? $defaults : array_merge( $defaults, json_decode( $json, true ) ) );
    					break;
    
    				default:
    					WP_CLI::error( 'Unknown format: ' . $format );
    					break;
    			}
    
    			civicrm_initialize();
    
    			// CRM-18062: Set CiviCRM timezone if any
    			$wp_base_timezone = date_default_timezone_get();
    			$wp_user_timezone = $this->getOption( 'timezone', get_option( 'timezone_string' ) );
    			if ( $wp_user_timezone ) {
    				date_default_timezone_set( $wp_user_timezone );
    				CRM_Core_Config::singleton()->userSystem->setMySQLTimeZone();
    			}
    
    			$result = civicrm_api( $entity, $action, $params );
    
    			// restore WP's timezone
    			if ( $wp_base_timezone ) {
    				date_default_timezone_set( $wp_base_timezone );
    			}
    
    			switch ( $this->getOption( 'out', 'pretty' ) ) {
    
    				# pretty-print output ( default )
    				case 'pretty':
    					WP_CLI::line( print_r( $result, true ) );
    					break;
    
    				# display output as json
    				case 'json':
    					WP_CLI::line( json_encode( $result ) );
    					break;
    
    				default:
    					return WP_CLI::error( 'Unknown format: ' . $format );
    
    			}
    
    		}
    
    		/**
    		 * Implementation of command 'cache-clear'
    		 */
    		private function cacheClear() {
    
    			civicrm_initialize();
    			require_once 'CRM/Core/Config.php';
    			$config = CRM_Core_Config::singleton();
    
    			# clear db caching
    			$config->clearDBCache();
    
    			# also cleanup the templates_c directory
    			$config->cleanup( 1, false );
    
    			# also cleanup the session object
    			$session = CRM_Core_Session::singleton();
    			$session->reset( 1 );
    
    		}
    
    		/**
    		 * Implementation of command 'enable-debug'
    		 */
    		private function enableDebug() {
    			civicrm_initialize();
    			Civi::settings()->add( array(
    				'debug_enabled' => 1,
    				'backtrace' => 1,
    			) );
    			WP_CLI::success( 'Debug setting enabled.' );
    		}
    
    		/**
    		 * Implementation of command 'disable-debug'
    		 */
    		private function disableDebug() {
    			civicrm_initialize();
    			Civi::settings()->add( array(
    				'debug_enabled' => 0,
    				'backtrace' => 0,
    			) );
    			WP_CLI::success( 'Debug setting disabled.' );
    		}
    
    		/**
    		 * Implementation of command 'install'
    		 */
    		private function install() {
    
    			# validate
    
    			if ( ! $dbuser = $this->getOption( 'dbuser', false ) ) {
    				return WP_CLI::error( 'CiviCRM database username not specified.' );
    			}
    
    			if ( ! $dbpass = $this->getOption( 'dbpass', false ) ) {
    				return WP_CLI::error( 'CiviCRM database password not specified.' );
    			}
    
    			if ( ! $dbhost = $this->getOption( 'dbhost', false ) ) {
    				return WP_CLI::error( 'CiviCRM database host not specified.' );
    			}
    
    			if ( ! $dbname = $this->getOption( 'dbname', false ) ) {
    				return WP_CLI::error( 'CiviCRM database name not specified.' );
    			}
    
    			if ( $lang = $this->getOption( 'lang', false ) and ! $langtarfile = $this->getOption( 'langtarfile', false ) ) {
    				return WP_CLI::error( 'CiviCRM language tarfile not specified.' );
    			}
    
    			# begin install
    
    			if ( $plugin_path = $this->getOption( 'destination', false ) ) {
    				$plugin_path = ABSPATH . $plugin_path;
    			} else {
    				$plugin_path = WP_PLUGIN_DIR . '/civicrm';
    			}
    
    			global $crmPath;
    			$crmPath = "$plugin_path/civicrm";
    			$crm_files_present = is_dir( $crmPath );
    
    			# extract the archive
    			if ( $this->getOption( 'tarfile', false ) ) {
    				# should probably never get to here as Wordpress Civi comes in a zip file, but
    				# just in case that ever changes ..
    				if ( $crm_files_present ) {
    					return WP_CLI::error( 'Existing CiviCRM found. No action taken.' );
    				}
    
    				if ( ! $this->untar( dirname( $plugin_path ) ) ) {
    					return WP_CLI::error( 'Error extracting tarfile' );
    				}
    			} elseif ( $this->getOption( 'zipfile', false ) ) {
    				if ( $crm_files_present ) {
    					return WP_CLI::error( 'Existing CiviCRM found. No action taken.' );
    				}
    
    				if ( ! $this->unzip( dirname( $plugin_path ) ) ) {
    					return WP_CLI::error( 'Error extracting zipfile' );
    				}
    			} elseif ( $crm_files_present ) {
    				// Site is already extracted (which is how we're running this
    				// script); we just need to run the installer.
    
    			} else {
    				return WP_CLI::error( 'No zipfile specified, use --zipfile=path/to/zipfile or extract file ahead of time' );
    			}
    
    			# include civicrm installer helper file
    			$civicrm_installer_helper = "$crmPath/install/civicrm.php";
    
    			if ( ! file_exists( $civicrm_installer_helper ) ) {
    				return WP_CLI::error( 'Archive could not be unpacked OR CiviCRM installer helper file is missing.' );
    			}
    
    			if ( $crm_files_present ) {
    				// We were using a directory that was already there.
    				WP_CLI::success( 'Using installer files found on the site.' );
    			} else {
    				// We must've just unpacked the archive because it wasn't there
    				// before.
    				WP_CLI::success( 'Archive unpacked.' );
    			}
    			require_once $civicrm_installer_helper;
    
    			if ( '' != $lang ) {
    				if ( ! $this->untar( $plugin_path, 'langtarfile' ) ) {
    					return WP_CLI::error( 'No language tarfile specified, use --langtarfile=path/to/tarfile' );
    				}
    			}
    
    			# create files dirs
    			$upload_dir = wp_upload_dir();
    			$settings_dir = $upload_dir['basedir'] . DIRECTORY_SEPARATOR . 'civicrm' . DIRECTORY_SEPARATOR;
    			civicrm_setup( $upload_dir['basedir'] . DIRECTORY_SEPARATOR );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    			WP_CLI::launch( "chmod 0755 $settings_dir -R" );
    
    
    			# now we've got some files in place, require PEAR DB and check db setup
    			$dsn = "mysql://{$dbuser}:{$dbpass}@{$dbhost}/{$dbname}?new_link=true";
    			$dsn_nodb = "mysql://{$dbuser}:{$dbpass}@{$dbhost}";
    
    			if ( ! defined( 'DB_DSN_MODE' ) ) {
    				define( 'DB_DSN_MODE', 'auto' );
    			}
    
    			require_once "$crmPath/packages/DB.php";
    
    			$db = DB::connect( $dsn );
    			if ( DB::iserror( $db ) ) {
    				$db = DB::connect( $dsn_nodb );
    				if ( DB::iserror( $db ) ) {
    					return WP_CLI::error( 'Unable to connect to database. Please re-check credentials.' );
    				}
    				$db->query( "CREATE DATABASE $dbname" );
    				if ( DB::iserror( $db ) ) {
    					return WP_CLI::error( 'CiviCRM database was not found. Failed to create one.' );
    				}
    				$db->disconnect();
    			}
    
    			# install db
    			global $sqlPath;
    
    			# setup database with civicrm structure and data
    			WP_CLI::line( 'Loading CiviCRM database structure ..' );
    			civicrm_source( $dsn, $sqlPath . '/civicrm.mysql' );
    			WP_CLI::line( 'Loading CiviCRM database with required data ..' );
    
    			# testing the translated sql files availability
    			$data_file = $sqlPath . '/civicrm_data.mysql';
    			$acl_file  = $sqlPath . '/civicrm_acl.mysql';
    
    			if ( '' != $lang ) {
    
    				if ( file_exists( $sqlPath . '/civicrm_data.' . $lang . '.mysql' )
    					and file_exists( $sqlPath . '/civicrm_acl.' . $lang . '.mysql' )
    					and '' != $lang
    				 ) {
    					$data_file = $sqlPath . '/civicrm_data.' . $lang . '.mysql';
    					$acl_file = $sqlPath . '/civicrm_acl.' . $lang . '.mysql';
    				} else {
    					WP_CLI::warning( "No sql files could be retrieved for '$lang' using default language." );
    				}
    			}
    
    			civicrm_source( $dsn, $data_file );
    			civicrm_source( $dsn, $acl_file );
    
    			WP_CLI::success( 'CiviCRM database loaded successfully.' );
    
    			# generate civicrm.settings.php file
    			global $tplPath;
    			if ( ! file_exists( $tplPath . 'civicrm.settings.php.template' ) ) {
    				return WP_CLI::error( 'Could not find CiviCRM settings template and therefore could not create settings file.' );
    			}
    
    			WP_CLI::line( 'Generating civicrm settings file ..' );
    
    			if ( $base_url = $this->getOption( 'site_url', false ) ) {
    				$ssl      = $this->getOption( 'ssl', false );
    				$protocol = ( 'on' == $ssl ? 'https' : 'http' );
    			}
    
    			$base_url = ! $base_url ? get_bloginfo( 'url' ) : $protocol . '://' . $base_url;
    			if ( substr( $base_url, -1 ) != '/' ) {
    				$base_url .= '/';
    			}
    			$params = array(
    				'crmRoot'            => $crmPath . '/',
    				'templateCompileDir' => "{$settings_dir}templates_c",
    				'frontEnd'           => 0,
    				'cms'                => 'WordPress',
    				'baseURL'            => $base_url,
    				'dbUser'             => $dbuser,
    				'dbPass'             => $dbpass,
    				'dbHost'             => $dbhost,
    				'dbName'             => $dbname,
    				'CMSdbUser'          => DB_USER,
    				'CMSdbPass'          => DB_PASSWORD,
    				'CMSdbHost'          => DB_HOST,
    				'CMSdbName'          => DB_NAME,
    				'siteKey'            => md5(rand() . mt_rand() . rand() . uniqid('', TRUE) . $params['baseURL']),
    			 );
    
    			$str = file_get_contents( $tplPath . 'civicrm.settings.php.template' );
    			foreach ( $params as $key => $value ) {
    				$str = str_replace( '%%' . $key . '%%', $value, $str );
    			}
    
    			$str = trim( $str );
    
    			$config_file = "{$settings_dir}civicrm.settings.php";
    			civicrm_write_file( $config_file, $str );
    			WP_CLI::launch( "chmod 0644 $config_file" );
    			WP_CLI::success( sprintf( 'Settings file generated: %s', $config_file ) );
    
    			# activate plugin and we're done
    			@WP_CLI::run_command( array( 'plugin', 'activate', 'civicrm' ), array() );
    			WP_CLI::success( 'CiviCRM installed.' );
    
    		}
    
    		/**
    		 * Implementation of command 'member-records'
    		 */
    		private function memberRecords() {
    
    			civicrm_initialize();
    
    			if ( substr( CRM_Utils_System::version(), 0, 3 ) >= '4.3' ) {
    
    				$job = new CRM_Core_JobManager();
    				$job->executeJobByAction( 'job', 'process_membership' );
    				WP_CLI::success( "Executed 'process_membership' job." );
    
    			} else {
    
    				$_REQUEST['name'] = $this->getOption( 'civicrm_cron_username', null );
    				$_REQUEST['pass'] = $this->getOption( 'civicrm_cron_password', null );
    				$_REQUEST['key']  = $this->getOption( 'civicrm_sitekey', null );
    
    				global $argv;
    				$argv = array(
    					0 => 'drush',
    					1 => '-u' . $_REQUEST['name'],
    					2 => '-p' . $_REQUEST['pass'],
    					3 => '-s' . $this->getOption( 'uri', false ),
    				 );
    
    				# if ( !defined( 'CIVICRM_CONFDIR' ) ) {
    				# $plugins_dir = plugin_dir_path( __FILE__ );
    				#     define( 'CIVICRM_CONFDIR', $plugins_dir );
    				# }
    
    				include 'bin/UpdateMembershipRecord.php';
    
    			}
    
    		}
    
    		/**
    		 * Implementation of command 'process-mail-queue'
    		 */
    		private function processMailQueue() {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			civicrm_initialize();
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			if ( substr( CRM_Utils_System::version(), 0, 3 ) >= '4.3' ) {
    
    				$job = new CRM_Core_JobManager();
    				$job->executeJobByAction( 'job', 'process_mailing' );
    				WP_CLI::success( "Executed 'process_mailing' job." );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    				$result = civicrm_api( 'Mailing', 'Process', array( 'version' => 3 ) );
    				if ( $result['is_error'] ) {
    					WP_CLI::error( $result['error_message'] );
    				}
    			}
    
    		}
    
    		/**
    		 * Implementation of command 'rest'
    		 */
    		private function rest() {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			civicrm_initialize();
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			if ( ! $query = $this->getOption( 'query', false ) ) {
    				return WP_CLI::error( 'query not specified.' );
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			$query     = explode( '&', $query );
    			$_GET['q'] = array_shift( $query );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			foreach ( $query as $key_val ) {
    				list( $key, $val ) = explode( '=', $key_val );
    				$_REQUEST[ $key ]  = $val;
    				$_GET[ $key ]      = $val;
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			require_once 'CRM/Utils/REST.php';
    			$rest = new CRM_Utils_REST();
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			require_once 'CRM/Core/Config.php';
    			$config = CRM_Core_Config::singleton();
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			global $civicrm_root;
    			// adding dummy script, since based on this api file path is computed.
    			$_SERVER['SCRIPT_FILENAME'] = "$civicrm_root/extern/rest.php";
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			if ( isset( $_GET['json'] ) && $_GET['json'] ) {
    				header( 'Content-Type: text/javascript' );
    			} else {
    				header( 'Content-Type: text/xml' );
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			echo $rest->run( $config );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    		/**
    		 * Implementation of command 'restore'
    		 */
    		private function restore() {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			# validate ..
    			$restore_dir = $this->getOption( 'restore-dir', false );
    			$restore_dir = rtrim( $restore_dir, '/' );
    			if ( ! $restore_dir ) {
    				return WP_CLI::error( 'Restore-dir not specified.' );
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			$sql_file = $restore_dir . '/civicrm.sql';
    			if ( ! file_exists( $sql_file ) ) {
    				return WP_CLI::error( 'Could not locate civicrm.sql file in the restore directory.' );
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			$code_dir = $restore_dir . '/civicrm';
    			if ( ! is_dir( $code_dir ) ) {
    				return WP_CLI::error( 'Could not locate civicrm directory inside restore-dir.' );
    			} elseif ( ! file_exists( "$code_dir/civicrm/civicrm-version.txt" ) and ! file_exists( "$code_dir/civicrm/civicrm-version.php" ) ) {
    				return WP_CLI::error( 'civicrm directory inside restore-dir, doesn\'t look to be a valid civicrm codebase.' );
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			# prepare to restore ..
    			$date = date( 'YmdHis' );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			civicrm_initialize();
    			global $civicrm_root;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			$civicrm_root_base = explode( '/', $civicrm_root );
    			array_pop( $civicrm_root_base );
    			$civicrm_root_base = implode( '/', $civicrm_root_base ) . '/';
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			$basepath = explode( '/', $civicrm_root );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			if ( ! end( $basepath ) ) {
    				array_pop( $basepath );
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			array_pop( $basepath );
    			$project_path = implode( '/', $basepath ) . '/';
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			$wp_root = ABSPATH;
    			$restore_backup_dir = $this->getOption( 'backup-dir', $wp_root . '/../backup' );
    			$restore_backup_dir = rtrim( $restore_backup_dir, '/' );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			# get confirmation from user -
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			if ( ! defined( 'CIVICRM_DSN' ) ) {
    				WP_CLI::error( 'CIVICRM_DSN is not defined.' );
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			$db_spec = DB::parseDSN( CIVICRM_DSN );
    			WP_CLI::line( '' );
    			WP_CLI::line( 'Process involves:' );
    			WP_CLI::line( sprintf( "1. Restoring '\$restore-dir/civicrm' directory to '%s'.", $civicrm_root_base ) );
    			WP_CLI::line( sprintf( "2. Dropping and creating '%s' database.", $db_spec['database'] ) );
    			WP_CLI::line( "3. Loading '\$restore-dir/civicrm.sql' file into the database." );
    			WP_CLI::line( '' );
    			WP_CLI::line( sprintf( "Note: Before restoring a backup will be taken in '%s' directory.", "$restore_backup_dir/plugins/restore" ) );
    			WP_CLI::line( '' );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			WP_CLI::confirm( 'Do you really want to continue?' );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			$restore_backup_dir .= '/plugins/restore/' . $date;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    			if ( ! mkdir( $restore_backup_dir, 0755, true ) ) {
    
    				return WP_CLI::error( 'Failed creating directory: ' . $restore_backup_dir );
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			# 1. backup and restore codebase
    			WP_CLI::line( 'Restoring civicrm codebase ..' );
    			if ( is_dir( $project_path ) && ! rename( $project_path, $restore_backup_dir . '/civicrm' ) ) {
    				return WP_CLI::error( sprintf( "Failed to take backup for '%s' directory", $project_path ) );
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			if ( ! rename( $code_dir, $project_path ) ) {
    				return WP_CLI::error( "Failed to restore civicrm directory '%s' to '%s'", $code_dir, $project_path );
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			WP_CLI::success( 'Codebase restored.' );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			# 2. backup, drop and create database
    			WP_CLI::run_command(
    				array( 'civicrm', 'sql-dump' ),
    				array( 'result-file' => $restore_backup_dir . '/civicrm.sql' )
    			);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			WP_CLI::success( 'Database backed up.' );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			# prepare a mysql command-line string for issuing
    			# db drop / create commands
    			$command = sprintf(
    				'mysql --user=%s --password=%s',
    				$db_spec['username'],
    				$db_spec['password']
    			);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			if ( isset( $db_spec['hostspec'] ) ) {
    				$command .= ' --host=' . $db_spec['hostspec'];
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			if ( isset( $dsn['port'] ) and ! mpty( $dsn['port'] ) ) {
    				$command .= ' --port=' . $db_spec['port'];
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			# attempt to drop old database
    			if ( system( $command . sprintf( ' --execute="DROP DATABASE IF EXISTS %s"', $db_spec['database'] ) ) ) {
    				return WP_CLI::error( 'Could not drop database: ' . $db_spec['database'] );
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			WP_CLI::success( 'Database dropped.' );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			# attempt to create new database
    			if ( system( $command . sprintf( ' --execute="CREATE DATABASE %s"', $db_spec['database'] ) ) ) {
    				WP_CLI::error( 'Could not create new database: ' . $db_spec['database'] );
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			WP_CLI::success( 'Database created.' );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			# 3. restore database
    			WP_CLI::line( 'Loading civicrm.sql file from restore-dir ..' );
    			system( $command . ' ' . $db_spec['database'] . ' < ' . $sql_file );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			WP_CLI::success( 'Database restored.' );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			WP_CLI::line( 'Clearing caches..' );
    			WP_CLI::run_command( array( 'civicrm', 'cache-clear' ) );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			WP_CLI::success( 'Restore process completed.' );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    		/**
    		 * Implementation of command 'sql-conf'
    		 */
    		private function sqlConf() {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			civicrm_initialize();
    			if ( ! defined( 'CIVICRM_DSN' ) ) {
    				WP_CLI::error( 'CIVICRM_DSN is not defined.' );
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			WP_CLI::line( print_r( DB::parseDSN( CIVICRM_DSN ), true ) );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    		/**
    		 * Implementation of command 'sql-connect'
    		 */
    		private function sqlConnect() {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			civicrm_initialize();
    			if ( ! defined( 'CIVICRM_DSN' ) ) {
    				return WP_CLI::error( 'CIVICRM_DSN is not defined.' );
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			$dsn = DB::parseDSN( CIVICRM_DSN );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			$command = sprintf(
    				'mysql --database=%s --host=%s --user=%s --password=%s',
    				$dsn['database'],
    				$dsn['hostspec'],
    				$dsn['username'],
    				$dsn['password']
    			);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			if ( isset( $dsn['port'] ) and ! empty( $dsn['port'] ) ) {
    				$command .= ' --port=' . $dsn['port'];
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			return WP_CLI::line( $command );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    		/**
    		 * Implementation of command 'sql-dump'
    		 */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    		private function sqlDump() {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			# bootstrap Civi when we're not being called as part of an upgrade
    			if ( ! defined( 'CIVICRM_UPGRADE_ACTIVE' ) ) {
    				civicrm_initialize();
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			if ( ! defined( 'CIVICRM_DSN' ) and ! defined( 'CIVICRM_OLD_DSN' ) ) {
    				WP_CLI::error( 'DSN is not defined.' );
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			$dsn = self::parseDSN( defined( 'CIVICRM_DSN' ) ? CIVICRM_DSN : CIVICRM_OLD_DSN );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			$assoc_args       = $this->assoc_args;
    			$stdout           = ! isset( $assoc_args['result-file'] );
    			$command          = "mysqldump --no-defaults --host={$dsn['hostspec']} --user={$dsn['username']} --password='{$dsn['password']}' %s";
    			$command_esc_args = array( $dsn['database'] );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			if ( isset( $assoc_args['tables'] ) ) {
    				$tables = explode( ',', $assoc_args['tables'] );
    				unset( $assoc_args['tables'] );
    				$command .= ' --tables';
    				foreach ( $tables as $table ) {
    					$command .= ' %s';
    					$command_esc_args[] = trim( $table );
    				}
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			$escaped_command = call_user_func_array(
    				'\WP_CLI\Utils\esc_cmd',
    				array_merge(
    					array( $command ),
    					$command_esc_args
    				)
    			);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			\WP_CLI\Utils\run_mysql_command( $escaped_command, $assoc_args );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			if ( ! $stdout ) {
    				WP_CLI::success( sprintf( 'Exported to %s', $assoc_args['result-file'] ) );
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    		/**
    		 * Implementation of command 'sql-query'
    		 */
    		private function sqlQuery() {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			if ( ! isset( $this->args[0] ) ) {
    				WP_CLI::error( 'No query specified.' );
    				return;
    			}
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    			$query = $this->args[0];
    
    			civicrm_initialize();
    			if ( ! defined( 'CIVICRM_DSN' ) ) {
    				WP_CLI::error( 'CIVICRM_DSN is not defined.' );
    			}
    
    			$dsn = DB::parseDSN( CIVICRM_DSN );
    
    			$mysql_args = array(
    				'host'     => $dsn['hostspec'],
    				'database' => $dsn['database'],
    				'user'     => $dsn['username'],
    				'password' => $dsn['password'],
    				'execute'  => $query,
    			 );
    
    			\WP_CLI\Utils\run_mysql_command( 'mysql --no-defaults', $mysql_args );
    
    		}
    
    		/**
    		 * Implementation of command 'sql-cli'
    		 */
    		private function sqlCLI() {
    
    			civicrm_initialize();
    			if ( ! defined( 'CIVICRM_DSN' ) ) {
    				WP_CLI::error( 'CIVICRM_DSN is not defined.' );
    			}
    
    			$dsn = DB::parseDSN( CIVICRM_DSN );
    
    			$mysql_args = array(
    				'host'     => $dsn['hostspec'],
    				'database' => $dsn['database'],
    				'user'     => $dsn['username'],
    				'password' => $dsn['password'],
    			 );
    
    			\WP_CLI\Utils\run_mysql_command( 'mysql --no-defaults', $mysql_args );
    
    		}
    
    		/**
    		 * Implementation of command 'update-cfg'
    		 */
    		private function updateConfig() {
    
    			civicrm_initialize();
    
    			$default_values = array();
    			$states        = array( 'old', 'new' );
    
    			for ( $i = 1; $i <= 3; $i++ ) {
    				foreach ( $states as $state ) {
    					$name = "{$state}Val_{$i}";
    					$value = $this->getOption( $name, null );
    					if ( $value ) {
    						$default_values[ $name ] = $value;
    					}
    				}
    			}
    
    			$webserver_user  = $this->getWebServerUser();
    			$webserver_group = $this->getWebServerGroup();
    
    			require_once 'CRM/Core/I18n.php';
    			require_once 'CRM/Core/BAO/ConfigSetting.php';
    			$result = CRM_Core_BAO_ConfigSetting::doSiteMove( $default_values );
    
    			if ( $result ) {
    
    				# attempt to preserve webserver ownership of templates_c, civicrm/upload
    				if ( $webserver_user and $webserver_group ) {
    					$upload_dir      = wp_upload_dir();
    					$civicrm_files_dir      = $upload_dir['basedir'] . DIRECTORY_SEPARATOR . 'civicrm' . DIRECTORY_SEPARATOR;
    					system( sprintf( 'chown -R %s:%s %s/templates_c', $webserver_user, $webserver_group, $civicrm_files_dir ) );
    					system( sprintf( 'chown -R %s:%s %s/upload', $webserver_user, $webserver_group, $civicrm_files_dir ) );
    				}
    
    				WP_CLI::success( 'Config successfully updated.' );
    
    			} else {
    				WP_CLI::error( 'Config update failed.' );
    			}
    
    		}
    
    		/**
    		 * Implementation of command 'upgrade'
    		 */
    		private function upgrade() {
    
    			# todo: use wp-cli to download tarfile.
    			# todo: if tarfile is not specified, see if the code already exists and use that instead.
    			if ( ! $this->getOption( 'tarfile', false ) and ! $this->getOption( 'zipfile', false ) ) {
    				return WP_CLI::error( 'Must specify either --tarfile or --zipfile' );
    			}
    
    			# fixme: throw error if tarfile is not in a valid format.
    			if ( ! defined( 'CIVICRM_UPGRADE_ACTIVE' ) ) {
    				define( 'CIVICRM_UPGRADE_ACTIVE', 1 );
    			}
    
    			$wp_root       = ABSPATH;
    			$plugins_dir = plugin_dir_path( __FILE__ );
    			$legacy_settings_file = $plugins_dir . '/civicrm.settings.php';
    			$upload_dir      = wp_upload_dir();
    			$settings_file     = $upload_dir['basedir'] . DIRECTORY_SEPARATOR . 'civicrm' . DIRECTORY_SEPARATOR . 'civicrm.settings.php';
    			if ( ! file_exists( $legacy_settings_file ) || ! file_exists( $settings_file ) ) {
    				return WP_CLI::error( 'Unable to locate settings file at ' . $legacy_settings_file . 'or at ' . $settings_file );
    			}
    
    			# nb: we don't want to require civicrm.settings.php here, because ..
    			#
    			# a ) this is the old environment we're going to replace
    			# b ) upgrade-db needs to bootstrap the new environment, so requiring the file
    			#    now will create multiple inclusion problems later on
    			#
    			# however, all we're really after is $civicrm_root and CIVICRM_DSN, so we're going to
    			# pull out the lines we need using a regex and run them - yes, it's pretty silly ..
    			# don't try this at home, kids.
    
    			$legacy_settings = file_get_contents( $legacy_settings_file );
    			$legacy_settings = str_replace( "\r", '', $legacy_settings );
    			$legacy_settings = explode( "\n", $legacy_settings );
    			$settings = file_get_contents( $settings_file );
    			$settings = str_replace( "\r", '', $settings );
    			$settings = explode( "\n", $settings );
    
    			if ( $civicrm_root_code = reset( preg_grep( '/^\s*\$civicrm_root\s*=.*$/', $legacy_settings ) ) ) {
    				eval( $civicrm_root_code );
    			} elseif ( $civicrm_root_code = reset( preg_grep( '/^\s*\$civicrm_root\s*=.*$/', $settings ) ) ) {
    				eval( $civicrm_root_code );
    			} else {
    				return WP_CLI::error( 'Unable to read $civicrm_root from civicrm.settings.php' );
    			}
    
    			if ( $civicrm_dsn_code = reset( preg_grep( '/^\s*define.*CIVICRM_DSN.*$/', $settings ) ) ) {
    				$civicrm_dsn_code = str_replace( 'CIVICRM_DSN', 'CIVICRM_OLD_DSN', $civicrm_dsn_code );
    				eval( $civicrm_dsn_code );
    			} else {
    				return WP_CLI::error( 'Unable to read CIVICRM_DSN from civicrm.settings.php' );
    			}
    
    			if ( ! defined( 'CIVICRM_OLD_DSN' ) ) {
    				return WP_CLI::error( 'Unable to set CIVICRM_OLD_DSN' );
    			}
    
    			$date        = date( 'YmdHis' );
    			$backup_file = 'civicrm';
    
    			$basepath = explode( '/', $civicrm_root );
    
    			if ( ! end( $basepath ) ) {
    				array_pop( $basepath );
    			}
    
    			array_pop( $basepath );
    			$project_path = implode( '/', $basepath ) . '/';
    			array_pop( $basepath );
    			$plugin_path = implode( '/', $basepath ) . '/';
    
    			$backup_dir = $this->getOption( 'backup-dir', $wp_root . '../backup' );
    			$backup_dir = rtrim( $backup_dir, '/' );
    
    			WP_CLI::line( "\nThe upgrade process involves - " );
    			WP_CLI::line( sprintf( '1. Backing up current CiviCRM code as => %s', "$backup_dir/plugins/$date/$backup_file" ) );
    			WP_CLI::line( sprintf( '2. Backing up database as => %s', "$backup_dir/plugins/$date/$backup_file.sql" ) );
    			WP_CLI::line( sprintf( '3. Unpacking tarfile to => %s', $plugin_path ) );
    			WP_CLI::line( "4. Executing civicrm/upgrade?reset=1 just as a browser would.\n" );
    
    			WP_CLI::confirm( 'Do you really want to continue?' );
    
    			# begin upgrade