From 921af8ecad9bfacd84ed90fcdd84cbe222854031 Mon Sep 17 00:00:00 2001
From: Christian Wach <needle@haystack.co.uk>
Date: Wed, 24 Nov 2021 17:26:18 +0000
Subject: [PATCH] Streamline and enhance the plugin load procedure.

---
 civicrm.php                                   | 166 +++--
 .../civicrm.metabox.contact.add.php           |   4 +-
 includes/admin-pages/civicrm.page.error.php   |  11 +-
 .../admin-pages/civicrm.page.integration.php  |  11 +-
 includes/admin-pages/civicrm.page.options.php |  24 +-
 includes/civicrm.admin.php                    |  64 +-
 includes/civicrm.basepage.php                 | 172 ++---
 includes/civicrm.compat.php                   |  10 +-
 includes/civicrm.shortcodes.modal.php         |   1 -
 includes/civicrm.shortcodes.php               | 138 ++--
 includes/civicrm.users.php                    |  42 +-
 uninstall.php                                 |   5 +
 wp-cli/LICENSE                                | 661 ------------------
 wp-cli/civicrm.php                            | 454 +++++++-----
 14 files changed, 606 insertions(+), 1157 deletions(-)
 delete mode 100644 wp-cli/LICENSE

diff --git a/civicrm.php b/civicrm.php
index d79d2ea..e200fc7 100644
--- a/civicrm.php
+++ b/civicrm.php
@@ -30,30 +30,12 @@
  *
  */
 
-/*
- * -----------------------------------------------------------------------------
- * WordPress resources for developers
- * -----------------------------------------------------------------------------
- * Not that they're ever adhered to anywhere other than core, but people do their
- * best to comply...
- *
- * WordPress core coding standards:
- * https://developer.wordpress.org/coding-standards/wordpress-coding-standards/php/
- *
- * WordPress HTML standards:
- * https://make.wordpress.org/core/handbook/best-practices/coding-standards/html/
- *
- * WordPress JavaScript standards:
- * https://developer.wordpress.org/coding-standards/wordpress-coding-standards/javascript/
- * -----------------------------------------------------------------------------
- */
-
 // This file must not accessed directly.
 if (!defined('ABSPATH')) {
   exit;
 }
 
-// Set version here: when it changes, will force Javascript & CSS to reload.
+// Set version here: changing it forces Javascript and CSS to reload.
 define('CIVICRM_PLUGIN_VERSION', '4.7');
 
 // Store reference to this file.
@@ -71,24 +53,26 @@
   define('CIVICRM_PLUGIN_DIR', plugin_dir_path(CIVICRM_PLUGIN_FILE));
 }
 
