Skip to content
Snippets Groups Projects
civicrm.php 42.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • Kevin Cristiano's avatar
    Kevin Cristiano committed
          WP_CLI::confirm('Do you really want to continue?');
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
          # begin upgrade
    
          $backup_dir .= '/plugins/' . $date;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if (!mkdir($backup_dir, 0755, TRUE)) {
            return WP_CLI::error('Failed creating directory: ' . $backup_dir);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          }
    
          $backup_target = $backup_dir . '/' . $backup_file;
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if (!rename($project_path, $backup_target)) {
            return WP_CLI::error(sprintf(
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              'Failed to backup CiviCRM project directory %s to %s',
              $project_path,
              $backup_target
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            ));
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          }
    
          WP_CLI::line();
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          WP_CLI::success('1. Code backed up.');
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
          WP_CLI::run_command(
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            ['civicrm', 'sql-dump'],
            ['result-file' => $backup_target . '.sql']
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          WP_CLI::success('2. Database backed up.');
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
          # decompress
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if ($this->getOption('tarfile', FALSE)) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            # should probably never get to here, as looks like Wordpress Civi comes
            # in a zip file
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            if (!$this->untar($plugin_path)) {
              return WP_CLI::error('Error extracting tarfile');
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          }
          elseif ($this->getOption('zipfile', FALSE)) {
            if (!$this->unzip($plugin_path)) {
              return WP_CLI::error('Error extracting zipfile');
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          }
          else {
            return WP_CLI::error('No zipfile specified, use --zipfile=path/to/zipfile');
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          WP_CLI::success('3. Archive unpacked.');
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          WP_CLI::line('Copying civicrm.settings.php to ' . $project_path . '..');
          define('CIVICRM_SETTINGS_PATH', $project_path . 'civicrm.settings.php');
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if (!copy($backup_dir . '/civicrm/civicrm.settings.php', CIVICRM_SETTINGS_PATH)) {
            return WP_CLI::error('Failed to copy file');
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          WP_CLI::success('4. ');
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          WP_CLI::run_command(['civicrm', 'upgrade-db'], []);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          WP_CLI::success('Process completed.');
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
        }
    
        /**
         * Implementation of command 'upgrade-db'
         */
        private function upgradeDB() {
    
          civicrm_initialize();
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if (!defined('CIVICRM_UPGRADE_ACTIVE')) {
            define('CIVICRM_UPGRADE_ACTIVE', 1);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if (class_exists('CRM_Upgrade_Headless')) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            # Note: CRM_Upgrade_Headless introduced in 4.2 -- at the same time as class auto-loading
            try {
              $upgrade_headless = new CRM_Upgrade_Headless();
              $result = $upgrade_headless->run();
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              WP_CLI::line('Upgrade outputs: ' . '"' . $result['message'] . '"');
            }
            catch (Exception $e) {
              WP_CLI::error($e->getMessage());
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          }
          else {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
            require_once 'CRM/Core/Smarty.php';
            $template = CRM_Core_Smarty::singleton();
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            require_once 'CRM/Upgrade/Page/Upgrade.php';
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $upgrade = new CRM_Upgrade_Page_Upgrade();
    
            // new since CiviCRM 4.1
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            if (is_callable([$upgrade, 'setPrint'])) {
              $upgrade->setPrint(TRUE);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            }
    
            # to suppress html output /w source code.
            ob_start();
            $upgrade->run();
            # capture the required message.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $result = $template->get_template_vars('message');
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            ob_end_clean();
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            WP_CLI::line('Upgrade outputs: ' . "\"$result\"");
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
          }
    
        }
    
        /**
         * DSN parser - this has been stolen from PEAR DB since we don't always have a
         * bootstrapped environment we can access this from, eg: when doing an upgrade
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         * @param  $dsn (string)
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         * @return array containing db connection details
         */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        private static function parseDSN($dsn) {
    
          $parsed = [
            'phptype'  => FALSE,
            'dbsyntax' => FALSE,
            'username' => FALSE,
            'password' => FALSE,
            'protocol' => FALSE,
            'hostspec' => FALSE,
            'port'     => FALSE,
            'socket'   => FALSE,
            'database' => FALSE,
          ];
    
          if (is_array($dsn)) {
            $dsn = array_merge($parsed, $dsn);
            if (!$dsn['dbsyntax']) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              $dsn['dbsyntax'] = $dsn['phptype'];
            }
            return $dsn;
          }
    
          // Find phptype and dbsyntax
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if (($pos = strpos($dsn, '://')) !== FALSE) {
            $str = substr($dsn, 0, $pos);
            $dsn = substr($dsn, $pos + 3);
          }
          else {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $str = $dsn;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $dsn = NULL;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          }
    
          // Get phptype and dbsyntax
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          // $str => phptype(dbsyntax)
          if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $parsed['phptype']  = $arr[1];
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2];
          }
          else {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $parsed['phptype']  = $str;
            $parsed['dbsyntax'] = $str;
          }
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if (empty($dsn)) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            return $parsed;
          }
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          // Get (if found): username and password
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          // $dsn => username:password@protocol+hostspec/database
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if (($at = strrpos($dsn, '@')) !== FALSE) {
            $str = substr($dsn, 0, $at);
            $dsn = substr($dsn, $at + 1);
            if (($pos = strpos($str, ':')) !== FALSE) {
              $parsed['username'] = rawurldecode(substr($str, 0, $pos));
              $parsed['password'] = rawurldecode(substr($str, $pos + 1));
            }
            else {
              $parsed['username'] = rawurldecode($str);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            }
          }
    
          // Find protocol and hostspec
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
            // $dsn => proto(proto_opts)/database
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $proto       = $match[1];
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $proto_opts  = $match[2] ? $match[2] : FALSE;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $dsn         = $match[3];
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          }
          else {
            // $dsn => protocol+hostspec/database (old format)
            if (strpos($dsn, '+') !== FALSE) {
              list($proto, $dsn) = explode('+', $dsn, 2);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            if (strpos($dsn, '/') !== FALSE) {
              list($proto_opts, $dsn) = explode('/', $dsn, 2);
            }
            else {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              $proto_opts = $dsn;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              $dsn = NULL;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            }
          }
    
          // process the different protocol options
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp';
          $proto_opts = rawurldecode($proto_opts);
          if (strpos($proto_opts, ':') !== FALSE) {
            list($proto_opts, $parsed['port']) = explode(':', $proto_opts);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if ('tcp' == $parsed['protocol']) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $parsed['hostspec'] = $proto_opts;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          }
          elseif ('unix' == $parsed['protocol']) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $parsed['socket'] = $proto_opts;
          }
    
          // Get dabase if any
          // $dsn => database
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if ($dsn) {
            if (($pos = strpos($dsn, '?')) === FALSE) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              // /database
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              $parsed['database'] = rawurldecode($dsn);
            }
            else {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              // /database?param1=value1&param2=value2
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              $parsed['database'] = rawurldecode(substr($dsn, 0, $pos));
              $dsn = substr($dsn, $pos + 1);
              if (strpos($dsn, '&') !== FALSE) {
                $opts = explode('&', $dsn);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              else {
                // database?param1=value1
                $opts = [$dsn];
              }
              foreach ($opts as $opt) {
                list($key, $value) = explode('=', $opt);
                if (!isset($parsed[$key])) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                  // don't allow params overwrite
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                  $parsed[$key] = rawurldecode($value);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                }
              }
            }
          }
    
          return $parsed;
        }
    
        /**
         * Helper function to replicate functionality of drush_get_option
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         *
         * @param string $name
         * @param string $default
         * @return mixed The value if found or default if not.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        private function getOption($name, $default) {
          return isset($this->assoc_args[$name]) ? $this->assoc_args[$name] : $default;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        }
    
        /**
         * Get the user the web server runs as, used to preserve file permissions on templates_c, civicrm/upload
         * etc when running as root. This is not a very good check, but is good enough for what we want to do,
         * which is preserve file permissions
         * @return string - the user which owns templates_c / empty string if not found
         */
        private function getWebServerUser() {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          $plugins_dir = plugin_dir_path(__FILE__);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          $plugins_dir_root = WP_PLUGIN_DIR;
          $upload_dir      = wp_upload_dir();
          $tpl_path     = $upload_dir['basedir'] . DIRECTORY_SEPARATOR . 'civicrm' . DIRECTORY_SEPARATOR . 'templates_c';
          $legacy_tpl_path = $plugins_dir_root . '/files/civicrm/templates_c';
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if (is_dir($legacy_tpl_path)) {
            $owner = posix_getpwuid(fileowner($legacy_tpl_path));
            if (isset($owner['name'])) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              return $owner['name'];
            }
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          }
          elseif (is_dir($tpl_path)) {
            $owner = posix_getpwuid(fileowner($tpl_path));
            if (isset($owner['name'])) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              return $owner['name'];
            }
          }
          return '';
    
        }
    
        /**
         * Get the group the webserver runs as - as above, but for group
         */
        private function getWebServerGroup() {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          $plugins_dir = plugin_dir_path(__FILE__);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          $plugins_dir_root = WP_PLUGIN_DIR;
          $upload_dir      = wp_upload_dir();
          $tpl_path     = $upload_dir['basedir'] . DIRECTORY_SEPARATOR . 'civicrm' . DIRECTORY_SEPARATOR . 'templates_c';
          $legacy_tpl_path = $plugins_dir_root . '/files/civicrm/templates_c';
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if (is_dir($legacy_tpl_path)) {
            $group = posix_getgrgid(filegroup($legacy_tpl_path));
            if (isset($group['name'])) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              return $group['name'];
            }
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          }
          elseif (is_dir($tpl_path)) {
            $group = posix_getgrgid(filegroup($tpl_path));
            if (isset($group['name'])) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              return $group['name'];
            }
          }
          return '';
    
        }
    
        /**
         * Extract a tar.gz archive
         * @param  $destination_path - the path to extract to
         * @param  $option          - command line option to get input filename from, defaults to 'tarfile'
         * @return bool
         */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        private function untar($destination_path, $option = 'tarfile') {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if ($tarfile = $this->getOption($option, FALSE)) {
            WP_CLI::launch("gzip -d $tarfile");
            $tarfile = substr($tarfile, 0, strlen($tarfile) - 3);
            WP_CLI::launch("tar -xf $tarfile -C \"$destination_path\"");
            return TRUE;
          }
          else {
            return FALSE;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          }
    
        }
    
        /**
         * Extract a zip archive
         * @param  $destination_path - the path to extract to
         * @param  $option          - command line option to get zip filename from, defaults to 'zipfile'
         * @return bool
         */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        private function unzip($destination_path, $option = 'zipfile') {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if ($zipfile = $this->getOption($option, FALSE)) {
            WP_CLI::line('Extracting zip archive ...');
            WP_CLI::launch("unzip -q $zipfile -d $destination_path");
            return TRUE;
          }
          else {
            return FALSE;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      WP_CLI::add_command('civicrm', 'CiviCRM_Command');
      WP_CLI::add_command('cv', 'CiviCRM_Command');
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      # Set path early.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      WP_CLI::add_hook('before_wp_load', function() {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        # If --path is set, save for later use by CiviCRM.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        global $civicrm_paths;
        $wp_cli_config = WP_CLI::get_config();
        if (!empty($wp_cli_config['path'])) {
          $civicrm_paths['cms.root']['path'] = $wp_cli_config['path'];
        }
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        # If --url is set, save for later use by CiviCRM.
        if (!empty($wp_cli_config['url'])) {
          $civicrm_paths['cms.root']['url'] = $wp_cli_config['url'];
        }
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      });
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    }