+/*
+ * Minimum required PHP.
+ *
+ * Note: This duplicates `CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER`.
+ * The duplication helps avoid dependency issues. (Reading
+ * `CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER` requires loading
+ * `civicrm.settings.php`, but that triggers a parse-error on PHP 5.x.)
+ *
+ * @see CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER
+ * @see CiviWP\PhpVersionTest::testConstantMatch()
+ */
 if (!defined('CIVICRM_WP_PHP_MINIMUM')) {
-  /**
-   * Minimum required PHP.
-   *
-   * Note: This duplicates `CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER`.
-   * The duplication helps avoid dependency issues. (Reading
-   * `CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER` requires loading
-   * `civicrm.settings.php`, but that triggers a parse-error on PHP 5.x.)
-   *
-   * @see CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER
-   * @see CiviWP\PhpVersionTest::testConstantMatch()
-   */
   define('CIVICRM_WP_PHP_MINIMUM', '7.2.0');
 }
 
 /*
  * The constant `CIVICRM_SETTINGS_PATH` is also defined in `civicrm.config.php`
  * and may already have been defined there - e.g. by cron or external scripts.
+ * These legacy routes should not be used because they try to bootstrap WordPress
+ * in unreliable ways. Use WP-CLI or WP-REST routes instead.
  */
 if (!defined('CIVICRM_SETTINGS_PATH')) {
 
@@ -98,14 +82,13 @@
    * If the settings file is found in the 4.6 and prior location, use that as
    * `CIVICRM_SETTINGS_PATH`, otherwise use the new location.
    */
-  $upload_dir = wp_upload_dir();
-  $wp_civi_settings = $upload_dir['basedir'] . DIRECTORY_SEPARATOR . 'civicrm' . DIRECTORY_SEPARATOR . 'civicrm.settings.php';
-  $wp_civi_settings_deprectated = CIVICRM_PLUGIN_DIR . 'civicrm.settings.php';
-
-  if (file_exists($wp_civi_settings_deprectated)) {
-    define('CIVICRM_SETTINGS_PATH', $wp_civi_settings_deprectated);
+  $wp_civi_settings_deprecated = CIVICRM_PLUGIN_DIR . 'civicrm.settings.php';
+  if (file_exists($wp_civi_settings_deprecated)) {
+    define('CIVICRM_SETTINGS_PATH', $wp_civi_settings_deprecated);
   }
   else {
+    $upload_dir = wp_upload_dir();
+    $wp_civi_settings = implode(DIRECTORY_SEPARATOR, [$upload_dir['basedir'], 'civicrm', 'civicrm.settings.php']);
     define('CIVICRM_SETTINGS_PATH', $wp_civi_settings);
   }
 
@@ -184,7 +167,7 @@ class CiviCRM_For_WordPress {
 
   /**
    * @var object
-   * Basepage management object.
+   * Base Page management object.
    * @since 4.4
    * @access public
    */
@@ -234,6 +217,17 @@ public static function singleton() {
       // Create instance.
       self::$instance = new CiviCRM_For_WordPress();
 
+      // Include legacy global scope functions.
+      include_once CIVICRM_PLUGIN_DIR . 'includes/civicrm.functions.php';
+
+      /*
+       * Incorporate WP-CLI Integration based on drush CiviCRM functionality.
+       * @see https://github.com/andy-walker/wp-cli-civicrm
+       */
+      if (defined('WP_CLI') && WP_CLI) {
+        include_once CIVICRM_PLUGIN_DIR . 'wp-cli/civicrm.php';
+      }
+
       // Delay setup until 'plugins_loaded' to allow other plugins to load as well.
       add_action('plugins_loaded', [self::$instance, 'setup_instance']);
 
@@ -272,9 +266,13 @@ public function __wakeup() {
   /**
    * Plugin activation.
    *
-   * This method is called only when CiviCRM plugin is activated. In order for
-   * other plugins to be able to interact with CiviCRM's activation, we wait until
-   * after the activation redirect to perform activation actions.
+   * This method is called only when CiviCRM plugin is activated. Other plugins
+   * are able to interact with CiviCRM's activation because "plugins_loaded" has
+   * already fired.
+   *
+   * Since CiviCRM has an Installer UI when activated via the WordPress Plugins
+   * screen, this method sets an option that can be read on the next page load
+   * allowing `self::activation()` to redirect to it when possible.
    *
    * @since 4.4
    */
@@ -283,10 +281,25 @@ public function activate() {
     // Set a one-time-only option.
     add_option('civicrm_activation_in_progress', 'true');
 
+    // Include and init classes because "plugins_loaded" has already fired.
+    include_once CIVICRM_PLUGIN_DIR . 'includes/civicrm.users.php';
+    $this->users = new CiviCRM_For_WordPress_Users();
+
+    /**
+     * Broadcast that the CiviCRM plugin has been activated.
+     *
+     * Used internally by:
+     *
+     * - CiviCRM_For_WordPress_Users::activate()
+     *
+     * @since 5.44
+     */
+    do_action('civicrm_activate');
+
   }
 
   /**
-   * Run CiviCRM's plugin activation procedure.
+   * Runs the CiviCRM activation procedure when activated via the WordPress UI.
    *
    * @since 4.4
    */
@@ -303,7 +316,10 @@ public function activation() {
     }
 
     /**
-     * Broadcast that activation actions need to happen now.
+     * Broadcast that activation via the WordPress UI has happened.
+     *
+     * This fires on the admin page load that happens directly after the CiviCRM
+     * plugin has been activated via the WordPress UI.
      *
      * @since 5.6
      */
@@ -312,11 +328,12 @@ public function activation() {
     // Change option so this action never fires again.
     update_option('civicrm_activation_in_progress', 'false');
 
-    // Try and redirect to the Installer page.
+    // When installed via the WordPress UI, try and redirect to the Installer page.
     if (!is_multisite() && !isset($_GET['activate-multi']) && !CIVICRM_INSTALLED) {
       wp_redirect(admin_url('admin.php?page=civicrm-install'));
       exit;
     }
+
   }
 
   /**
@@ -336,6 +353,10 @@ public function deactivate() {
     /**
      * Broadcast that deactivation actions need to happen now.
      *
+     * Used internally by:
+     *
+     * - CiviCRM_For_WordPress_Users::deactivate()
+     *
      * @since 5.6
      */
     do_action('civicrm_deactivation');
@@ -377,7 +398,7 @@ public function setup_instance() {
     $this->include_files();
     $this->setup_objects();
 
-    // Do plugin activation.
+    // Do plugin activation when activated via the WordPress UI.
     $this->activation();
 
     // Use translation files.
@@ -389,6 +410,10 @@ public function setup_instance() {
     /**
      * Broadcast that this plugin is now loaded.
      *
+     * Used internally by:
+     *
+     * - CiviCRM_For_WordPress_Basepage::maybe_create_basepage()
+     *
      * @since 4.4
      */
     do_action('civicrm_instance_loaded');
@@ -514,11 +539,11 @@ public function enable_translation() {
    * Setter for determining if CiviCRM is currently being displayed in WordPress.
    * This becomes true whe CiviCRM is called in the following contexts:
    *
-   * (a) in the WordPress back-end
-   * (b) when CiviCRM content is being displayed on the front-end via wpBasePage
-   * (c) when an AJAX request is made to CiviCRM
+   * (a) In the WordPress back-end.
+   * (b) When CiviCRM content is being displayed on the front-end via the Base Page.
+   * (c) When an AJAX request is made to CiviCRM.
    *
-   * It is NOT true when CiviCRM is called via a shortcode.
+   * It is NOT true when CiviCRM is called via a Shortcode.
    *
    * @since 4.4
    */
@@ -549,7 +574,6 @@ public function civicrm_in_wordpress() {
      * @since 4.4
      *
      * @param bool $in_wordpress True if CiviCRM is displayed in WordPress, false otherwise.
-     * @return bool $in_wordpress True if CiviCRM is displayed in WordPress, false otherwise.
      */
     return apply_filters('civicrm_in_wordpress', self::$in_wordpress);
 
@@ -561,10 +585,10 @@ public function civicrm_in_wordpress() {
    * Setter for determining how CiviCRM is currently being displayed in WordPress.
    * This can be one of the following contexts:
    *
-   * (a) in the WordPress back-end
-   * (b) when CiviCRM content is being displayed on the front-end via wpBasePage
-   * (c) when a "non-page" request is made to CiviCRM
-   * (d) when CiviCRM is called via a shortcode
+   * (a) In the WordPress back-end.
+   * (b) When CiviCRM content is being displayed on the front-end via the Base Page.
+   * (c) When a "non-page" request is made to CiviCRM.
+   * (d) When CiviCRM is called via a Shortcode.
    *
    * The following codes correspond to the different contexts:
    *
@@ -600,10 +624,13 @@ public function civicrm_context_get() {
     /**
      * Allow specific context to be filtered.
      *
+     * Used internally by:
+     *
+     * - CiviCRM_For_WordPress_Shortcodes::get_context()
+     *
      * @since 4.4
      *
      * @param bool $context The existing context in which CiviCRM is displayed in WordPress.
-     * @return bool $context The modified context in which CiviCRM is displayed in WordPress.
      */
     return apply_filters('civicrm_context', self::$context);
 
@@ -632,7 +659,7 @@ public function register_hooks() {
       // Handle WordPress Admin context.
       $this->admin->register_hooks();
 
-      // Enable shortcode modal.
+      // Enable Shortcode modal.
       $this->modal->register_hooks();
 
       return;
@@ -813,7 +840,7 @@ public function rewrite_rules($flush_rewrite_rules = FALSE) {
     // Get config.
     $config = CRM_Core_Config::singleton();
 
-    // Get basepage object.
+    // Get Base Page object.
     $basepage = get_page_by_path($config->wpBasePage);
 
     // Sanity check.
@@ -821,7 +848,7 @@ public function rewrite_rules($flush_rewrite_rules = FALSE) {
       return;
     }
 
-    // Let's add rewrite rule when viewing the basepage.
+    // Let's add Rewrite Rule when viewing the Base Page.
     add_rewrite_rule(
       '^' . $config->wpBasePage . '/([^?]*)?',
       'index.php?page_id=' . $basepage->ID . '&civiwp=CiviCRM&q=civicrm%2F$matches[1]',
@@ -836,11 +863,15 @@ public function rewrite_rules($flush_rewrite_rules = FALSE) {
     /**
      * Broadcast the rewrite rules event.
      *
+     * Used internally by:
+     *
+     * - CiviCRM_For_WordPress_Compat::rewrite_rules_polylang()
+     *
      * @since 5.7
      * @since 5.24 Added $basepage parameter.
      *
      * @param bool $flush_rewrite_rules True if rules flushed, false otherwise.
-     * @param WP_Post $basepage The Basepage post object.
+     * @param WP_Post $basepage The Base Page post object.
      */
     do_action('civicrm_after_rewrite_rules', $flush_rewrite_rules, $basepage);
 
@@ -879,7 +910,6 @@ public function query_vars($query_vars) {
      * @since 5.7
      *
      * @param array $civicrm_query_vars The default set of query vars.
-     * @return array $civicrm_query_vars The modified set of query vars.
      */
     $civicrm_query_vars = apply_filters('civicrm_query_vars', $civicrm_query_vars);
 
@@ -1390,7 +1420,7 @@ public function get_request_args() {
    * Get base URL.
    *
    * Clone of CRM_Utils_System_WordPress::getBaseUrl() whose access is set to
-   * private. Until it is public, we cannot access the URL of the basepage since
+   * private. Until it is public, we cannot access the URL of the Base Page since
    * CRM_Utils_System_WordPress::url().
    *
    * 27-09-2016
@@ -1466,19 +1496,3 @@ function civi_wp() {
  *
  * @see https://developer.wordpress.org/reference/functions/register_uninstall_hook/
  */
-
-// Include legacy global scope functions.
-include_once CIVICRM_PLUGIN_DIR . 'includes/civicrm.functions.php';
-
-/**
- * Incorporate WP-CLI Integration.
- *
- * Based on drush CiviCRM functionality, work done by Andy Walker.
- * https://github.com/andy-walker/wp-cli-civicrm
- *
- * @since 4.5
- */
-if (defined('WP_CLI') && WP_CLI) {
-  // Changed from __DIR__ because of possible symlink issues.
-  include_once CIVICRM_PLUGIN_DIR . 'wp-cli/civicrm.php';
-}
diff --git a/includes/admin-metaboxes/civicrm.metabox.contact.add.php b/includes/admin-metaboxes/civicrm.metabox.contact.add.php
index ce80294..0bb9a21 100644
--- a/includes/admin-metaboxes/civicrm.metabox.contact.add.php
+++ b/includes/admin-metaboxes/civicrm.metabox.contact.add.php
@@ -213,7 +213,7 @@ public function meta_box_add() {
    * @param mixed $unused Unused param.
    * @param array $metabox Array containing id, title, callback, and args elements.
    */
-  public function meta_box_render($unused = NULL, $metabox) {
+  public function meta_box_render($unused, $metabox) {
 
     if (!$this->civi->initialize()) {
       return;
@@ -295,7 +295,7 @@ public function form_submitted() {
   }
 
   /**
-   * Save the CiviCRM Basepage Setting.
+   * Save the CiviCRM Base Page Setting.
    *
    * @since 5.34
    */
diff --git a/includes/admin-pages/civicrm.page.error.php b/includes/admin-pages/civicrm.page.error.php
index 1f164ca..20106f0 100644
--- a/includes/admin-pages/civicrm.page.error.php
+++ b/includes/admin-pages/civicrm.page.error.php
@@ -83,7 +83,6 @@ public function access_capability() {
      * @since 5.40
      *
      * @param str The default access capability.
-     * @return str The modified access capability.
      */
     return apply_filters('civicrm/admin/error/cap', 'manage_options');
 
@@ -170,6 +169,10 @@ public function page_error() {
      *
      * The Screen ID to use is: "civicrm_page_civi_error".
      *
+     * Used internally by:
+     *
+     * - self::meta_boxes_error_add()
+     *
      * @since 5.40
      *
      * @param str $screen_id The ID of the current screen.
@@ -283,7 +286,7 @@ public function meta_boxes_error_add($screen_id) {
    * @param mixed $unused Unused param.
    * @param array $metabox Array containing id, title, callback, and args elements.
    */
-  public function meta_box_error_help_render($unused = NULL, $metabox) {
+  public function meta_box_error_help_render($unused, $metabox) {
 
     // Include template file.
     include CIVICRM_PLUGIN_DIR . 'assets/templates/metaboxes/metabox.error.help.php';
@@ -298,7 +301,7 @@ public function meta_box_error_help_render($unused = NULL, $metabox) {
    * @param mixed $unused Unused param.
    * @param array $metabox Array containing id, title, callback, and args elements.
    */
-  public function meta_box_error_php_render($unused = NULL, $metabox) {
+  public function meta_box_error_php_render($unused, $metabox) {
 
     global $civicrm_root;
 
@@ -315,7 +318,7 @@ public function meta_box_error_php_render($unused = NULL, $metabox) {
    * @param mixed $unused Unused param.
    * @param array $metabox Array containing id, title, callback, and args elements.
    */
-  public function meta_box_error_path_render($unused = NULL, $metabox) {
+  public function meta_box_error_path_render($unused, $metabox) {
 
     global $civicrm_root;
 
diff --git a/includes/admin-pages/civicrm.page.integration.php b/includes/admin-pages/civicrm.page.integration.php
index 683830d..511bf6f 100644
--- a/includes/admin-pages/civicrm.page.integration.php
+++ b/includes/admin-pages/civicrm.page.integration.php
@@ -106,7 +106,6 @@ public function access_capability() {
      * @since 5.37
      *
      * @param str The default access capability.
-     * @return str The modified access capability.
      */
     return apply_filters('civicrm/admin/integration/cap', 'manage_options');
 
@@ -194,6 +193,10 @@ public function page_integration() {
      *
      * The Screen ID to use is: "civicrm_page_cwps_settings".
      *
+     * Used internally by:
+     *
+     * - self::meta_boxes_integration_add()
+     *
      * @since 5.34
      *
      * @param str $screen_id The ID of the current screen.
@@ -295,7 +298,7 @@ public function meta_boxes_integration_add($screen_id) {
    * @param mixed $unused Unused param.
    * @param array $metabox Array containing id, title, callback, and args elements.
    */
-  public function meta_box_integration_wordpress_render($unused = NULL, $metabox) {
+  public function meta_box_integration_wordpress_render($unused, $metabox) {
 
     // First check our transient for the data.
     $plugins = get_site_transient('civicrm_plugins_by_tag');
@@ -345,7 +348,7 @@ public function meta_box_integration_wordpress_render($unused = NULL, $metabox)
    * @param mixed $unused Unused param.
    * @param array $metabox Array containing id, title, callback, and args elements.
    */
-  public function meta_box_integration_git_render($unused = NULL, $metabox) {
+  public function meta_box_integration_git_render($unused, $metabox) {
 
     // First check our transient for the data.
     $plugins = get_site_transient('civicrm_plugins_by_repo');
@@ -393,7 +396,7 @@ public function meta_box_integration_git_render($unused = NULL, $metabox) {
    * @param mixed $unused Unused param.
    * @param array $metabox Array containing id, title, callback, and args elements.
    */
-  public function meta_box_integration_ext_render($unused = NULL, $metabox) {
+  public function meta_box_integration_ext_render($unused, $metabox) {
 
     if (!$this->civi->initialize()) {
       return;
diff --git a/includes/admin-pages/civicrm.page.options.php b/includes/admin-pages/civicrm.page.options.php
index 7483ac4..49c2f1e 100644
--- a/includes/admin-pages/civicrm.page.options.php
+++ b/includes/admin-pages/civicrm.page.options.php
@@ -109,7 +109,6 @@ public function access_capability() {
      * @since 5.37
      *
      * @param str The default access capability.
-     * @return str The modified access capability.
      */
     return apply_filters('civicrm/admin/settings/cap', 'manage_options');
 
@@ -229,6 +228,10 @@ public function page_options() {
      *
      * The Screen ID to use is: "civicrm_page_cwps_settings".
      *
+     * Used internally by:
+     *
+     * - self::meta_boxes_options_add()
+     *
      * @since 5.34
      *
      * @param str $screen_id The ID of the current screen.
@@ -370,7 +373,7 @@ public function meta_boxes_options_add($screen_id) {
    * @param mixed $unused Unused param.
    * @param array $metabox Array containing id, title, callback, and args elements.
    */
-  public function meta_box_options_basepage_render($unused = NULL, $metabox) {
+  public function meta_box_options_basepage_render($unused, $metabox) {
 
     // Get the setting.
     $basepage_slug = civicrm_api3('Setting', 'getvalue', [
@@ -439,7 +442,6 @@ public function meta_box_options_basepage_render($unused = NULL, $metabox) {
      * @since 5.34
      *
      * @param array $options_post The existing button attributes.
-     * @return array $options_post The modified button attributes.
      */
     $options_post = apply_filters('civicrm/metabox/basepage/submit/options', $options_post);
 
@@ -456,7 +458,7 @@ public function meta_box_options_basepage_render($unused = NULL, $metabox) {
    * @param mixed $unused Unused param.
    * @param array $metabox Array containing id, title, callback, and args elements.
    */
-  public function meta_box_options_shortcode_render($unused = NULL, $metabox) {
+  public function meta_box_options_shortcode_render($unused, $metabox) {
 
     if (!$this->civi->initialize()) {
       return;
@@ -487,7 +489,6 @@ public function meta_box_options_shortcode_render($unused = NULL, $metabox) {
      * @since 5.44
      *
      * @param array $options_post The existing button attributes.
-     * @return array $options_post The modified button attributes.
      */
     $options_post = apply_filters('civicrm/metabox/shortcode/submit/options', $options_post);
 
@@ -504,7 +505,7 @@ public function meta_box_options_shortcode_render($unused = NULL, $metabox) {
    * @param mixed $unused Unused param.
    * @param array $metabox Array containing id, title, callback, and args elements.
    */
-  public function meta_box_options_email_render($unused = NULL, $metabox) {
+  public function meta_box_options_email_render($unused, $metabox) {
 
     if (!$this->civi->initialize()) {
       return;
@@ -538,7 +539,6 @@ public function meta_box_options_email_render($unused = NULL, $metabox) {
      * @since 5.34
      *
      * @param array $options_post The existing button attributes.
-     * @return array $options_post The modified button attributes.
      */
     $options_post = apply_filters('civicrm/metabox/email_sync/submit/options', $options_post);
 
@@ -555,7 +555,7 @@ public function meta_box_options_email_render($unused = NULL, $metabox) {
    * @param mixed $unused Unused param.
    * @param array $metabox Array containing id, title, callback, and args elements.
    */
-  public function meta_box_options_cache_render($unused = NULL, $metabox) {
+  public function meta_box_options_cache_render($unused, $metabox) {
 
     // Set submit button options.
     $options = [
@@ -576,7 +576,7 @@ public function meta_box_options_cache_render($unused = NULL, $metabox) {
    * @param mixed $unused Unused param.
    * @param array $metabox Array containing id, title, callback, and args elements.
    */
-  public function meta_box_options_links_render($unused = NULL, $metabox) {
+  public function meta_box_options_links_render($unused, $metabox) {
 
     if (!$this->civi->initialize()) {
       return;
@@ -608,7 +608,6 @@ public function meta_box_options_links_render($unused = NULL, $metabox) {
      * @since 5.34
      *
      * @param array $admin_links The default array of admin links.
-     * @return array $admin_links The modified array of admin links.
      */
     $admin_links = apply_filters('civicrm/metabox/links/admin', $admin_links);
 
@@ -635,7 +634,6 @@ public function meta_box_options_links_render($unused = NULL, $metabox) {
      * @since 5.34
      *
      * @param array $maintenance_links The default array of admin links.
-     * @return array $maintenance_links The modified array of admin links.
      */
     $maintenance_links = apply_filters('civicrm/metabox/links/maintenance', $maintenance_links);
 
@@ -683,7 +681,7 @@ public function form_submitted() {
   }
 
   /**
-   * Save the CiviCRM Basepage Setting.
+   * Save the CiviCRM Base Page Setting.
    *
    * @since 5.34
    */
@@ -784,7 +782,7 @@ private function form_redirect() {
   // ---------------------------------------------------------------------------
 
   /**
-   * Save the CiviCRM Basepage Setting.
+   * Save the CiviCRM Base Page Setting.
    *
    * @since 5.34
    */
diff --git a/includes/civicrm.admin.php b/includes/civicrm.admin.php
index 1e0dd65..7cef08d 100644
--- a/includes/civicrm.admin.php
+++ b/includes/civicrm.admin.php
@@ -90,6 +90,9 @@ public function __construct() {
     $this->include_files();
     $this->setup_objects();
 
+    // Always check setting for path to "wp-load.php".
+    add_action('civicrm_initialized', [$this, 'add_wpload_setting']);
+
     // Filter Heartbeat on CiviCRM admin pages as late as is practical.
     add_filter('heartbeat_settings', [$this, 'heartbeat'], 1000, 1);
 
@@ -149,7 +152,7 @@ public function register_hooks() {
     }
     else {
 
-      // Listen for changes to the basepage setting.
+      // Listen for changes to the Base Page setting.
       add_action('civicrm_postSave_civicrm_setting', [$this, 'settings_change'], 10);
 
       // Set page title.
@@ -160,6 +163,12 @@ public function register_hooks() {
     /**
      * Broadcast that this object has registered its callbacks.
      *
+     * Used internally by:
+     *
+     * - CiviCRM_For_WordPress_Admin_Metabox_Contact_Add::register_hooks()
+     * - CiviCRM_For_WordPress_Admin_Page_Integration::register_hooks()
+     * - CiviCRM_For_WordPress_Admin_Page_Options::register_hooks()
+     *
      * @since 5.34
      */
     do_action('civicrm/admin/hooks/registered');
@@ -442,6 +451,9 @@ public function initialize() {
 
     }
 
+    // Success! Set static flag.
+    $initialized = TRUE;
+
     /**
      * Broadcast that CiviCRM is now initialized.
      *
@@ -449,8 +461,6 @@ public function initialize() {
      */
     do_action('civicrm_initialized');
 
-    // Success! Set and return static flag.
-    $initialized = TRUE;
     return $initialized;
 
   }
@@ -595,7 +605,6 @@ public function add_menu_items() {
      * @since 4.4
      *
      * @param str The default menu position expressed as a float.
-     * @return str The modified menu position expressed as a float.
      */
     $position = apply_filters('civicrm_menu_item_position', '3.904981');
 
@@ -648,10 +657,11 @@ public function add_menu_items() {
         );
 
         /*
-        // Add scripts and styles like this.
-        add_action('admin_print_scripts-' . $this->menu_page, [$this, 'admin_installer_js']);
-        add_action('admin_print_styles-' . $this->menu_page, [$this, 'admin_installer_css']);
-        add_action('admin_head-' . $this->menu_page, [$this, 'admin_installer_head'], 50);
+         * Add scripts and styles like this if needed:
+         *
+         * add_action('admin_print_scripts-' . $this->menu_page, [$this, 'admin_installer_js']);
+         * add_action('admin_print_styles-' . $this->menu_page, [$this, 'admin_installer_css']);
+         * add_action('admin_head-' . $this->menu_page, [$this, 'admin_installer_head'], 50);
          */
 
       }
@@ -739,9 +749,6 @@ public function admin_page_load() {
     // Add resources for back end.
     $this->civi->add_core_resources(FALSE);
 
-    // Check setting for path to wp-load.php.
-    $this->add_wpload_setting();
-
   }
 
   /**
@@ -761,11 +768,6 @@ public function admin_page_load() {
    * Multisite, because the path to wp-load.php is common to all sites on the
    * network.
    *
-   * My final concern is that the value will only be set *after* someone visits
-   * CiviCRM in the back end. I have restricted it to this so as not to add
-   * overhead to the front end, but there remains the possibility that the value
-   * could be missing. To repeat: this would be better in civicrm.settings.php.
-   *
    * To get the path to wp-load.php, use:
    * $path = CRM_Core_BAO_Setting::getItem('CiviCRM Preferences', 'wpLoadPhp');
    *
@@ -774,7 +776,11 @@ public function admin_page_load() {
    */
   public function add_wpload_setting() {
 
-    if (!$this->civi->initialize()) {
+    if (!CIVICRM_INSTALLED) {
+      return;
+    }
+
+    if (!$this->initialize()) {
       return;
     }
 
@@ -782,16 +788,16 @@ public function add_wpload_setting() {
     $path = ABSPATH . 'wp-load.php';
 
     // Get the setting, if it exists.
-    $setting = CRM_Core_BAO_Setting::getItem('CiviCRM Preferences', 'wpLoadPhp');
-
-    // If we don't have one, create it.
-    if (is_null($setting)) {
-      CRM_Core_BAO_Setting::setItem($path, 'CiviCRM Preferences', 'wpLoadPhp');
-    }
+    $setting = civicrm_api3('Setting', 'getvalue', [
+      'name' => 'wpLoadPhp',
+      'group' => 'CiviCRM Preferences',
+    ]);
 
-    // Is it different to the one we've stored?
-    if ($setting !== $path) {
-      // Yes - set new path (this could be because we've changed server or location)
+    /*
+     * If we don't have a setting, create it. Also set it if it's different to
+     * what's stored. This could be because we've changed server or location.
+     */
+    if (empty($setting) || $setting !== $path) {
       CRM_Core_BAO_Setting::setItem($path, 'CiviCRM Preferences', 'wpLoadPhp');
     }
 
@@ -811,7 +817,7 @@ public function get_admin_link($path = '', $params = NULL) {
     // Init link.
     $link = '';
 
-    if (!$this->civi->initialize()) {
+    if (!$this->initialize()) {
       return $link;
     }
 
@@ -841,7 +847,7 @@ public function get_admin_link($path = '', $params = NULL) {
    */
   public function clear_caches() {
 
-    if (!$this->civi->initialize()) {
+    if (!$this->initialize()) {
       return;
     }
 
@@ -878,7 +884,7 @@ public function get_by_dedupe_unsupervised($contact, $contact_type = 'Individual
       return FALSE;
     }
 
-    if (!$this->civi->initialize()) {
+    if (!$this->initialize()) {
       return FALSE;
     }
 
diff --git a/includes/civicrm.basepage.php b/includes/civicrm.basepage.php
index 70506d1..297b3f4 100644
--- a/includes/civicrm.basepage.php
+++ b/includes/civicrm.basepage.php
@@ -52,13 +52,13 @@ public function __construct() {
     // Always listen for deactivation action.
     add_action('civicrm_deactivation', [$this, 'deactivate']);
 
-    // Always check if the basepage needs to be created.
+    // Always check if the Base Page needs to be created.
     add_action('civicrm_instance_loaded', [$this, 'maybe_create_basepage']);
 
   }
 
   /**
-   * Register hooks to handle CiviCRM in a WordPress wpBasePage context.
+   * Register hooks to handle CiviCRM in a WordPress Base Page context.
    *
    * @since 4.6
    */
@@ -69,22 +69,22 @@ public function register_hooks() {
       return;
     }
 
-    // Cache CiviCRM base page markup.
+    // Cache CiviCRM Base Page markup.
     add_action('wp', [$this, 'basepage_handler'], 10, 1);
 
   }
 
   /**
-   * Trigger the process whereby the WordPress basepage is created.
+   * Triggers the process whereby the WordPress Base Page is created.
    *
-   * Sets a one-time-only option to flag that we need to create a basepage -
+   * Sets a one-time-only option to flag that we need to create a Base Page -
    * it will not update the option once it has been set to another value nor
    * create a new option with the same name.
    *
-   * As a result of doing this, we know that a basepage needs to be created, but
-   * the moment to do so is once CiviCRM has been successfully installed.
+   * As a result of doing this, we know that a Base Page needs to be created,
+   * but the moment to do so is once CiviCRM has been successfully installed.
    *
-   * @see do_basepage_creation()
+   * @see self::maybe_create_basepage()
    *
    * @since 5.6
    */
@@ -108,11 +108,11 @@ public function deactivate() {
   }
 
   /**
-   * Register the hook to create the WordPress basepage, if necessary.
+   * Auto-creates the WordPress Base Page if necessary.
    *
-   * Changes the one-time-only option so that the basepage can only be created
+   * Changes the one-time-only option so that the Base Page can only be created
    * once. Thereafter, we're on our own until there's a 'delete_post' callback
-   * to prevent the basepage from being deleted.
+   * to prevent the Base Page from being deleted.
    *
    * @since 5.6
    */
@@ -128,12 +128,7 @@ public function maybe_create_basepage() {
       return;
     }
 
-    // Bail if not WordPress admin.
-    if (!is_admin()) {
-      return;
-    }
-
-    // Create basepage.
+    // Create the Base Page.
     add_action('wp_loaded', [$this, 'create_wp_basepage']);
 
     // Change option so the callback above never runs again.
@@ -142,71 +137,64 @@ public function maybe_create_basepage() {
   }
 
   /**
-   * Create WordPress basepage and save setting.
+   * Creates the WordPress Base Page and saves the CiviCRM "wpBasePage" setting.
    *
    * @since 4.6
    * @since 5.6 Relocated from CiviCRM_For_WordPress to here.
+   * @since 5.44 Returns success or failure.
+   *
+   * @return bool TRUE if successful, FALSE otherwise.
    */
   public function create_wp_basepage() {
 
     if (!$this->civi->initialize()) {
-      return;
+      return FALSE;
     }
 
+    // Bail if we already have a Base Page setting.
     $config = CRM_Core_Config::singleton();
-
-    // Bail if we already have a basepage setting.
     if (!empty($config->wpBasePage)) {
-      return;
+      return TRUE;
     }
 
     /**
-     * Filter the default page slug.
+     * Filter the default Base Page slug.
      *
      * @since 4.6
      *
-     * @param str The default basepage slug.
-     * @return str The modified basepage slug.
+     * @param str The default Base Page slug.
      */
     $slug = apply_filters('civicrm_basepage_slug', 'civicrm');
 
-    // Get existing page with that slug.
+    // Get existing Page with that slug.
     $page = get_page_by_path($slug);
 
-    // Does it exist?
-    if ($page) {
-
-      // We already have a basepage.
+    // Get the ID if the Base Page already exists.
+    $result = 0;
+    if ($page instanceof WP_Post) {
       $result = $page->ID;
-
     }
-    else {
 
-      // Create the basepage.
+    // Create the Base Page if it's missing.
+    if ($result === 0) {
       $result = $this->create_basepage($slug);
-
     }
 
-    // Were we successful?
+    // Save the Page slug as the setting if we have one.
     if ($result !== 0 && !is_wp_error($result)) {
-
-      // Get the post object.
       $post = get_post($result);
-
-      $params = [
-        'version' => 3,
+      civicrm_api3('Setting', 'create', [
         'wpBasePage' => $post->post_name,
-      ];
-
-      // Save the setting.
-      civicrm_api3('setting', 'create', $params);
-
+      ]);
+      return TRUE;
     }
 
+    return FALSE;
+
   }
 
   /**
-   * Create a WordPress page to act as the CiviCRM base page.
+   * Create a WordPress page to act as the CiviCRM Base Page.
    *
    * @since 4.6
    * @since 5.6 Relocated from CiviCRM_For_WordPress to here.
@@ -219,16 +207,40 @@ private function create_basepage($slug) {
     // If multisite, switch to main site.
     if (is_multisite() && !is_main_site()) {
 
-      // Store this site.
-      $original_site = get_current_blog_id();
+      /**
+       * Allow plugins to override the switch to the main site.
+       *
+       * This filter changes the default behaviour on WordPress Multisite so
+       * that the Base Page *is* created on every site on which CiviCRM is
+       * activated. This is a more sensible and inclusive default, since the
+       * absence of the Base Page on a sub-site often leads to confusion.
+       *
+       * To restore the previous functionality, return boolean TRUE.
+       *
+       * The previous functionality may be the desired behaviour when the
+       * WordPress Multisite instance in question is one where sub-sites aren't
+       * truly "separate" e.g. sites built on frameworks such as "Commons in
+       * a Box" or "MultilingualPress".
+       *
+       * @since 5.44
+       *
+       * @param bool False by default prevents the switch to the main site.
+       */
+      $switch = apply_filters('civicrm/basepage/main_site_only', FALSE);
+
+      if ($switch !== FALSE) {
+
+        // Store this site.
+        $original_site = get_current_blog_id();
 
-      // Switch.
-      global $current_site;
-      switch_to_blog($current_site->blog_id);
+        // Switch to main site.
+        switch_to_blog(get_main_site_id());
+
+      }
 
     }
 
-    // Define basepage.
+    // Define Base Page.
     $page = [
       'post_status' => 'publish',
       'post_type' => 'page',
@@ -248,12 +260,11 @@ private function create_basepage($slug) {
     ];
 
     /**
-     * Filter the default page title.
+     * Filter the default Base Page title.
      *
      * @since 4.6
      *
-     * @param str The default base page title.
-     * @return str The modified base page title.
+     * @param str The default Base Page title.
      */
     $page['post_title'] = apply_filters('civicrm_basepage_title', __('CiviCRM', 'civicrm'));
 
@@ -261,12 +272,12 @@ private function create_basepage($slug) {
     $content = __('Do not delete this page. Page content is generated by CiviCRM.', 'civicrm');
 
     /**
-     * Filter the default page content.
+     * Filter the default Base Page content.
      *
      * @since 4.6
      *
-     * @param str $content The default base page content.
-     * @return str $content The modified base page content.
+     * @param str $content The default Base Page content.
+     * @return str $content The modified Base Page content.
      */
     $page['post_content'] = apply_filters('civicrm_basepage_content', $content);
 
@@ -286,7 +297,7 @@ private function create_basepage($slug) {
   }
 
   /**
-   * Build CiviCRM base page content.
+   * Build CiviCRM Base Page content.
    *
    * Callback method for 'wp' hook, always called from WordPress front-end.
    *
@@ -350,7 +361,6 @@ public function basepage_handler($wp) {
          *
          * @param bool By default "Base Page mode" should not be triggered.
          * @param WP_Post $post The current WordPress Post object.
-         * @return bool Whether or not to force "Base Page mode" - FALSE by default.
          */
         $basepage_mode = (bool) apply_filters('civicrm_force_basepage_mode', FALSE, $post);
 
@@ -362,7 +372,7 @@ public function basepage_handler($wp) {
 
           // Start buffering.
           ob_start();
-          // Now, instead of echoing, base page output ends up in buffer.
+          // Now, instead of echoing, Base Page output ends up in buffer.
           $this->civi->invoke();
           // Save the output and flush the buffer.
           $this->basepage_markup = ob_get_clean();
@@ -433,7 +443,7 @@ public function basepage_handler($wp) {
     // Add compatibility with Yoast SEO plugin's Open Graph title.
     add_filter('wpseo_opengraph_title', [$this, 'wpseo_page_title'], 100, 1);
 
-    // Don't let the Yoast SEO plugin parse the basepage title.
+    // Don't let the Yoast SEO plugin parse the Base Page title.
     if (class_exists('WPSEO_Frontend')) {
       $frontend = WPSEO_Frontend::get_instance();
       remove_filter('pre_get_document_title', [$frontend, 'title'], 15);
@@ -460,11 +470,11 @@ public function basepage_handler($wp) {
 
     }
 
-    // Flag that we have parsed the base page.
+    // Flag that we have parsed the Base Page.
     $this->basepage_parsed = TRUE;
 
     /**
-     * Broadcast that the base page is parsed.
+     * Broadcast that the Base Page is parsed.
      *
      * @since 4.4
      */
@@ -473,7 +483,7 @@ public function basepage_handler($wp) {
   }
 
   /**
-   * Get CiviCRM basepage title for <title> element.
+   * Get CiviCRM Base Page title for <title> element.
    *
    * Callback method for 'wp_title' hook, called at the end of function wp_title.
    *
@@ -518,7 +528,7 @@ public function wp_page_title($title, $separator = '&raquo;', $separator_locatio
   }
 
   /**
-   * Get CiviCRM basepage title for <title> element.
+   * Get CiviCRM Base Page title for <title> element.
    *
    * Callback method for 'document_title_parts' hook. This filter was introduced
    * in WordPress 3.8 but it depends on whether the theme has implemented that
@@ -542,7 +552,7 @@ public function wp_page_title_parts($parts) {
   }
 
   /**
-   * Get CiviCRM base page title for Open Graph elements.
+   * Get CiviCRM Base Page title for Open Graph elements.
    *
    * Callback method for 'wpseo_opengraph_title' hook, to provide compatibility
    * with the WordPress SEO plugin.
@@ -554,30 +564,30 @@ public function wp_page_title_parts($parts) {
    */
   public function wpseo_page_title($post_title) {
 
-    // Hand back our base page title.
+    // Hand back our Base Page title.
     return $this->basepage_title;
 
   }
 
   /**
-   * Get CiviCRM base page content.
+   * Get CiviCRM Base Page content.
    *
    * Callback method for 'the_content' hook, always called from WordPress
    * front-end.
    *
    * @since 4.6
    *
-   * @return str $basepage_markup The base page markup.
+   * @return str $basepage_markup The Base Page markup.
    */
   public function basepage_render() {
 
-    // Hand back our base page markup.
+    // Hand back our Base Page markup.
     return $this->basepage_markup;
 
   }
 
   /**
-   * Provide the canonical URL for a page accessed through a basepage.
+   * Provide the canonical URL for a page accessed through a Base Page.
    *
    * WordPress will default to saying the canonical URL is the URL of the base
    * page itself, but we need to indicate that in this case, the whole thing
@@ -630,14 +640,14 @@ public function basepage_canonical_url($canonical) {
 
     /*
      * We should, however, build the URL the way that CiviCRM expects it to be
-     * (rather than through some other funny base page).
+     * (rather than through some other funny Base Page).
      */
     return CRM_Utils_System::url($path, $query);
 
   }
 
   /**
-   * Get CiviCRM base page template.
+   * Get CiviCRM Base Page template.
    *
    * Callback method for 'template_include' hook, always called from WordPress
    * front-end.
@@ -663,7 +673,7 @@ public function basepage_template($template) {
     }
 
     /**
-     * Allow base page template to be overridden.
+     * Allow Base Page template to be overridden.
      *
      * In most cases, the logic will not progress beyond here. Shortcodes in
      * posts and pages will have a template set, so we leave them alone unless
@@ -672,11 +682,10 @@ public function basepage_template($template) {
      * @since 4.6
      *
      * @param string $template_name The provided template name.
-     * @return string The overridden template name.
      */
     $basepage_template = apply_filters('civicrm_basepage_template', $template_name);
 
-    // Find the base page template.
+    // Find the Base Page template.
     $page_template = locate_template([$basepage_template]);
 
     // If not homepage and template is found.
@@ -687,20 +696,19 @@ public function basepage_template($template) {
     /**
      * Override the template, but allow plugins to amend.
      *
-     * This filter handles the scenario where no basepage has been set, in
+     * This filter handles the scenario where no Base Page has been set, in
      * which case CiviCRM will try to load its content in the site's homepage.
      * Many themes, however, do not have a call to "the_content()" on the
      * homepage - it is often used as a gateway page to display widgets,
      * archives and so forth.
      *
      * Be aware that if the homepage is set to show latest posts, then this
-     * template override will not have the desired effect. A basepage *must*
+     * template override will not have the desired effect. A Base Page *must*
      * be set if this is the case.
      *
      * @since 4.6
      *
      * @param string The template name (set to the default page template).
-     * @return string The overridden template name.
      */
     $home_template_name = apply_filters('civicrm_basepage_home_template', 'page.php');
 
@@ -718,10 +726,10 @@ public function basepage_template($template) {
   }
 
   /**
-   * Add classes to body element when on basepage.
+   * Add classes to body element when on Base Page.
    *
    * This allows selectors to be written for particular CiviCRM "pages" despite
-   * them all being rendered on the one WordPress basepage.
+   * them all being rendered on the one WordPress Base Page.
    *
    * @since 4.7.18
    *
diff --git a/includes/civicrm.compat.php b/includes/civicrm.compat.php
index 8acae0c..4457a51 100644
--- a/includes/civicrm.compat.php
+++ b/includes/civicrm.compat.php
@@ -79,7 +79,7 @@ public function register_hooks() {
    * @since 5.24
    *
    * @param bool $flush_rewrite_rules True if rules flushed, false otherwise.
-   * @param WP_Post $basepage The Basepage post object.
+   * @param WP_Post $basepage The Base Page post object.
    */
   public function rewrite_rules_polylang($flush_rewrite_rules, $basepage) {
 
@@ -92,12 +92,12 @@ public function rewrite_rules_polylang($flush_rewrite_rules, $basepage) {
      * Collect all rewrite rules into an array.
      *
      * Because the array of specific Post IDs is added *after* the array of
-     * paths for the Basepage ID, those specific rewrite rules will "win" over
-     * the more general Basepage rules.
+     * paths for the Base Page ID, those specific rewrite rules will "win" over
+     * the more general Base Page rules.
      */
     $collected_rewrites = [];
 
-    // Support prefixes for a single Basepage.
+    // Support prefixes for a single Base Page.
     $basepage_url = get_permalink($basepage->ID);
     $basepage_raw_url = PLL()->links_model->remove_language_from_link($basepage_url);
     $language_slugs = pll_languages_list();
@@ -113,7 +113,7 @@ public function rewrite_rules_polylang($flush_rewrite_rules, $basepage) {
       }
     };
 
-    // Support prefixes for Basepages in multiple languages.
+    // Support prefixes for Base Pages in multiple languages.
     foreach ($language_slugs as $slug) {
       $post_id = pll_get_post($basepage->ID, $slug);
       if (empty($post_id)) {
diff --git a/includes/civicrm.shortcodes.modal.php b/includes/civicrm.shortcodes.modal.php
index ae894a7..0d7f765 100644
--- a/includes/civicrm.shortcodes.modal.php
+++ b/includes/civicrm.shortcodes.modal.php
@@ -140,7 +140,6 @@ public function post_type_has_button() {
      *
      * @param bool $allowed True if the button is allowed, false otherwise.
      * @param object $screen The current WordPress screen object.
-     * @return bool $allowed True if the button is allowed, false otherwise.
      */
     $allowed = apply_filters('civicrm_restrict_button_appearance', $allowed, $screen);
 
diff --git a/includes/civicrm.shortcodes.php b/includes/civicrm.shortcodes.php
index c7fd2b5..7811409 100644
--- a/includes/civicrm.shortcodes.php
+++ b/includes/civicrm.shortcodes.php
@@ -38,7 +38,7 @@ class CiviCRM_For_WordPress_Shortcodes {
 
   /**
    * @var array
-   * The stored shortcodes.
+   * The stored Shortcodes.
    * @since 4.6
    * @access public
    */
@@ -46,7 +46,7 @@ class CiviCRM_For_WordPress_Shortcodes {
 
   /**
    * @var array
-   * The array of rendered shortcode markup.
+   * The array of rendered Shortcode markup.
    * @since 4.6
    * @access public
    */
@@ -73,13 +73,13 @@ public function __construct() {
   }
 
   /**
-   * Register hooks to handle the presence of shortcodes in content.
+   * Register hooks to handle the presence of Shortcodes in content.
    *
    * @since 4.6
    */
   public function register_hooks() {
 
-    // Register the CiviCRM shortcode.
+    // Register the CiviCRM Shortcode.
     add_shortcode('civicrm', [$this, 'render_single']);
 
     // Pre-render CiviCRM content when one or more Shortcodes are detected.
@@ -88,7 +88,7 @@ public function register_hooks() {
   }
 
   /**
-   * Determine if a CiviCRM shortcode is present in any of the posts about to be displayed.
+   * Determine if a CiviCRM Shortcode is present in any of the posts about to be displayed.
    *
    * Callback method for 'wp' hook, always called from WordPress front-end.
    *
@@ -128,10 +128,10 @@ public function prerender($wp) {
 
         global $post;
 
-        // Check for existence of shortcode in content.
+        // Check for existence of Shortcode in content.
         if (has_shortcode($post->post_content, 'civicrm')) {
 
-          // Get CiviCRM shortcodes in this post.
+          // Get CiviCRM Shortcodes in this post.
           $shortcodes_array = $this->get_for_post($post->post_content);
 
           // Sanity check.
@@ -140,7 +140,7 @@ public function prerender($wp) {
             // Add it to our property.
             $this->shortcodes[$post->ID] = $shortcodes_array;
 
-            // Bump shortcode counter.
+            // Bump Shortcode counter.
             $shortcodes_present += count($this->shortcodes[$post->ID]);
 
           }
@@ -164,12 +164,12 @@ public function prerender($wp) {
     // Did we get any?
     if ($shortcodes_present) {
 
-      // We need CiviCRM initialised prior to parsing shortcodes.
+      // We need CiviCRM initialised prior to parsing Shortcodes.
       if (!$this->civi->initialize()) {
         return;
       }
 
-      // How should we handle multiple shortcodes?
+      // How should we handle multiple Shortcodes?
       if ($shortcodes_present > 1) {
 
         // Add CSS resources for front end.
@@ -178,12 +178,12 @@ public function prerender($wp) {
         // Let's add dummy markup.
         foreach ($this->shortcodes as $post_id => $shortcode_array) {
 
-          // Set flag if there are multple shortcodes in this post.
+          // Set flag if there are multple Shortcodes in this post.
           $multiple = (count($shortcode_array) > 1) ? 1 : 0;
 
           foreach ($shortcode_array as $shortcode) {
 
-            // Mimic invoke in multiple shortcode context.
+            // Mimic invoke in multiple Shortcode context.
             $this->shortcode_markup[$post_id][] = $this->render_multiple($post_id, $shortcode, $multiple);
 
           }
@@ -197,7 +197,7 @@ public function prerender($wp) {
         add_action('wp', [$this->civi, 'front_end_page_load'], 100);
 
         /*
-         * Since we have only one shortcode, run the_loop again.
+         * Since we have only one Shortcode, run the_loop again.
          * The DB query has already been done, so this has no significant impact.
          */
         if (have_posts()) {
@@ -212,10 +212,10 @@ public function prerender($wp) {
               continue;
             }
 
-            // The shortcode must be the first item in the shortcodes array.
+            // The Shortcode must be the first item in the Shortcodes array.
             $shortcode = $this->shortcodes[$post->ID][0];
 
-            // Check to see if a shortcode component has been repeated?
+            // Check to see if a Shortcode component has been repeated?
             $atts = $this->get_atts($shortcode);
 
             // Test for hijacking.
@@ -254,11 +254,11 @@ public function prerender($wp) {
 
     }
 
-    // Flag that we have parsed shortcodes.
+    // Flag that we have parsed Shortcodes.
     $this->shortcodes_parsed = TRUE;
 
     /**
-     * Broadcast that shortcodes have been parsed.
+     * Broadcast that Shortcodes have been parsed.
      *
      * @since 4.6
      */
@@ -267,7 +267,7 @@ public function prerender($wp) {
   }
 
   /**
-   * Handles CiviCRM-defined shortcodes.
+   * Handles CiviCRM-defined Shortcodes.
    *
    * @since 4.6
    *
@@ -276,9 +276,9 @@ public function prerender($wp) {
    */
   public function render_single($atts) {
 
-    // Do not parse shortcodes in REST context for PUT, POST and DELETE methods.
+    // Do not parse Shortcodes in REST context for PUT, POST and DELETE methods.
     if (defined('REST_REQUEST') && REST_REQUEST && (isset($_PUT) || isset($_POST) || isset($_DELETE))) {
-      // Return the original shortcode.
+      // Return the original Shortcode.
       $shortcode = '[civicrm';
       foreach ($atts as $att => $val) {
         $shortcode .= ' ' . $att . '="' . $val . '"';
@@ -287,7 +287,7 @@ public function render_single($atts) {
       return $shortcode;
     }
 
-    // Check if we've already parsed this shortcode.
+    // Check if we've already parsed this Shortcode.
     global $post;
     if (is_object($post)) {
       if (!empty($this->shortcode_markup)) {
@@ -301,14 +301,14 @@ public function render_single($atts) {
             $this->shortcode_in_post[$post->ID]++;
           }
 
-          // This shortcode must have been rendered.
+          // This Shortcode must have been rendered.
           return $this->shortcode_markup[$post->ID][$this->shortcode_in_post[$post->ID]];
 
         }
       }
     }
 
-    // Preprocess shortcode attributes.
+    // Preprocess Shortcode attributes.
     $args = $this->preprocess_atts($atts);
 
     // Check for pathless Shortcode.
@@ -320,18 +320,21 @@ public function render_single($atts) {
        * Get the markup for "pathless" Shortcodes.
        *
        * This filter allows plugins or CiviCRM Extensions to modify the markup used
-       * to display a shortcode that has no CiviCRM route/path. This may be:
+       * to display a Shortcode that has no CiviCRM route/path. This may be:
        *
-       * * Accidental due to an improperly constructed shortcode or
+       * * Accidental due to an improperly constructed Shortcode or
        * * Deliberate because a component may not require a route/path
        *
+       * Used internally by:
+       *
+       * - afform_shortcode_content()
+       *
        * @since 5.37
        *
-       * @param str $content The default markup for an improperly constructed shortcode.
-       * @param array $atts The shortcode attributes array.
-       * @param array $args The shortcode arguments array.
+       * @param str $content The default markup for an improperly constructed Shortcode.
+       * @param array $atts The Shortcode attributes array.
+       * @param array $args The Shortcode arguments array.
        * @param str Context flag - value is either 'single' or 'multiple'.
-       * @return str The modified shortcode markup.
        */
       return apply_filters('civicrm_shortcode_get_markup', $content, $atts, $args, 'single');
 
@@ -368,7 +371,7 @@ public function render_single($atts) {
     // Check permission.
     $argdata = $this->civi->get_request_args();
     if (!$this->civi->users->check_permission($argdata['args'])) {
-      return $this->civi->users->get_permission_denied();;
+      return $this->civi->users->get_permission_denied();
     }
 
     // Start buffering.
@@ -383,13 +386,13 @@ public function render_single($atts) {
   }
 
   /**
-   * Return a generic display for a shortcode instead of a CiviCRM invocation.
+   * Return a generic display for a Shortcode instead of a CiviCRM invocation.
    *
    * @since 4.6
    *
    * @param int $post_id The containing WordPress post ID.
-   * @param string $shortcode The shortcode being parsed.
-   * @param bool $multiple Boolean flag, TRUE if post has multiple shortcodes, FALSE otherwise.
+   * @param string $shortcode The Shortcode being parsed.
+   * @param bool $multiple Boolean flag, TRUE if post has multiple Shortcodes, FALSE otherwise.
    * @return string $markup Generic markup for multiple instances.
    */
   private function render_multiple($post_id = FALSE, $shortcode = FALSE, $multiple = 0) {
@@ -397,7 +400,7 @@ private function render_multiple($post_id = FALSE, $shortcode = FALSE, $multiple
     // Get attributes.
     $atts = $this->get_atts($shortcode);
 
-    // Pre-process shortcode and retrieve args.
+    // Pre-process Shortcode and retrieve args.
     $args = $this->preprocess_atts($atts);
 
     // Get pathless markup from filter callback.
@@ -407,7 +410,7 @@ private function render_multiple($post_id = FALSE, $shortcode = FALSE, $multiple
       return apply_filters('civicrm_shortcode_get_markup', $markup, $atts, $args, 'multiple');
     }
 
-    // Get data for this shortcode.
+    // Get data for this Shortcode.
     $data = $this->get_data($atts, $args);
 
     // Sanity check.
@@ -433,7 +436,7 @@ private function render_multiple($post_id = FALSE, $shortcode = FALSE, $multiple
     // Access CiviCRM config object.
     $config = CRM_Core_Config::singleton();
 
-    // Do we have multiple shortcodes?
+    // Do we have multiple Shortcodes?
     if ($multiple != 0) {
 
       $links = [];
@@ -522,12 +525,11 @@ private function render_multiple($post_id = FALSE, $shortcode = FALSE, $multiple
       $link,
 
       /**
-       * Filter the CiviCRM shortcode more link text.
+       * Filter the CiviCRM Shortcode more link text.
        *
        * @since 4.6
        *
-       * @param str The existing shortcode more link text.
-       * @return str The modified shortcode more link text.
+       * @param str The existing Shortcode more link text.
        */
       apply_filters('civicrm_shortcode_more_link', __('Find out more...', 'civicrm'))
 
@@ -547,12 +549,11 @@ private function render_multiple($post_id = FALSE, $shortcode = FALSE, $multiple
       $empowered = sprintf(__('Empowered by %s', 'civicrm'), $civi_link);
 
       /**
-       * Filter the CiviCRM shortcode footer text.
+       * Filter the CiviCRM Shortcode footer text.
        *
        * @since 4.6
        *
-       * @param str $empowered The existing shortcode footer.
-       * @return str $empowered The modified shortcode footer.
+       * @param str $empowered The existing Shortcode footer.
        */
       $footer = apply_filters('civicrm_shortcode_footer', $empowered);
 
@@ -570,14 +571,13 @@ private function render_multiple($post_id = FALSE, $shortcode = FALSE, $multiple
     $markup = ob_get_clean();
 
     /**
-     * Filter the computed CiviCRM shortcode markup.
+     * Filter the computed CiviCRM Shortcode markup.
      *
      * @since 4.6
      *
-     * @param str $markup The computed shortcode markup.
+     * @param str $markup The computed Shortcode markup.
      * @param int $post_id The numeric ID of the WordPress post.
-     * @param string $shortcode The shortcode being parsed.
-     * @return str $markup The modified shortcode markup.
+     * @param string $shortcode The Shortcode being parsed.
      */
     return apply_filters('civicrm_shortcode_render_multiple', $markup, $post_id, $shortcode);
 
@@ -610,7 +610,7 @@ public function get_content($content) {
       return $content;
     }
 
-    // Bail if it has multiple shortcodes.
+    // Bail if it has multiple Shortcodes.
     if (count($this->shortcode_markup[$post->ID]) > 1) {
       return $content;
     }
@@ -635,7 +635,7 @@ public function get_title($title, $post_id) {
       return $title;
     }
 
-    // Bail if it has multiple shortcodes.
+    // Bail if it has multiple Shortcodes.
     if (count($this->shortcode_markup[$post_id]) > 1) {
       return $title;
     }
@@ -724,12 +724,12 @@ private function get_for_post($content) {
   }
 
   /**
-   * Return attributes for a given CiviCRM shortcode.
+   * Return attributes for a given CiviCRM Shortcode.
    *
    * @since 4.6
    *
-   * @param $shortcode The shortcode to parse.
-   * @return array $shortcode_atts Array of shortcode attributes.
+   * @param $shortcode The Shortcode to parse.
+   * @return array $shortcode_atts Array of Shortcode attributes.
    */
   private function get_atts($shortcode) {
 
@@ -745,7 +745,7 @@ private function get_atts($shortcode) {
   }
 
   /**
-   * Preprocess CiviCRM-defined shortcodes.
+   * Preprocess CiviCRM-defined Shortcodes.
    *
    * @since 4.6
    *
@@ -882,30 +882,29 @@ public function preprocess_atts($atts) {
     }
 
     /**
-     * Filter the CiviCRM shortcode arguments.
+     * Filter the CiviCRM Shortcode arguments.
      *
      * This filter allows plugins or CiviCRM Extensions to modify the attributes
-     * that the 'civicrm' shortcode allows. Injected attributes and their values
+     * that the 'civicrm' Shortcode allows. Injected attributes and their values
      * will also become available in the $_REQUEST and $_GET arrays.
      *
      * @since 4.7.28
      *
-     * @param array $args Existing shortcode arguments.
+     * @param array $args Existing Shortcode arguments.
      * @param array $shortcode_atts Shortcode attributes.
-     * @return array $args Modified shortcode arguments.
      */
     return apply_filters('civicrm_shortcode_preprocess_atts', $args, $shortcode_atts);
 
   }
 
   /**
-   * Post-process CiviCRM-defined shortcodes.
+   * Post-process CiviCRM-defined Shortcodes.
    *
    * @since 4.6
    *
    * @param array $atts Shortcode attributes array.
    * @param array $args Shortcode arguments array.
-   * @return array|bool $data The array data used to build the shortcode markup, or false on failure.
+   * @return array|bool $data The array data used to build the Shortcode markup, or false on failure.
    */
   public function get_data($atts, $args) {
 
@@ -920,18 +919,16 @@ public function get_data($atts, $args) {
      * Filter the base CiviCRM API parameters.
      *
      * This filter allows plugins or CiviCRM Extensions to modify the API call
-     * when there are multiple shortcodes being rendered.
+     * when there are multiple Shortcodes being rendered.
      *
      * @since 4.7.28
      *
      * @param array $params Existing API params.
      * @param array $atts Shortcode attributes array.
      * @param array $args Shortcode arguments array.
-     * @return array $params Modified API params.
      */
     $params = apply_filters('civicrm_shortcode_api_params', [
-      'version' => 3,
-      'sequential' => '1',
+      'sequential' => 1,
     ], $atts, $args);
 
     // Get the CiviCRM entity via the API.
@@ -943,7 +940,7 @@ public function get_data($atts, $args) {
         $params['id'] = $args['id'];
 
         // Call API.
-        $civi_entity = civicrm_api('contribution_page', 'getsingle', $params);
+        $civi_entity = civicrm_api3('ContributionPage', 'getsingle', $params);
 
         // Set title.
         $data['title'] = $civi_entity['title'];
@@ -962,7 +959,7 @@ public function get_data($atts, $args) {
         $params['id'] = $args['id'];
 
         // Call API.
-        $civi_entity = civicrm_api('event', 'getsingle', $params);
+        $civi_entity = civicrm_api3('Event', 'getsingle', $params);
 
         // Set title.
         switch ($atts['action']) {
@@ -1006,7 +1003,7 @@ public function get_data($atts, $args) {
         $params['id'] = $args['gid'];
 
         // Call API.
-        $civi_entity = civicrm_api('uf_group', 'getsingle', $params);
+        $civi_entity = civicrm_api3('UFGroup', 'getsingle', $params);
 
         // Set title.
         $data['title'] = $civi_entity['title'];
@@ -1021,7 +1018,7 @@ public function get_data($atts, $args) {
         $params['id'] = $atts['id'];
 
         // Call API.
-        $civi_entity = civicrm_api('survey', 'getsingle', $params);
+        $civi_entity = civicrm_api3('Survey', 'getsingle', $params);
 
         // Set title.
         $data['title'] = $civi_entity['title'];
@@ -1035,23 +1032,22 @@ public function get_data($atts, $args) {
         break;
 
       default:
-        // Do we need to protect against malformed shortcodes?
+        // Do we need to protect against malformed Shortcodes?
         break;
 
     }
 
     /**
-     * Filter the CiviCRM shortcode data array.
+     * Filter the CiviCRM Shortcode data array.
      *
      * This filter allows plugins or CiviCRM Extensions to modify the data used
-     * to display the shortcode when there are multiple shortcodes being rendered.
+     * to display the Shortcode when there are multiple Shortcodes being rendered.
      *
      * @since 4.7.28
      *
-     * @param array $data The existing shortcode data.
+     * @param array $data The existing Shortcode data.
      * @param array $atts Shortcode attributes array.
      * @param array $args Shortcode arguments array.
-     * @return array $data The modified shortcode data.
      */
     return apply_filters('civicrm_shortcode_get_data', $data, $atts, $args);
 
diff --git a/includes/civicrm.users.php b/includes/civicrm.users.php
index e4ee2f7..14a384f 100644
--- a/includes/civicrm.users.php
+++ b/includes/civicrm.users.php
@@ -47,7 +47,7 @@ public function __construct() {
     $this->civi = civi_wp();
 
     // Always listen for activation action.
-    add_action('civicrm_activation', [$this, 'activate']);
+    add_action('civicrm_activate', [$this, 'activate']);
 
   }
 
@@ -59,7 +59,7 @@ public function __construct() {
   public function activate() {
 
     /*
-     * Assign minimum capabilities for all WordPress roles and create
+     * Assign minimum capabilities to all WordPress roles and create
      * 'anonymous_user' role.
      */
     $this->set_wp_user_capabilities();
@@ -86,14 +86,22 @@ public function register_hooks() {
     add_action('profile_update', [$this, 'update_user']);
 
     // Delete ufMatch record when a WordPress user is deleted.
-    add_action('deleted_user', [$this, 'delete_user_ufmatch'], 10, 1);
+    add_action('deleted_user', [$this, 'delete_user_ufmatch']);
 
   }
 
   /**
    * Check permissions.
    *
-   * Authentication function used by basepage_register_hooks()
+   * This method only denies permission when the CiviCRM path that is requested
+   * begins with "civicrm/admin". Its intention seems to be to exclude admin
+   * requests from display on the front-end.
+   *
+   * Used internally by:
+   *
+   * - CiviCRM_For_WordPress_Basepage::basepage_handler()
+   * - CiviCRM_For_WordPress_Shortcodes::render_single()
+   * - civicrm_check_permission()
    *
    * @since 4.6
    *
@@ -113,7 +121,7 @@ public function check_permission($args) {
 
     require_once 'CRM/Utils/Array.php';
 
-    // All profile and file urls, as well as user dashboard and tell-a-friend are valid.
+    // All profile and file URLs, as well as user dashboard and tell-a-friend are valid.
     $arg1 = CRM_Utils_Array::value(1, $args);
     $invalidPaths = ['admin'];
     if (in_array($arg1, $invalidPaths)) {
@@ -195,8 +203,8 @@ public function update_user($user_id) {
    */
   public function sync_user($user = FALSE) {
 
-    // Sanity check
-    if ($user === FALSE || !is_a($user, 'WP_User')) {
+    // Sanity check.
+    if ($user === FALSE || !($user instanceof WP_User)) {
       return;
     }
 
@@ -258,11 +266,6 @@ public function delete_user_ufmatch($user_id) {
    */
   public function set_wp_user_capabilities() {
 
-    global $wp_roles;
-    if (!isset($wp_roles)) {
-      $wp_roles = new WP_Roles();
-    }
-
     // Define minimum capabilities (CiviCRM permissions).
     $default_min_capabilities = [
       'access_civimail_subscribe_unsubscribe_pages' => 1,
@@ -284,11 +287,11 @@ public function set_wp_user_capabilities() {
      * @since 4.6
      *
      * @param array $default_min_capabilities The minimum capabilities.
-     * @return array $default_min_capabilities The modified capabilities.
      */
     $min_capabilities = apply_filters('civicrm_min_capabilities', $default_min_capabilities);
 
     // Assign the minimum capabilities to all WordPress roles.
+    $wp_roles = wp_roles();
     foreach ($wp_roles->role_names as $role => $name) {
       $roleObj = $wp_roles->get_role($role);
       foreach ($min_capabilities as $capability_name => $capability_value) {
@@ -298,11 +301,7 @@ public function set_wp_user_capabilities() {
 
     // Add the 'anonymous_user' role with minimum capabilities.
     if (!in_array('anonymous_user', $wp_roles->roles)) {
-      add_role(
-        'anonymous_user',
-        __('Anonymous User', 'civicrm'),
-        $min_capabilities
-      );
+      add_role('anonymous_user', __('Anonymous User', 'civicrm'), $min_capabilities);
     }
 
   }
@@ -319,11 +318,7 @@ public function set_wp_user_capabilities() {
    */
   public function set_access_capabilities() {
 
-    // Test for existing global
-    global $wp_roles;
-    if (!isset($wp_roles)) {
-      $wp_roles = new WP_Roles();
-    }
+    $wp_roles = wp_roles();
 
     /**
      * Filter the default roles with access to CiviCRM.
@@ -334,7 +329,6 @@ public function set_access_capabilities() {
      * @since 4.6
      *
      * @param array The default roles with access to CiviCRM.
-     * @return array The modified roles with access to CiviCRM.
      */
     $roles = apply_filters('civicrm_access_roles', ['super admin', 'administrator']);
 
diff --git a/uninstall.php b/uninstall.php
index 4dfde30..ae999bb 100644
--- a/uninstall.php
+++ b/uninstall.php
@@ -24,3 +24,8 @@
 
 // Delete options that this plugin has set.
 delete_option('civicrm_activation_in_progress');
+delete_option('civicrm_rules_flushed');
+
+// TODO: Remove the CiviCRM Base Page(s).
+// TODO: Remove the directory/directories that "civicrm.settings.php" lives in.
+// TODO: Remove the CiviCRM database(s).
diff --git a/wp-cli/LICENSE b/wp-cli/LICENSE
deleted file mode 100644
index 3ffc567..0000000
--- a/wp-cli/LICENSE
+++ /dev/null
@@ -1,661 +0,0 @@
-GNU AFFERO GENERAL PUBLIC LICENSE
-                       Version 3, 19 November 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The GNU Affero General Public License is a free, copyleft license for
-software and other kinds of works, specifically designed to ensure
-cooperation with the community in the case of network server software.
-
-  The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works.  By contrast,
-our General Public Licenses are intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
-  Developers that use our General Public Licenses protect your rights
-with two steps: (1) assert copyright on the software, and (2) offer
-you this License which gives you legal permission to copy, distribute
-and/or modify the software.
-
-  A secondary benefit of defending all users' freedom is that
-improvements made in alternate versions of the program, if they
-receive widespread use, become available for other developers to
-incorporate.  Many developers of free software are heartened and
-encouraged by the resulting cooperation.  However, in the case of
-software used on network servers, this result may fail to come about.
-The GNU General Public License permits making a modified version and
-letting the public access it on a server without ever releasing its
-source code to the public.
-
-  The GNU Affero General Public License is designed specifically to
-ensure that, in such cases, the modified source code becomes available
-to the community.  It requires the operator of a network server to
-provide the source code of the modified version running there to the
-users of that server.  Therefore, public use of a modified version, on
-a publicly accessible server, gives the public access to the source
-code of the modified version.
-
-  An older license, called the Affero General Public License and
-published by Affero, was designed to accomplish similar goals.  This is
-a different license, not a version of the Affero GPL, but Affero has
-released a new version of the Affero GPL which permits relicensing under
-this license.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                       TERMS AND CONDITIONS
-
-  0. Definitions.
-
-  "This License" refers to version 3 of the GNU Affero General Public License.
-
-  "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
-  "The Program" refers to any copyrightable work licensed under this
-License.  Each licensee is addressed as "you".  "Licensees" and
-"recipients" may be individuals or organizations.
-
-  To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy.  The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
-  A "covered work" means either the unmodified Program or a work based
-on the Program.
-
-  To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy.  Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
-  To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies.  Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
-  An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License.  If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
-  1. Source Code.
-
-  The "source code" for a work means the preferred form of the work
-for making modifications to it.  "Object code" means any non-source
-form of a work.
-
-  A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
-  The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form.  A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
-  The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities.  However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work.  For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
-  The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
-  The Corresponding Source for a work in source code form is that
-same work.
-
-  2. Basic Permissions.
-
-  All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met.  This License explicitly affirms your unlimited
-permission to run the unmodified Program.  The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work.  This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
-  You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force.  You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright.  Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
-  Conveying under any other circumstances is permitted solely under
-the conditions stated below.  Sublicensing is not allowed; section 10
-makes it unnecessary.
-
-  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
-  No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
-  When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
-  4. Conveying Verbatim Copies.
-
-  You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
-  You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
-  5. Conveying Modified Source Versions.
-
-  You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
-    a) The work must carry prominent notices stating that you modified
-    it, and giving a relevant date.
-
-    b) The work must carry prominent notices stating that it is
-    released under this License and any conditions added under section
-    7.  This requirement modifies the requirement in section 4 to
-    "keep intact all notices".
-
-    c) You must license the entire work, as a whole, under this
-    License to anyone who comes into possession of a copy.  This
-    License will therefore apply, along with any applicable section 7
-    additional terms, to the whole of the work, and all its parts,
-    regardless of how they are packaged.  This License gives no
-    permission to license the work in any other way, but it does not
-    invalidate such permission if you have separately received it.
-
-    d) If the work has interactive user interfaces, each must display
-    Appropriate Legal Notices; however, if the Program has interactive
-    interfaces that do not display Appropriate Legal Notices, your
-    work need not make them do so.
-
-  A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit.  Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
-  6. Conveying Non-Source Forms.
-
-  You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
-    a) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by the
-    Corresponding Source fixed on a durable physical medium
-    customarily used for software interchange.
-
-    b) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by a
-    written offer, valid for at least three years and valid for as
-    long as you offer spare parts or customer support for that product
-    model, to give anyone who possesses the object code either (1) a
-    copy of the Corresponding Source for all the software in the
-    product that is covered by this License, on a durable physical
-    medium customarily used for software interchange, for a price no
-    more than your reasonable cost of physically performing this
-    conveying of source, or (2) access to copy the
-    Corresponding Source from a network server at no charge.
-
-    c) Convey individual copies of the object code with a copy of the
-    written offer to provide the Corresponding Source.  This
-    alternative is allowed only occasionally and noncommercially, and
-    only if you received the object code with such an offer, in accord
-    with subsection 6b.
-
-    d) Convey the object code by offering access from a designated
-    place (gratis or for a charge), and offer equivalent access to the
-    Corresponding Source in the same way through the same place at no
-    further charge.  You need not require recipients to copy the
-    Corresponding Source along with the object code.  If the place to
-    copy the object code is a network server, the Corresponding Source
-    may be on a different server (operated by you or a third party)
-    that supports equivalent copying facilities, provided you maintain
-    clear directions next to the object code saying where to find the
-    Corresponding Source.  Regardless of what server hosts the
-    Corresponding Source, you remain obligated to ensure that it is
-    available for as long as needed to satisfy these requirements.
-
-    e) Convey the object code using peer-to-peer transmission, provided
-    you inform other peers where the object code and Corresponding
-    Source of the work are being offered to the general public at no
-    charge under subsection 6d.
-
-  A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
-  A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling.  In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage.  For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product.  A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
-  "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source.  The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
-  If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information.  But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
-  The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed.  Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
-  Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
-  7. Additional Terms.
-
-  "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law.  If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
-  When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it.  (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.)  You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
-  Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
-    a) Disclaiming warranty or limiting liability differently from the
-    terms of sections 15 and 16 of this License; or
-
-    b) Requiring preservation of specified reasonable legal notices or
-    author attributions in that material or in the Appropriate Legal
-    Notices displayed by works containing it; or
-
-    c) Prohibiting misrepresentation of the origin of that material, or
-    requiring that modified versions of such material be marked in
-    reasonable ways as different from the original version; or
-
-    d) Limiting the use for publicity purposes of names of licensors or
-    authors of the material; or
-
-    e) Declining to grant rights under trademark law for use of some
-    trade names, trademarks, or service marks; or
-
-    f) Requiring indemnification of licensors and authors of that
-    material by anyone who conveys the material (or modified versions of
-    it) with contractual assumptions of liability to the recipient, for
-    any liability that these contractual assumptions directly impose on
-    those licensors and authors.
-
-  All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10.  If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term.  If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
-  If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
-  Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
-  8. Termination.
-
-  You may not propagate or modify a covered work except as expressly
-provided under this License.  Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
-  However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
-  Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
-  Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License.  If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
-  9. Acceptance Not Required for Having Copies.
-
-  You are not required to accept this License in order to receive or
-run a copy of the Program.  Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance.  However,
-nothing other than this License grants you permission to propagate or
-modify any covered work.  These actions infringe copyright if you do
-not accept this License.  Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
-  10. Automatic Licensing of Downstream Recipients.
-
-  Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License.  You are not responsible
-for enforcing compliance by third parties with this License.
-
-  An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations.  If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
-  You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License.  For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
-  11. Patents.
-
-  A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based.  The
-work thus licensed is called the contributor's "contributor version".
-
-  A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version.  For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
-  Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
-  In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement).  To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
-  If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients.  "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
-  If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
-  A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License.  You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
-  Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
-  12. No Surrender of Others' Freedom.
-
-  If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all.  For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
-  13. Remote Network Interaction; Use with the GNU General Public License.
-
-  Notwithstanding any other provision of this License, if you modify the
-Program, your modified version must prominently offer all users
-interacting with it remotely through a computer network (if your version
-supports such interaction) an opportunity to receive the Corresponding
-Source of your version by providing access to the Corresponding Source
-from a network server at no charge, through some standard or customary
-means of facilitating copying of software.  This Corresponding Source
-shall include the Corresponding Source for any work covered by version 3
-of the GNU General Public License that is incorporated pursuant to the
-following paragraph.
-
-  Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU General Public License into a single
-combined work, and to convey the resulting work.  The terms of this
-License will continue to apply to the part which is the covered work,
-but the work with which it is combined will remain governed by version
-3 of the GNU General Public License.
-
-  14. Revised Versions of this License.
-
-  The Free Software Foundation may publish revised and/or new versions of
-the GNU Affero General Public License from time to time.  Such new versions
-will be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-  Each version is given a distinguishing version number.  If the
-Program specifies that a certain numbered version of the GNU Affero General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation.  If the Program does not specify a version number of the
-GNU Affero General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
-  If the Program specifies that a proxy can decide which future
-versions of the GNU Affero General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
-  Later license versions may give you additional or different
-permissions.  However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
-  15. Disclaimer of Warranty.
-
-  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. Limitation of Liability.
-
-  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
-  17. Interpretation of Sections 15 and 16.
-
-  If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU Affero General Public License as published
-    by the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program 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
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
-  If your software can interact with users remotely through a computer
-network, you should also make sure that it provides a way for users to
-get its source.  For example, if your program is a web application, its
-interface could display a "Source" link that leads users to an archive
-of the code.  There are many ways you could offer source, and different
-solutions will be better for different programs; see section 13 for the
-specific requirements.
-
-  You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU AGPL, see
-<http://www.gnu.org/licenses/>.
\ No newline at end of file
diff --git a/wp-cli/civicrm.php b/wp-cli/civicrm.php
index e13d2b2..fe93a39 100644
--- a/wp-cli/civicrm.php
+++ b/wp-cli/civicrm.php
@@ -9,15 +9,22 @@
  +--------------------------------------------------------------------+
  */
 
+/**
+ *
+ * @package CRM
+ * @copyright CiviCRM LLC https://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
+   * WP-CLI port of drush-civicrm integration.
+   *
+   * @see https://github.com/andy-walker/wp-cli-civicrm
    *
-   * Distributed under the GNU Affero General Public License, version 3
-   * http://www.gnu.org/licenses/agpl-3.0.html
+   * @since 4.5
    */
   class CiviCRM_Command extends WP_CLI_Command {
 
@@ -28,27 +35,27 @@ class CiviCRM_Command extends WP_CLI_Command {
      * WP-CLI integration with CiviCRM.
      *
      * wp civicrm api
-     * ===============
-     * Command for accessing CiviCRM APIs. Syntax is identical to drush cvap.
+     * ==============
+     * Command for accessing the CiviCRM API. Syntax is identical to `drush cvap`.
      *
      * wp civicrm cache-clear
-     * ===============
-     * Command for accessing clearing cache.  Equivilant of running civicrm/admin/setting/updateConfigBackend&reset=1
+     * ======================
+     * 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
@@ -59,15 +66,15 @@ class CiviCRM_Command extends WP_CLI_Command {
      *
      * wp civicrm restore
      * ==================
-     * Restore CiviCRM codebase and database back from the specified backup directory
+     * Restore CiviCRM codebase and database back from the specified backup directory.
      *
      * wp civicrm sql-conf
      * ===================
-     * Show civicrm database connection details.
+     * Show CiviCRM database connection details.
      *
      * wp civicrm sql-connect
      * ======================
-     * A string which connects to the civicrm database.
+     * A string which connects to the CiviCRM database.
      *
      * wp civicrm sql-cli
      * ==================
@@ -80,11 +87,11 @@ class CiviCRM_Command extends WP_CLI_Command {
      * 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.";
+     * <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.
+     * Update config_backend to correct config settings, especially when the CiviCRM site has been cloned or migrated.
      *
      * wp civicrm upgrade
      * ==================
@@ -95,7 +102,7 @@ class CiviCRM_Command extends WP_CLI_Command {
      * 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.
@@ -107,6 +114,7 @@ class CiviCRM_Command extends WP_CLI_Command {
      * --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.
+     * --zipfile           Path to your CiviCRM zip file.
      *
      */
     public function __invoke($args, $assoc_args) {
@@ -114,7 +122,7 @@ public function __invoke($args, $assoc_args) {
       $this->args       = $args;
       $this->assoc_args = $assoc_args;
 
-      # define command router
+      // Define command router.
       $command_router = [
         'api'                => 'api',
         'cache-clear'        => 'cacheClear',
@@ -135,26 +143,33 @@ public function __invoke($args, $assoc_args) {
         'upgrade-db'         => 'upgradeDB',
       ];
 
-      # get command
+      // Get the command.
       $command = array_shift($args);
 
-      # check for existence of Civi (except for command 'install')
-      if (!function_exists('civicrm_initialize') and 'install' != $command) {
+      // Allow help to pass.
+      if ('help' === $command) {
+        return;
+      }
+
+      // Check for existence of CiviCRM (except for command 'install').
+      if (!function_exists('civicrm_initialize') && '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'");
+      // Check existence of router entry / handler method.
+      if (!isset($command_router[$command]) || !method_exists($this, $command_router[$command])) {
+        return WP_CLI::error(sprintf('Unrecognized command: %s', $command));
       }
 
-      # run command
+      // Run command.
       return $this->{$command_router[$command]}();
 
     }
 
     /**
-     * Implementation of command 'api'
+     * Implementation of command 'api'.
+     *
+     * @since 4.5
      */
     private function api() {
 
@@ -164,11 +179,11 @@ private function api() {
       list($entity, $action) = explode('.', $this->args[0]);
       array_shift($this->args);
 
-      # parse $params
+      //  Parse params.
       $format = $this->getOption('in', 'args');
       switch ($format) {
 
-        # input params supplied via args ..
+        //  Input params supplied via args.
         case 'args':
           $params = $defaults;
           foreach ($this->args as $arg) {
@@ -177,20 +192,21 @@ private function api() {
           }
           break;
 
-        # input params supplied via json ..
+        //  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);
+          WP_CLI::error(sprintf('Unknown format: %s', $format));
           break;
+
       }
 
       civicrm_initialize();
 
-      // CRM-18062: Set CiviCRM timezone if any
+      // 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) {
@@ -200,32 +216,34 @@ private function api() {
 
       $result = civicrm_api($entity, $action, $params);
 
-      // restore WP's timezone
+      // Restore WordPress's timezone.
       if ($wp_base_timezone) {
         date_default_timezone_set($wp_base_timezone);
       }
 
       switch ($this->getOption('out', 'pretty')) {
 
-        # pretty-print output (default)
+        // Pretty-print output (default).
         case 'pretty':
           WP_CLI::line(print_r($result, TRUE));
           break;
 
-        # display output as json
+        // Display output as json.
         case 'json':
           WP_CLI::line(json_encode($result));
           break;
 
         default:
-          return WP_CLI::error('Unknown format: ' . $format);
+          return WP_CLI::error(sprintf('Unknown format: %s', $format));
 
       }
 
     }
 
     /**
-     * Implementation of command 'cache-clear'
+     * Implementation of command 'cache-clear'.
+     *
+     * @since 4.5
      */
     private function cacheClear() {
 
@@ -233,20 +251,22 @@ private function cacheClear() {
       require_once 'CRM/Core/Config.php';
       $config = CRM_Core_Config::singleton();
 
-      # clear db caching
+      // Clear db caching.
       $config->clearDBCache();
 
-      # also cleanup the templates_c directory
+      // Also cleanup the templates_c directory.
       $config->cleanup(1, FALSE);
 
-      # also cleanup the session object
+      // Also cleanup the session object.
       $session = CRM_Core_Session::singleton();
       $session->reset(1);
 
     }
 
     /**
-     * Implementation of command 'enable-debug'
+     * Implementation of command 'enable-debug'.
+     *
+     * @since 4.5
      */
     private function enableDebug() {
       civicrm_initialize();
@@ -258,7 +278,9 @@ private function enableDebug() {
     }
 
     /**
-     * Implementation of command 'disable-debug'
+     * Implementation of command 'disable-debug'.
+     *
+     * @since 4.7
      */
     private function disableDebug() {
       civicrm_initialize();
@@ -270,34 +292,30 @@ private function disableDebug() {
     }
 
     /**
-     * Implementation of command 'install'
+     * Implementation of command 'install'.
+     *
+     * @since 4.5
      */
     private function install() {
 
-      # validate
-
+      // 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)) {
+      if ($lang = $this->getOption('lang', FALSE) && !$langtarfile = $this->getOption('langtarfile', FALSE)) {
         return WP_CLI::error('CiviCRM language tarfile not specified.');
       }
 
-      # begin install
-
+      // Begin install.
       if ($plugin_path = $this->getOption('destination', FALSE)) {
         $plugin_path = ABSPATH . $plugin_path;
       }
@@ -309,10 +327,10 @@ private function install() {
       $crmPath = "$plugin_path/civicrm";
       $crm_files_present = is_dir($crmPath);
 
-      # extract the archive
+      // 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 ..
+        // Should probably never get to here as WordPress CiviCRM comes as a zip file.
+        // Check anyway just in case that ever changes.
         if ($crm_files_present) {
           return WP_CLI::error('Existing CiviCRM found. No action taken.');
         }
@@ -327,19 +345,18 @@ private function install() {
         }
 
         if (!$this->unzip(dirname($plugin_path))) {
-          return WP_CLI::error('Error extracting zipfile');
+          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.
-
+        // 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');
+        return WP_CLI::error('No zipfile specified, use "--zipfile=path/to/zipfile" or extract file ahead of time.');
       }
 
-      # include civicrm installer helper file
+      // Include CiviCRM Installer helper file.
       $civicrm_installer_helper = "$crmPath/install/civicrm.php";
 
       if (!file_exists($civicrm_installer_helper)) {
@@ -351,25 +368,25 @@ private function install() {
         WP_CLI::success('Using installer files found on the site.');
       }
       else {
-        // We must've just unpacked the archive because it wasn't there
-        // before.
+        // 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');
+          return WP_CLI::error('No language tarfile specified, use "--langtarfile=path/to/tarfile".');
         }
       }
 
-      # create files dirs
+      // 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);
       WP_CLI::launch("chmod -R 0755 " . escapeshellarg($settings_dir));
 
-      # now we've got some files in place, require PEAR DB and check db setup
+      // 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}";
 
@@ -392,29 +409,28 @@ private function install() {
         $db->disconnect();
       }
 
-      # install db
+      // Install database.
       global $sqlPath;
 
-      # setup database with civicrm structure and data
-      WP_CLI::line('Loading CiviCRM database structure ..');
+      // 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 ..');
+      WP_CLI::line('Loading CiviCRM database with required data...');
 
-      # testing the translated sql files availability
+      // 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
+          && file_exists($sqlPath . '/civicrm_acl.' . $lang . '.mysql')
+          && '' != $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.");
+          WP_CLI::warning(sprintf('No SQL files could be retrieved for "%s" using default language.', $lang));
         }
       }
 
@@ -423,13 +439,13 @@ private function install() {
 
       WP_CLI::success('CiviCRM database loaded successfully.');
 
-      # generate civicrm.settings.php file
+      // 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 ..');
+      WP_CLI::line('Generating CiviCRM settings file...');
 
       if ($base_url = $this->getOption('site_url', FALSE)) {
         $ssl      = $this->getOption('ssl', FALSE);
@@ -474,14 +490,34 @@ private function install() {
       WP_CLI::launch("chmod 0644 $config_file");
       WP_CLI::success(sprintf('Settings file generated: %s', $config_file));
 
-      # activate plugin and we're done
+      // Activate plugin.
       @WP_CLI::run_command(['plugin', 'activate', 'civicrm'], []);
+
+      // Bootstrap the plugin.
+      $civicrm = civi_wp();
+      $civicrm->include_files();
+      $civicrm->setup_objects();
+      $civicrm->enable_translation();
+
+      // Add the "wpLoadPhp" setting.
+      $civicrm->admin->add_wpload_setting();
+
+      // Add Base Page and "wpBasePage" setting.
+      $basepage = $civicrm->basepage->create_wp_basepage();
+      if (!$basepage) {
+        return WP_CLI::error('Could not create the Base Page.');
+      }
+      WP_CLI::success('Base Page created successfully.');
+
+      // Now we're done.
       WP_CLI::success('CiviCRM installed.');
 
     }
 
     /**
-     * Implementation of command 'member-records'
+     * Implementation of command 'member-records'.
+     *
+     * @since 4.5
      */
     private function memberRecords() {
 
@@ -491,7 +527,7 @@ private function memberRecords() {
 
         $job = new CRM_Core_JobManager();
         $job->executeJobByAction('job', 'process_membership');
-        WP_CLI::success("Executed 'process_membership' job.");
+        WP_CLI::success('Executed "process_membership" job.');
 
       }
       else {
@@ -520,7 +556,9 @@ private function memberRecords() {
     }
 
     /**
-     * Implementation of command 'process-mail-queue'
+     * Implementation of command 'process-mail-queue'.
+     *
+     * @since 4.5
      */
     private function processMailQueue() {
 
@@ -544,7 +582,9 @@ private function processMailQueue() {
     }
 
     /**
-     * Implementation of command 'rest'
+     * Implementation of command 'rest'.
+     *
+     * @since 4.5
      */
     private function rest() {
 
@@ -570,7 +610,7 @@ private function rest() {
       $config = CRM_Core_Config::singleton();
 
       global $civicrm_root;
-      // adding dummy script, since based on this api file path is computed.
+      // Adding dummy script, since based on this api file path is computed.
       $_SERVER['SCRIPT_FILENAME'] = "$civicrm_root/extern/rest.php";
 
       if (isset($_GET['json']) && $_GET['json']) {
@@ -585,31 +625,33 @@ private function rest() {
     }
 
     /**
-     * Implementation of command 'restore'
+     * Implementation of command 'restore'.
+     *
+     * @since 4.5
      */
     private function restore() {
 
-      # validate ..
+      // Validate.
       $restore_dir = $this->getOption('restore-dir', FALSE);
       $restore_dir = rtrim($restore_dir, '/');
       if (!$restore_dir) {
-        return WP_CLI::error('Restore-dir not specified.');
+        return WP_CLI::error('"restore-dir" not specified.');
       }
 
       $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.');
+        return WP_CLI::error('Could not locate "civicrm.sql" file in the restore directory.');
       }
 
       $code_dir = $restore_dir . '/civicrm';
       if (!is_dir($code_dir)) {
-        return WP_CLI::error('Could not locate civicrm directory inside restore-dir.');
+        return WP_CLI::error('Could not locate the 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.');
+      elseif (!file_exists("$code_dir/civicrm/civicrm-version.txt") && !file_exists("$code_dir/civicrm/civicrm-version.php")) {
+        return WP_CLI::error('The CiviCRM directory inside "restore-dir" does not seem to be a valid CiviCRM codebase.');
       }
 
-      # prepare to restore ..
+      // Prepare to restore.
       $date = date('YmdHis');
 
       civicrm_initialize();
@@ -632,7 +674,7 @@ private function restore() {
       $restore_backup_dir = $this->getOption('backup-dir', $wp_root . '/../backup');
       $restore_backup_dir = rtrim($restore_backup_dir, '/');
 
-      # get confirmation from user -
+      // Get confirmation from user.
 
       if (!defined('CIVICRM_DSN')) {
         WP_CLI::error('CIVICRM_DSN is not defined.');
@@ -645,7 +687,7 @@ private function restore() {
       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(sprintf("Note: Before restoring, a backup will be taken in '%s' directory.", "$restore_backup_dir/plugins/restore"));
       WP_CLI::line('');
 
       WP_CLI::confirm('Do you really want to continue?');
@@ -653,22 +695,22 @@ private function restore() {
       $restore_backup_dir .= '/plugins/restore/' . $date;
 
       if (!mkdir($restore_backup_dir, 0755, TRUE)) {
-        return WP_CLI::error('Failed creating directory: ' . $restore_backup_dir);
+        return WP_CLI::error(sprintf('Failed to create directory: %s', $restore_backup_dir));
       }
 
-      # 1. backup and restore codebase
-      WP_CLI::line('Restoring civicrm codebase ..');
+      // 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));
       }
 
       if (!rename($code_dir, $project_path)) {
-        return WP_CLI::error("Failed to restore civicrm directory '%s' to '%s'", $code_dir, $project_path);
+        return WP_CLI::error(sprintf("Failed to restore CiviCRM directory '%s' to '%s'", $code_dir, $project_path));
       }
 
       WP_CLI::success('Codebase restored.');
 
-      # 2. backup, drop and create database
+      // 2. Backup, drop and create database.
       WP_CLI::run_command(
         ['civicrm', 'sql-dump'],
         ['result-file' => $restore_backup_dir . '/civicrm.sql']
@@ -676,8 +718,7 @@ private function restore() {
 
       WP_CLI::success('Database backed up.');
 
-      # prepare a mysql command-line string for issuing
-      # db drop / create commands
+      // Prepare a mysql command-line string for issuing db drop/create commands.
       $command = sprintf(
         'mysql --user=%s --password=%s',
         $db_spec['username'],
@@ -688,31 +729,31 @@ private function restore() {
         $command .= ' --host=' . $db_spec['hostspec'];
       }
 
-      if (isset($dsn['port']) and !mpty($dsn['port'])) {
+      if (isset($dsn['port']) && !mpty($dsn['port'])) {
         $command .= ' --port=' . $db_spec['port'];
       }
 
-      # attempt to drop old database
+      // 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']);
+        return WP_CLI::error(sprintf('Could not drop database: %s', $db_spec['database']));
       }
 
       WP_CLI::success('Database dropped.');
 
-      # attempt to create new database
+      // 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']);
+        WP_CLI::error(sprintf('Could not create new database: %s', $db_spec['database']));
       }
 
       WP_CLI::success('Database created.');
 
-      # 3. restore database
-      WP_CLI::line('Loading civicrm.sql file from restore-dir ..');
+      // 3. Restore database.
+      WP_CLI::line('Loading "civicrm.sql" file from "restore-dir"...');
       system($command . ' ' . $db_spec['database'] . ' < ' . $sql_file);
 
       WP_CLI::success('Database restored.');
 
-      WP_CLI::line('Clearing caches..');
+      WP_CLI::line('Clearing caches...');
       WP_CLI::run_command(['civicrm', 'cache-clear']);
 
       WP_CLI::success('Restore process completed.');
@@ -720,7 +761,9 @@ private function restore() {
     }
 
     /**
-     * Implementation of command 'sql-conf'
+     * Implementation of command 'sql-conf'.
+     *
+     * @since 4.5
      */
     private function sqlConf() {
 
@@ -734,7 +777,9 @@ private function sqlConf() {
     }
 
     /**
-     * Implementation of command 'sql-connect'
+     * Implementation of command 'sql-connect'.
+     *
+     * @since 4.5
      */
     private function sqlConnect() {
 
@@ -753,7 +798,7 @@ private function sqlConnect() {
         $dsn['password']
       );
 
-      if (isset($dsn['port']) and !empty($dsn['port'])) {
+      if (isset($dsn['port']) && !empty($dsn['port'])) {
         $command .= ' --port=' . $dsn['port'];
       }
 
@@ -762,16 +807,18 @@ private function sqlConnect() {
     }
 
     /**
-     * Implementation of command 'sql-dump'
+     * Implementation of command 'sql-dump'.
+     *
+     * @since 4.5
      */
     private function sqlDump() {
 
-      # bootstrap Civi when we're not being called as part of an upgrade
+      // Bootstrap CiviCRM when we're not being called as part of an upgrade.
       if (!defined('CIVICRM_UPGRADE_ACTIVE')) {
         civicrm_initialize();
       }
 
-      if (!defined('CIVICRM_DSN') and !defined('CIVICRM_OLD_DSN')) {
+      if (!defined('CIVICRM_DSN') && !defined('CIVICRM_OLD_DSN')) {
         WP_CLI::error('DSN is not defined.');
       }
 
@@ -809,7 +856,9 @@ private function sqlDump() {
     }
 
     /**
-     * Implementation of command 'sql-query'
+     * Implementation of command 'sql-query'.
+     *
+     * @since 4.5
      */
     private function sqlQuery() {
 
@@ -840,7 +889,9 @@ private function sqlQuery() {
     }
 
     /**
-     * Implementation of command 'sql-cli'
+     * Implementation of command 'sql-cli'.
+     *
+     * @since 4.5
      */
     private function sqlCLI() {
 
@@ -863,7 +914,9 @@ private function sqlCLI() {
     }
 
     /**
-     * Implementation of command 'update-cfg'
+     * Implementation of command 'update-cfg'.
+     *
+     * @since 4.5
      */
     private function updateConfig() {
 
@@ -891,8 +944,8 @@ private function updateConfig() {
 
       if ($result) {
 
-        # attempt to preserve webserver ownership of templates_c, civicrm/upload
-        if ($webserver_user and $webserver_group) {
+        // Attempt to preserve webserver ownership of templates_c, civicrm/upload.
+        if ($webserver_user && $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));
@@ -909,17 +962,19 @@ private function updateConfig() {
     }
 
     /**
-     * Implementation of command 'upgrade'
+     * Implementation of command 'upgrade'.
+     *
+     * @since 4.5
      */
     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)) {
+      // 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) && !$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.
+      // FIXME: Throw error if tarfile is not in a valid format.
       if (!defined('CIVICRM_UPGRADE_ACTIVE')) {
         define('CIVICRM_UPGRADE_ACTIVE', 1);
       }
@@ -930,18 +985,20 @@ private function upgrade() {
       $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);
+        return WP_CLI::error(sprintf('Unable to locate settings file at "%s" or at "%s"', $legacy_settings_file, $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.
+      /*
+       * 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);
@@ -975,7 +1032,7 @@ private function upgrade() {
       }
 
       if (!defined('CIVICRM_OLD_DSN')) {
-        return WP_CLI::error('Unable to set CIVICRM_OLD_DSN');
+        return WP_CLI::error('Unable to set CIVICRM_OLD_DSN.');
       }
 
       $date        = date('YmdHis');
@@ -995,29 +1052,26 @@ private function upgrade() {
       $backup_dir = $this->getOption('backup-dir', $wp_root . '../backup');
       $backup_dir = rtrim($backup_dir, '/');
 
-      WP_CLI::line("\nThe upgrade process involves - ");
+      WP_CLI::line();
+      WP_CLI::line('The 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::line('4. Executing "civicrm/upgrade?reset=1" just as a browser would.');
+      WP_CLI::line();
 
       WP_CLI::confirm('Do you really want to continue?');
 
-      # begin upgrade
-
+      // Begin upgrade.
       $backup_dir .= '/plugins/' . $date;
       if (!mkdir($backup_dir, 0755, TRUE)) {
-        return WP_CLI::error('Failed creating directory: ' . $backup_dir);
+        return WP_CLI::error(sprintf('Failed to create directory: %s', $backup_dir));
       }
 
       $backup_target = $backup_dir . '/' . $backup_file;
 
       if (!rename($project_path, $backup_target)) {
-        return WP_CLI::error(sprintf(
-          'Failed to backup CiviCRM project directory %s to %s',
-          $project_path,
-          $backup_target
-        ));
+        return WP_CLI::error(sprintf('Failed to backup CiviCRM project directory %s to %s', $project_path, $backup_target));
       }
 
       WP_CLI::line();
@@ -1030,10 +1084,9 @@ private function upgrade() {
 
       WP_CLI::success('2. Database backed up.');
 
-      # decompress
+      // Decompress.
       if ($this->getOption('tarfile', FALSE)) {
-        # should probably never get to here, as looks like Wordpress Civi comes
-        # in a zip file
+        // Should probably never get to here, because WordPress CiviCRM comes in a zip file.
         if (!$this->untar($plugin_path)) {
           return WP_CLI::error('Error extracting tarfile');
         }
@@ -1053,10 +1106,10 @@ private function upgrade() {
       define('CIVICRM_SETTINGS_PATH', $project_path . 'civicrm.settings.php');
 
       if (!copy($backup_dir . '/civicrm/civicrm.settings.php', CIVICRM_SETTINGS_PATH)) {
-        return WP_CLI::error('Failed to copy file');
+        return WP_CLI::error('Failed to copy file.');
       }
 
-      WP_CLI::success('4. ');
+      WP_CLI::success('4. Settings file copied.');
 
       WP_CLI::run_command(['civicrm', 'upgrade-db'], []);
 
@@ -1065,7 +1118,9 @@ private function upgrade() {
     }
 
     /**
-     * Implementation of command 'upgrade-db'
+     * Implementation of command 'upgrade-db'.
+     *
+     * @since 4.5
      */
     private function upgradeDB() {
 
@@ -1076,11 +1131,12 @@ private function upgradeDB() {
       }
 
       if (class_exists('CRM_Upgrade_Headless')) {
-        # Note: CRM_Upgrade_Headless introduced in 4.2 -- at the same time as class auto-loading
+
+        // 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();
-          WP_CLI::line('Upgrade outputs: ' . '"' . $result['message'] . '"');
+          WP_CLI::line(sprintf('Upgrade outputs: "%s"', $result['message']));
         }
         catch (Exception $e) {
           WP_CLI::error($e->getMessage());
@@ -1095,18 +1151,18 @@ private function upgradeDB() {
         require_once 'CRM/Upgrade/Page/Upgrade.php';
         $upgrade = new CRM_Upgrade_Page_Upgrade();
 
-        // new since CiviCRM 4.1
+        // New since CiviCRM 4.1.
         if (is_callable([$upgrade, 'setPrint'])) {
           $upgrade->setPrint(TRUE);
         }
 
-        # to suppress html output /w source code.
+        // To suppress HTML output with source code.
         ob_start();
         $upgrade->run();
-        # capture the required message.
+        // Capture the required message.
         $result = $template->get_template_vars('message');
         ob_end_clean();
-        WP_CLI::line('Upgrade outputs: ' . "\"$result\"");
+        WP_CLI::line(sprintf('Upgrade outputs: "%s"', $result));
 
       }
 
@@ -1114,9 +1170,12 @@ private function upgradeDB() {
 
     /**
      * 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
-     * @param  $dsn (string)
-     * @return array containing db connection details
+     * bootstrapped environment we can access this from, eg: when doing an upgrade.
+     *
+     * @since 4.5
+     *
+     * @param string|array $dsn
+     * @return array $parsed The arry containing db connection details.
      */
     private static function parseDSN($dsn) {
 
@@ -1140,7 +1199,7 @@ private static function parseDSN($dsn) {
         return $dsn;
       }
 
-      // Find phptype and dbsyntax
+      // Find phptype and dbsyntax.
       if (($pos = strpos($dsn, '://')) !== FALSE) {
         $str = substr($dsn, 0, $pos);
         $dsn = substr($dsn, $pos + 3);
@@ -1150,7 +1209,7 @@ private static function parseDSN($dsn) {
         $dsn = NULL;
       }
 
-      // Get phptype and dbsyntax
+      // Get phptype and dbsyntax.
       // $str => phptype(dbsyntax)
       if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
         $parsed['phptype']  = $arr[1];
@@ -1165,7 +1224,7 @@ private static function parseDSN($dsn) {
         return $parsed;
       }
 
-      // Get (if found): username and password
+      // Get (if found): username and password.
       // $dsn => username:password@protocol+hostspec/database
       if (($at = strrpos($dsn, '@')) !== FALSE) {
         $str = substr($dsn, 0, $at);
@@ -1179,7 +1238,7 @@ private static function parseDSN($dsn) {
         }
       }
 
-      // Find protocol and hostspec
+      // Find protocol and hostspec.
 
       if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
         // $dsn => proto(proto_opts)/database
@@ -1202,7 +1261,7 @@ private static function parseDSN($dsn) {
         }
       }
 
-      // process the different protocol options
+      // Process the different protocol options.
       $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp';
       $proto_opts = rawurldecode($proto_opts);
       if (strpos($proto_opts, ':') !== FALSE) {
@@ -1215,7 +1274,7 @@ private static function parseDSN($dsn) {
         $parsed['socket'] = $proto_opts;
       }
 
-      // Get dabase if any
+      // Get dabase if any.
       // $dsn => database
       if ($dsn) {
         if (($pos = strpos($dsn, '?')) === FALSE) {
@@ -1236,7 +1295,7 @@ private static function parseDSN($dsn) {
           foreach ($opts as $opt) {
             list($key, $value) = explode('=', $opt);
             if (!isset($parsed[$key])) {
-              // don't allow params overwrite
+              // Don't allow params overwrite.
               $parsed[$key] = rawurldecode($value);
             }
           }
@@ -1244,10 +1303,13 @@ private static function parseDSN($dsn) {
       }
 
       return $parsed;
+
     }
 
     /**
-     * Helper function to replicate functionality of drush_get_option
+     * Helper function to replicate functionality of 'drush_get_option'.
+     *
+     * @since 4.5
      *
      * @param string $name
      * @param string $default
@@ -1258,17 +1320,23 @@ private function getOption($name, $default) {
     }
 
     /**
-     * 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
+     * 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 to preserve
+     * file permissions.
+     *
+     * @since 4.5
+     *
+     * @return string The user which owns templates_c. Empty string if not found.
      */
     private function getWebServerUser() {
+
       $plugins_dir = plugin_dir_path(__FILE__);
       $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';
+
       if (is_dir($legacy_tpl_path)) {
         $owner = posix_getpwuid(fileowner($legacy_tpl_path));
         if (isset($owner['name'])) {
@@ -1281,19 +1349,26 @@ private function getWebServerUser() {
           return $owner['name'];
         }
       }
+
       return '';
 
     }
 
     /**
-     * Get the group the webserver runs as - as above, but for group
+     * Get the group the webserver runs as - as above, but for group.
+     *
+     * @since 4.5
+     *
+     * @return string The group the webserver runs as. Empty string if not found.
      */
     private function getWebServerGroup() {
+
       $plugins_dir = plugin_dir_path(__FILE__);
       $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';
+
       if (is_dir($legacy_tpl_path)) {
         $group = posix_getgrgid(filegroup($legacy_tpl_path));
         if (isset($group['name'])) {
@@ -1306,19 +1381,24 @@ private function getWebServerGroup() {
           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
+     * Extracts a tar.gz archive.
+     *
+     * @since 4.5
+     *
+     * @param string $destination_path The path to extract to.
+     * @param string $option The command line option to get input filename from, defaults to 'tarfile'.
+     * @return bool True if successful, false otherwise.
      */
     private function untar($destination_path, $option = 'tarfile') {
 
       if ($tarfile = $this->getOption($option, FALSE)) {
+        WP_CLI::line('Extracting tar.gz archive...');
         WP_CLI::launch("gzip -d $tarfile");
         $tarfile = substr($tarfile, 0, strlen($tarfile) - 3);
         WP_CLI::launch("tar -xf $tarfile -C \"$destination_path\"");
@@ -1331,15 +1411,18 @@ private function untar($destination_path, $option = 'tarfile') {
     }
 
     /**
-     * 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
+     * Extracts a zip archive.
+     *
+     * @since 4.5
+     *
+     * @param string $destination_path The path to extract to.
+     * @param string $option The command line option to get zip filename from, defaults to 'zipfile'.
+     * @return bool True if successful, false otherwise.
      */
     private function unzip($destination_path, $option = 'zipfile') {
 
       if ($zipfile = $this->getOption($option, FALSE)) {
-        WP_CLI::line('Extracting zip archive ...');
+        WP_CLI::line('Extracting zip archive...');
         WP_CLI::launch("unzip -q $zipfile -d $destination_path");
         return TRUE;
       }
@@ -1354,17 +1437,18 @@ private function unzip($destination_path, $option = 'zipfile') {
   WP_CLI::add_command('civicrm', 'CiviCRM_Command');
   WP_CLI::add_command('cv', 'CiviCRM_Command');
 
-  # Set path early.
+  // Set path early.
   WP_CLI::add_hook('before_wp_load', function() {
 
-    # If --path is set, save for later use by CiviCRM.
     global $civicrm_paths;
     $wp_cli_config = WP_CLI::get_config();
+
+    // If --path is set, save for later use by CiviCRM.
     if (!empty($wp_cli_config['path'])) {
       $civicrm_paths['cms.root']['path'] = $wp_cli_config['path'];
     }
 
-    # If --url is set, save for later use by CiviCRM.
+    // 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'];
     }