Skip to content
Snippets Groups Projects
civicrm.php 55.2 KiB
Newer Older
Kevin Cristiano's avatar
Kevin Cristiano committed
<?php
/*
Plugin Name: CiviCRM
Description: CiviCRM - Growing and Sustaining Relationships
Kevin Cristiano's avatar
Kevin Cristiano committed
Version: 5.27.4
Kevin Cristiano's avatar
Kevin Cristiano committed
Requires at least: 4.9
Requires PHP:      7.1
Kevin Cristiano's avatar
Kevin Cristiano committed
Author: CiviCRM LLC
Author URI: https://civicrm.org/
Kevin Cristiano's avatar
Kevin Cristiano committed
Plugin URI: https://docs.civicrm.org/sysadmin/en/latest/install/wordpress/
Kevin Cristiano's avatar
Kevin Cristiano committed
License: AGPL3
Text Domain: civicrm
Domain Path: /languages
*/


/*
 +--------------------------------------------------------------------+
Kevin Cristiano's avatar
Kevin Cristiano committed
 | Copyright CiviCRM LLC. All rights reserved.                        |
Kevin Cristiano's avatar
Kevin Cristiano committed
 |                                                                    |
Kevin Cristiano's avatar
Kevin Cristiano committed
 | This work is published under the GNU AGPLv3 license with some      |
 | permitted exceptions and without any warranty. For full license    |
 | and copyright information, see https://civicrm.org/licensing       |
Kevin Cristiano's avatar
Kevin Cristiano committed
 +--------------------------------------------------------------------+
*/

/**
 *
 * @package CRM
Kevin Cristiano's avatar
Kevin Cristiano committed
 * @copyright CiviCRM LLC https://civicrm.org/licensing
Kevin Cristiano's avatar
Kevin Cristiano committed
 *
 */


/*
--------------------------------------------------------------------------------
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:
http://make.wordpress.org/core/handbook/coding-standards/php/

WordPress HTML standards:
http://make.wordpress.org/core/handbook/coding-standards/html/

WordPress JavaScript standards:
http://make.wordpress.org/core/handbook/coding-standards/javascript/
--------------------------------------------------------------------------------
*/


Kevin Cristiano's avatar
Kevin Cristiano committed
// This file must not accessed directly
Kevin Cristiano's avatar
Kevin Cristiano committed
if ( ! defined( 'ABSPATH' ) ) exit;


Kevin Cristiano's avatar
Kevin Cristiano committed
// Set version here: when it changes, will force JS to reload
Kevin Cristiano's avatar
Kevin Cristiano committed
define( 'CIVICRM_PLUGIN_VERSION', '5.27.4' );
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
// Store reference to this file
Kevin Cristiano's avatar
Kevin Cristiano committed
if (!defined('CIVICRM_PLUGIN_FILE')) {
  define( 'CIVICRM_PLUGIN_FILE', __FILE__ );
}

Kevin Cristiano's avatar
Kevin Cristiano committed
// Store URL to this plugin's directory
Kevin Cristiano's avatar
Kevin Cristiano committed
if (!defined( 'CIVICRM_PLUGIN_URL')) {
  define( 'CIVICRM_PLUGIN_URL', plugin_dir_url(CIVICRM_PLUGIN_FILE) );
}

Kevin Cristiano's avatar
Kevin Cristiano committed
// Store PATH to this plugin's directory
Kevin Cristiano's avatar
Kevin Cristiano committed
if (!defined( 'CIVICRM_PLUGIN_DIR')) {
  define( 'CIVICRM_PLUGIN_DIR', plugin_dir_path(CIVICRM_PLUGIN_FILE) );
}

Kevin Cristiano's avatar
Kevin Cristiano committed
if ( !defined( 'CIVICRM_WP_PHP_MINIMUM' ) ) {
  /**
   * Minimum required PHP
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * 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
Kevin Cristiano's avatar
Kevin Cristiano committed
   * on PHP 5.x.)
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @see CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @see CiviWP\PhpVersionTest::testConstantMatch()
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  define( 'CIVICRM_WP_PHP_MINIMUM', '7.1.0' );
Kevin Cristiano's avatar
Kevin Cristiano committed
/*
Kevin Cristiano's avatar
Kevin Cristiano committed
 * 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.
 */
if ( !defined( 'CIVICRM_SETTINGS_PATH' ) ) {

Kevin Cristiano's avatar
Kevin Cristiano committed
  /*
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Test where the settings file exists.
   *
   * If the settings file is found in the 4.6 and prior location, use that as
   * CIVICRM_SETTINGS_PATH, otherwise use the new location.
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  $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';

Kevin Cristiano's avatar
Kevin Cristiano committed
  if (file_exists($wp_civi_settings_deprectated)) {
    define( 'CIVICRM_SETTINGS_PATH', $wp_civi_settings_deprectated );
  }
  else  {
    define( 'CIVICRM_SETTINGS_PATH', $wp_civi_settings );
  }

Kevin Cristiano's avatar
Kevin Cristiano committed
// Test if CiviCRM is installed
Kevin Cristiano's avatar
Kevin Cristiano committed
if ( file_exists( CIVICRM_SETTINGS_PATH )  ) {
    define( 'CIVICRM_INSTALLED', TRUE );
  } else {
    define( 'CIVICRM_INSTALLED', FALSE );
}

Kevin Cristiano's avatar
Kevin Cristiano committed
// Prevent CiviCRM from rendering its own header
Kevin Cristiano's avatar
Kevin Cristiano committed
define( 'CIVICRM_UF_HEAD', TRUE );

/**
 * Setting this to 'true' will replace all mailing URLs calls to 'extern/url.php'
 * and 'extern/open.php' with their REST counterpart 'civicrm/v3/url' and 'civicrm/v3/open'.
 *
 * Use for test purposes, may affect mailing
 * performance, see Plugin->replace_tracking_urls() method.
 */
if ( ! defined( 'CIVICRM_WP_REST_REPLACE_MAILING_TRACKING' ) ) {
  define( 'CIVICRM_WP_REST_REPLACE_MAILING_TRACKING', false );
}

Kevin Cristiano's avatar
Kevin Cristiano committed

/**
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Define CiviCRM_For_WordPress Class.
 *
 * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
class CiviCRM_For_WordPress {

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Plugin instance.
   *
   * @since 4.4
   * @access private
   * @var object $instance The plugin instance.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  private static $instance;
Kevin Cristiano's avatar
Kevin Cristiano committed

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Plugin context (broad).
   *
   * @since 4.4
   * @access public
   * @var bool $in_wordpress The broad plugin context.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  static $in_wordpress;

Kevin Cristiano's avatar
Kevin Cristiano committed
  /**
   * Plugin context (specific).
   *
   * @since 4.4
   * @access public
   * @var str $context The specific plugin context.
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  static $context;

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Shortcodes management object.
   *
   * @since 4.4
   * @access public
   * @var object CiviCRM_For_WordPress_Shortcodes The shortcodes management object.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public $shortcodes;

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Modal dialog management object.
   *
   * @since 4.4
   * @access public
   * @var object CiviCRM_For_WordPress_Shortcodes_Modal The modal dialog management object.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public $modal;

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Basepage management object.
   *
   * @since 4.4
   * @access public
   * @var object CiviCRM_For_WordPress_Basepage The basepage management object.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public $basepage;

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * User management object.
   *
   * @since 4.4
   * @access public
   * @var object CiviCRM_For_WordPress_Users The user management object.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public $users;

  /**
   * Compatibility object.
   *
   * @since 5.24
   * @access public
   * @var object CiviCRM_For_WordPress_Compat The plugin compatibility object.
   */
  public $compat;

Kevin Cristiano's avatar
Kevin Cristiano committed

  // ---------------------------------------------------------------------------
  // Setup
  // ---------------------------------------------------------------------------


  /**
   * Getter method which returns the CiviCRM instance and optionally creates one
   * if it does not already exist. Standard CiviCRM singleton pattern.
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
   *
   * @return object CiviCRM_For_WordPress The CiviCRM plugin instance.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public static function singleton() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // If instance doesn't already exist
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ( ! isset( self::$instance ) ) {

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Create instance
Kevin Cristiano's avatar
Kevin Cristiano committed
      self::$instance = new CiviCRM_For_WordPress;
Kevin Cristiano's avatar
Kevin Cristiano committed

      // Delay setup until 'plugins_loaded' to allow other plugins to load as well
      add_action( 'plugins_loaded', array( self::$instance, 'setup_instance' ) );
Kevin Cristiano's avatar
Kevin Cristiano committed
    // Return instance
Kevin Cristiano's avatar
Kevin Cristiano committed
    return self::$instance;

  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Dummy instance constructor.
   *
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  function __construct() {}

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Dummy magic method to prevent CiviCRM_For_WordPress from being cloned.
   *
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function __clone() {
    _doing_it_wrong( __FUNCTION__, __( 'Only one instance of CiviCRM_For_WordPress please', 'civicrm' ), '4.4' );
  }

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Dummy magic method to prevent CiviCRM_For_WordPress from being unserialized.
   *
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function __wakeup() {
    _doing_it_wrong( __FUNCTION__, __( 'Please do not serialize CiviCRM_For_WordPress', 'civicrm' ), '4.4' );
  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Plugin activation.
   *
   * This method is called only when CiviCRM plugin is activated. In order for
   * other plugins to be able to interact with Civi's activation, we wait until
   * after the activation redirect to perform activation actions.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function activate() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Set a one-time-only option
Kevin Cristiano's avatar
Kevin Cristiano committed
    add_option( 'civicrm_activation_in_progress', 'true' );

  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Run CiviCRM's plugin activation procedure.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function activation() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Bail if not activating
    if ( get_option( 'civicrm_activation_in_progress' ) !== 'true' ) {
      return;
Kevin Cristiano's avatar
Kevin Cristiano committed
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Bail if not in WordPress admin
    if ( !is_admin() ) {
      return;
    }
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    /**
     * Broadcast that activation actions need to happen now.
     *
     * @since 5.6
     */
    do_action( 'civicrm_activation' );
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Change option so this action never fires again
    update_option( 'civicrm_activation_in_progress', 'false' );
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ( ! is_multisite() && !isset($_GET['activate-multi']) && ! CIVICRM_INSTALLED ) {
      wp_redirect(admin_url("options-general.php?page=civicrm-install"));
      exit;
    }
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Plugin deactivation.
   *
   * This method is called only when CiviCRM plugin is deactivated. In order for
   * other plugins to be able to interact with Civi's activation, we need to
   * remove any options that are set in activate() above.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function deactivate() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Delete any options we hay have set
Kevin Cristiano's avatar
Kevin Cristiano committed
    delete_option( 'civicrm_activation_in_progress' );
Kevin Cristiano's avatar
Kevin Cristiano committed

    /**
     * Broadcast that deactivation actions need to happen now.
     *
     * @since 5.6
     */
    do_action( 'civicrm_deactivation' );
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Set up the CiviCRM plugin instance.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function setup_instance() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Kick out if another instance is being inited
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ( isset( self::$in_wordpress ) ) {
      wp_die( __( 'Only one instance of CiviCRM_For_WordPress please', 'civicrm' ) );
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Get existing session ID
    $session_id = session_id();

Kevin Cristiano's avatar
Kevin Cristiano committed
    /*
     * There is no session handling in WP - hence we start it for CiviCRM pages
     * except when running via WP-CLI which does not require sessions.
     */
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ( empty( $session_id ) && ! ( defined( 'WP_CLI' ) && WP_CLI ) ) {
Kevin Cristiano's avatar
Kevin Cristiano committed
      session_start();
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    /*
     * AJAX calls do not set the 'cms.root' item, so make sure it is set here so
     * the CiviCRM doesn't fall back on flaky directory traversal code.
     */
    global $civicrm_paths;
    if (empty($civicrm_paths['cms.root']['path'])) {
      $civicrm_paths['cms.root']['path'] = untrailingslashit(ABSPATH);
    }
Kevin Cristiano's avatar
Kevin Cristiano committed
    if (empty($civicrm_paths['cms.root']['url'])) {
      $civicrm_paths['cms.root']['url'] = home_url();
    }
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Get classes and instantiate
Kevin Cristiano's avatar
Kevin Cristiano committed
    $this->include_files();

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Do plugin activation
Kevin Cristiano's avatar
Kevin Cristiano committed
    $this->activation();

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Use translation files
    $this->enable_translation();

    // Register all hooks on init
    add_action( 'init', array( $this, 'register_hooks' ) );
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    /**
     * Broadcast that this plugin is now loaded.
     *
     * @since 4.4
     */
Kevin Cristiano's avatar
Kevin Cristiano committed
    do_action( 'civicrm_instance_loaded' );

  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Set broad CiviCRM context.
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * 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
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * It is NOT true when CiviCRM is called via a shortcode.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function civicrm_in_wordpress_set() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Get identifying query var.
    $page = get_query_var( 'civiwp' );
Kevin Cristiano's avatar
Kevin Cristiano committed
    // Store
Kevin Cristiano's avatar
Kevin Cristiano committed
    self::$in_wordpress = ( $page == 'CiviCRM' ) ? TRUE : FALSE;
Kevin Cristiano's avatar
Kevin Cristiano committed

  }


  /**
   * Getter for testing if CiviCRM is currently being displayed in WordPress.
   *
   * @see $this->civicrm_in_wordpress_set()
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
   *
   * @return bool $in_wordpress True if CiviCRM is displayed in WordPress, false otherwise.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function civicrm_in_wordpress() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    /**
     * Allow broad context to be filtered.
     *
     * @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.
     */
Kevin Cristiano's avatar
Kevin Cristiano committed
    return apply_filters( 'civicrm_in_wordpress', self::$in_wordpress );

  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Set specific CiviCRM context.
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * 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
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * The following codes correspond to the different contexts:
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
   * (a) 'admin'
   * (b) 'basepage'
   * (c) 'nonpage'
   * (d) 'shortcode'
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
   *
   * @param string $context One of the four context codes above.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function civicrm_context_set( $context ) {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Store
Kevin Cristiano's avatar
Kevin Cristiano committed
    self::$context = $context;

  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Get specific CiviCRM context.
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Getter for determining how CiviCRM is currently being displayed in WordPress.
   *
   * @see $this->civicrm_context_set()
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
   *
   * @return string The context in which CiviCRM is displayed in WordPress.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function civicrm_context_get() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    /**
     * Allow specific context to be filtered.
     *
     * @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.
     */
Kevin Cristiano's avatar
Kevin Cristiano committed
    return apply_filters( 'civicrm_context', self::$context );

  }


  // ---------------------------------------------------------------------------
  // Files
  // ---------------------------------------------------------------------------


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Include files.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function include_files() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Include users class
Kevin Cristiano's avatar
Kevin Cristiano committed
    include_once CIVICRM_PLUGIN_DIR . 'includes/civicrm.users.php';
    $this->users = new CiviCRM_For_WordPress_Users;

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Include shortcodes class
Kevin Cristiano's avatar
Kevin Cristiano committed
    include_once CIVICRM_PLUGIN_DIR . 'includes/civicrm.shortcodes.php';
    $this->shortcodes = new CiviCRM_For_WordPress_Shortcodes;

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Include shortcodes modal dialog class
Kevin Cristiano's avatar
Kevin Cristiano committed
    include_once CIVICRM_PLUGIN_DIR . 'includes/civicrm.shortcodes.modal.php';
    $this->modal = new CiviCRM_For_WordPress_Shortcodes_Modal;

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Include basepage class
Kevin Cristiano's avatar
Kevin Cristiano committed
    include_once CIVICRM_PLUGIN_DIR . 'includes/civicrm.basepage.php';
    $this->basepage = new CiviCRM_For_WordPress_Basepage;

    // Include compatibility class
    include_once CIVICRM_PLUGIN_DIR . 'includes/civicrm.compat.php';
    $this->compat = new CiviCRM_For_WordPress_Compat;

    if ( ! class_exists( 'CiviCRM_WP_REST\Autoloader' ) ) {
      // Include REST API autoloader class
      require_once( CIVICRM_PLUGIN_DIR . 'wp-rest/Autoloader.php' );
    }
Kevin Cristiano's avatar
Kevin Cristiano committed
  }


  // ---------------------------------------------------------------------------
  // Hooks
  // ---------------------------------------------------------------------------


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Register hooks on init.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function register_hooks() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Always add the common hooks
Kevin Cristiano's avatar
Kevin Cristiano committed
    $this->register_hooks_common();

Kevin Cristiano's avatar
Kevin Cristiano committed
    // When in WordPress admin...
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ( is_admin() ) {

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Set context
Kevin Cristiano's avatar
Kevin Cristiano committed
      $this->civicrm_context_set( 'admin' );

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Handle WP admin context
Kevin Cristiano's avatar
Kevin Cristiano committed
      $this->register_hooks_admin();
      return;

    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Go no further if CiviCRM not installed yet
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ( ! CIVICRM_INSTALLED ) return;

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Attempt to replace 'page' query arg with 'civiwp'.
    add_filter( 'request', array( $this, 'maybe_replace_page_query_var' ) );

    // Add our query vars.
    add_filter( 'query_vars', array( $this, 'query_vars' ) );

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Delay everything else until query has been parsed
    add_action( 'parse_query', array( $this, 'register_hooks_front_end' ) );

  }


  /**
   * Register hooks for the front end.
   *
   * @since 5.6
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
   * @param WP_Query $query The WP_Query instance (passed by reference).
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  public function register_hooks_front_end( $query ) {

    // Bail if $query is not the main loop.
    if ( ! $query->is_main_query() ) {
      return;
    }

    // Bail if filters are suppressed on this query.
    if ( true == $query->get( 'suppress_filters' ) ) {
      return;
    }
Kevin Cristiano's avatar
Kevin Cristiano committed

    // Prevent multiple calls
    static $alreadyRegistered = FALSE;
    if ( $alreadyRegistered ) {
      return;
    }
    $alreadyRegistered = TRUE;

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Redirect if old query var is present.
    if ( 'CiviCRM' == get_query_var( 'page' ) && 'CiviCRM' != get_query_var( 'civiwp' ) ) {
      $redirect_url = remove_query_arg( 'page', false );
      $redirect_url = add_query_arg( 'civiwp', 'CiviCRM', $redirect_url );
      wp_redirect( $redirect_url, 301 );
      exit();
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Store context
    $this->civicrm_in_wordpress_set();

    // When embedded via wpBasePage or AJAX call...
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ( $this->civicrm_in_wordpress() ) {

Kevin Cristiano's avatar
Kevin Cristiano committed
      /*
Kevin Cristiano's avatar
Kevin Cristiano committed
       * Directly output CiviCRM html only in a few cases and skip WP templating:
       *
       * (a) when a snippet is set
       * (b) when there is an AJAX call
       * (c) for an iCal feed (unless 'html' is specified)
       * (d) for file download URLs
       */
      if ( ! $this->is_page_request() ) {

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Set context
Kevin Cristiano's avatar
Kevin Cristiano committed
        $this->civicrm_context_set( 'nonpage' );

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Add core resources for front end
Kevin Cristiano's avatar
Kevin Cristiano committed
        add_action( 'wp', array( $this, 'front_end_page_load' ) );

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Echo all output when WP has been set up but nothing has been rendered
Kevin Cristiano's avatar
Kevin Cristiano committed
        add_action( 'wp', array( $this, 'invoke' ) );
        return;

      }

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Set context
Kevin Cristiano's avatar
Kevin Cristiano committed
      $this->civicrm_context_set( 'basepage' );

Kevin Cristiano's avatar
Kevin Cristiano committed
      // If we get here, we must be in a wpBasePage context
Kevin Cristiano's avatar
Kevin Cristiano committed
      $this->basepage->register_hooks();
      return;

    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Set context
Kevin Cristiano's avatar
Kevin Cristiano committed
    $this->civicrm_context_set( 'shortcode' );

Kevin Cristiano's avatar
Kevin Cristiano committed
    // That leaves us with handling shortcodes, should they exist
Kevin Cristiano's avatar
Kevin Cristiano committed
    $this->shortcodes->register_hooks();

  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Register hooks that must always be present.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function register_hooks_common() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Register user hooks.
Kevin Cristiano's avatar
Kevin Cristiano committed
    $this->users->register_hooks();

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Register hooks for clean URLs.
    $this->register_hooks_clean_urls();

    if ( ! class_exists( 'CiviCRM_WP_REST\Plugin' ) ) {

      // Set up REST API.
      CiviCRM_WP_REST\Autoloader::add_source( $source_path = trailingslashit( CIVICRM_PLUGIN_DIR . 'wp-rest' ) );
      // Init REST API.
      new CiviCRM_WP_REST\Plugin;

    }
Kevin Cristiano's avatar
Kevin Cristiano committed
  }


  /**
   * Register hooks to handle Clean URLs.
   *
   * @since 5.12
   */
  public function register_hooks_clean_urls() {

    // Bail if CiviCRM is not installed.
    if (!CIVICRM_INSTALLED) {
      return;
    }

    // Bail if we can't initialize CiviCRM.
    if (!$this->initialize()) {
      return;
    }

    // Bail if CiviCRM is not using clean URLs.
    if (!defined('CIVICRM_CLEANURL') || CIVICRM_CLEANURL !== 1) {
      return;
    }

    // Have we flushed rewrite rules?
    if ( get_option( 'civicrm_rules_flushed' ) !== 'true' ) {

      // Apply custom rewrite rules, then flush rules afterwards.
      $this->rewrite_rules( true );

      // Set a one-time-only option to flag that this has been done.
      add_option( 'civicrm_rules_flushed', 'true' );

    } else {

      // Apply custom rewrite rules normally.
      $this->rewrite_rules();

    }

Kevin Cristiano's avatar
Kevin Cristiano committed
   * Register hooks to handle CiviCRM in a WordPress admin context.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function register_hooks_admin() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Modify the admin menu
Kevin Cristiano's avatar
Kevin Cristiano committed
    add_action( 'admin_menu', array( $this, 'add_menu_items' ) );

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Set page title
Kevin Cristiano's avatar
Kevin Cristiano committed
    add_filter( 'admin_title', array( $this, 'set_admin_title' ) );

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Print CiviCRM's header
Kevin Cristiano's avatar
Kevin Cristiano committed
    add_action('admin_head', array( $this, 'wp_head' ), 50);

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Listen for changes to the basepage setting
    add_action( 'civicrm_postSave_civicrm_setting', array( $this, 'settings_change' ), 10 );

Kevin Cristiano's avatar
Kevin Cristiano committed
    // If settings file does not exist, show notice with link to installer
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ( ! CIVICRM_INSTALLED ) {
      if ( isset( $_GET['page'] ) && $_GET['page'] == 'civicrm-install' ) {
Kevin Cristiano's avatar
Kevin Cristiano committed
        // Set install type
        $_GET['civicrm_install_type'] = 'wordpress';
Kevin Cristiano's avatar
Kevin Cristiano committed
      } else {
Kevin Cristiano's avatar
Kevin Cristiano committed
        // Show notice
Kevin Cristiano's avatar
Kevin Cristiano committed
        add_action( 'admin_notices', array( $this, 'show_setup_warning' ) );
      }
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Enable shortcode modal
Kevin Cristiano's avatar
Kevin Cristiano committed
    $this->modal->register_hooks();

  }


Kevin Cristiano's avatar
Kevin Cristiano committed
  /**
   * Force rewrite rules to be recreated.
   *
   * When CiviCRM settings are saved, the method is called post-save. It checks
   * if it's the WordPress Base Page setting that has been saved and causes all
   * rewrite rules to be flushed on the next page load.
   *
   * @since 5.14
   *
   * @param obj $dao The CiviCRM database access object.
   */
  public function settings_change( $dao ) {

    // Delete the option if conditions are met
    if ( $dao instanceOf CRM_Core_DAO_Setting ) {
      if ( isset( $dao->name ) && $dao->name == 'wpBasePage' ) {
        delete_option( 'civicrm_rules_flushed' );
      }
    }

  }


Kevin Cristiano's avatar
Kevin Cristiano committed
  /**
   * Add our rewrite rules.
   *
   * @since 5.7
   *
   * @param bool $flush_rewrite_rules True if rules should be flushed, false otherwise.
   */
  public function rewrite_rules( $flush_rewrite_rules = false ) {

    // Kick out if not CiviCRM
    if (!$this->initialize()) {
      return;
    }

    // Get config
    $config = CRM_Core_Config::singleton();

    // Get basepage object
    $basepage = get_page_by_path( $config->wpBasePage );

    // Sanity check
    if (!is_object($basepage)) {
        return;
    }

    // Let's add rewrite rule when viewing the basepage
    add_rewrite_rule(
      '^' . $config->wpBasePage . '/([^?]*)?',
Kevin Cristiano's avatar
Kevin Cristiano committed
      'index.php?page_id=' . $basepage->ID . '&civiwp=CiviCRM&q=civicrm%2F$matches[1]',
Kevin Cristiano's avatar
Kevin Cristiano committed
      'top'
    );

    // Maybe force flush
    if ($flush_rewrite_rules) {
      flush_rewrite_rules();
    }

    /**
     * Broadcast the rewrite rules event.
     *
     * @since 5.7
     * @since 5.24 Added $basepage parameter.
Kevin Cristiano's avatar
Kevin Cristiano committed
     *
     * @param bool $flush_rewrite_rules True if rules flushed, false otherwise.
     * @param WP_Post $basepage The Basepage post object.
    do_action( 'civicrm_after_rewrite_rules', $flush_rewrite_rules, $basepage );
Kevin Cristiano's avatar
Kevin Cristiano committed

  }


  /**
   * Add our query vars.
   *
   * @since 5.7
   *
   * @param array $query_vars The existing query vars.
   * @return array $query_vars The modified query vars.
   */
  public function query_vars( $query_vars ) {

    // Sanity check
    if (!is_array($query_vars)) {
      $query_vars = array();
    }

    // Build our query vars
    $civicrm_query_vars = array(
Kevin Cristiano's avatar
Kevin Cristiano committed
      'civiwp', 'q', 'reset', 'id', 'html', 'snippet', // URL query vars
Kevin Cristiano's avatar
Kevin Cristiano committed
      'action', 'mode', 'cid', 'gid', 'sid', 'cs', 'force', // Shortcode query vars
    );

    /**
     * Filter the default CiviCRM query vars.
     *
     * Use in combination with `civicrm_query_vars_assigned` action to ensure
     * that any other query vars are included in the assignment to the
     * super-global arrays.
     *
     * @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 );

    // Now add them to WordPress
    foreach( $civicrm_query_vars as $civicrm_query_var ) {
      $query_vars[] = $civicrm_query_var;
    }

    return $query_vars;

  }


Kevin Cristiano's avatar
Kevin Cristiano committed
  /**
   * Filters the request right after WP's
   * parsed it and replaces the 'page' query
   * variable with 'civiwp' if applicable.
   *
   * Prevents old URLs like example.org/civicrm/?page=CiviCRM&q=what/ever/path&reset=1
   * being redirected to example.org/civicrm/?civiwp=CiviCRM&q=what/ever/path&reset=1
   *
   * @see https://lab.civicrm.org/dev/wordpress/-/issues/49
   *
   * @since 5.26
   *
   * @param array $query_vars The existing query vars.
   * @return array $query_vars The modified query vars.
   */
  public function maybe_replace_page_query_var( $query_vars ) {

    $civi_query_arg = array_search( 'CiviCRM', $query_vars );

    // Bail if the query var is not 'page'.
    if ( false === $civi_query_arg || $civi_query_arg !== 'page' ) return $query_vars;

    unset( $query_vars['page'] );
    $query_vars['civiwp'] = 'CiviCRM';

    return $query_vars;

  }


Kevin Cristiano's avatar
Kevin Cristiano committed
  // ---------------------------------------------------------------------------
  // CiviCRM Initialisation
  // ---------------------------------------------------------------------------

Kevin Cristiano's avatar
Kevin Cristiano committed
  /**
   * Check that the PHP version is supported. If not, raise a fatal error with a pointed message.
   *
   * One should check this before bootstrapping Civi - after we start the class-loader, the
   * PHP-compatibility errors will become more ugly.
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  protected function assertPhpSupport() {
    if ( version_compare( PHP_VERSION, CIVICRM_WP_PHP_MINIMUM ) < 0 ) {
      echo '<p>' .
         sprintf(
Kevin Cristiano's avatar
Kevin Cristiano committed
          __( 'CiviCRM requires PHP version %1$s or greater. You are running PHP version %2$s', 'civicrm' ),
Kevin Cristiano's avatar
Kevin Cristiano committed
          CIVICRM_WP_PHP_MINIMUM,
          PHP_VERSION
         ) .
         '<p>';
      exit();
    }
  }
Kevin Cristiano's avatar
Kevin Cristiano committed

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Initialize CiviCRM.
   *
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @return bool $success True if CiviCRM is initialized, false otherwise.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function initialize() {

    static $initialized = FALSE;
    static $failure = FALSE;

    if ( $failure ) {
      return FALSE;
    }

    if ( ! $initialized ) {

Kevin Cristiano's avatar
Kevin Cristiano committed
      $this->assertPhpSupport();
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Check for settings
Kevin Cristiano's avatar
Kevin Cristiano committed
      if ( ! CIVICRM_INSTALLED ) {
        $error = FALSE;
      } elseif ( file_exists( CIVICRM_SETTINGS_PATH) ) {
        $error = include_once ( CIVICRM_SETTINGS_PATH );
      }

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Autoload
Kevin Cristiano's avatar
Kevin Cristiano committed
      require_once 'CRM/Core/ClassLoader.php';
      CRM_Core_ClassLoader::singleton()->register();

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Get ready for problems
Kevin Cristiano's avatar
Kevin Cristiano committed
      $installLink    = admin_url() . "options-general.php?page=civicrm-install";
      $docLinkInstall = "https://wiki.civicrm.org/confluence/display/CRMDOC/Installing+CiviCRM+for+WordPress";
      $docLinkTrouble = "https://wiki.civicrm.org/confluence/display/CRMDOC/Installation+and+Upgrades";
      $forumLink      = "https://civicrm.stackexchange.com/";
Kevin Cristiano's avatar
Kevin Cristiano committed
      // Construct message
Kevin Cristiano's avatar
Kevin Cristiano committed
      $errorMsgAdd = sprintf(
        __( 'Please review the <a href="%s">WordPress Installation Guide</a> and the <a href="%s">Trouble-shooting page</a> for assistance. If you still need help installing, you can often find solutions to your issue by searching for the error message in the <a href="%s">installation support section of the community forum</a>.', 'civicrm' ),
        $docLinkInstall,
        $docLinkTrouble,
        $forumLink
      );

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Does install message get used?
Kevin Cristiano's avatar
Kevin Cristiano committed
      $installMessage = sprintf(
        __( 'Click <a href="%s">here</a> for fresh install.', 'civicrm' ),
        $installLink
      );

      if ($error == FALSE) {
        header( 'Location: ' . admin_url() . 'options-general.php?page=civicrm-install' );
        return FALSE;
      }

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Access global defined in civicrm.settings.php
Kevin Cristiano's avatar
Kevin Cristiano committed
      global $civicrm_root;

Kevin Cristiano's avatar
Kevin Cristiano committed
      // This does pretty much all of the civicrm initialization
Kevin Cristiano's avatar
Kevin Cristiano committed
      if ( ! file_exists( $civicrm_root . 'CRM/Core/Config.php' ) ) {
        $error = FALSE;
      } else {
        $error = include_once ( 'CRM/Core/Config.php' );
      }

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Have we got it?
Kevin Cristiano's avatar
Kevin Cristiano committed
      if ( $error == FALSE ) {

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Set static flag
Kevin Cristiano's avatar
Kevin Cristiano committed
        $failure = TRUE;

        // FIX ME - why?
        wp_die(
          "<strong><p class='error'>" .
          sprintf(
            __( 'Oops! - The path for including CiviCRM code files is not set properly. Most likely there is an error in the <em>civicrm_root</em> setting in your CiviCRM settings file (%s).', 'civicrm' ),
            CIVICRM_SETTINGS_PATH
          ) .
          "</p><p class='error'> &raquo; " .
          sprintf(
            __( 'civicrm_root is currently set to: <em>%s</em>.', 'civicrm' ),
            $civicrm_root
          ) .
          "</p><p class='error'>" . $errorMsgAdd . "</p></strong>"
        );

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Won't reach here!
Kevin Cristiano's avatar
Kevin Cristiano committed
        return FALSE;

      }

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Set static flag
Kevin Cristiano's avatar
Kevin Cristiano committed
      $initialized = TRUE;

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Initialize the system by creating a config object
Kevin Cristiano's avatar
Kevin Cristiano committed
      $config = CRM_Core_Config::singleton();

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Sync the logged in user with WP
Kevin Cristiano's avatar
Kevin Cristiano committed
      global $current_user;
      if ( $current_user ) {

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Sync procedure sets session values for logged in users
Kevin Cristiano's avatar
Kevin Cristiano committed
        require_once 'CRM/Core/BAO/UFMatch.php';
        CRM_Core_BAO_UFMatch::synchronize(
Kevin Cristiano's avatar
Kevin Cristiano committed
          $current_user, // User object
          FALSE, // Do not update
Kevin Cristiano's avatar
Kevin Cristiano committed
          'WordPress', // CMS
          $this->users->get_civicrm_contact_type('Individual')
        );

      }

    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    /**
     * Broadcast that CiviCRM is now initialized.
     *
     * @since 4.4
     */
Kevin Cristiano's avatar
Kevin Cristiano committed
    do_action( 'civicrm_initialized' );

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Success!
Kevin Cristiano's avatar
Kevin Cristiano committed
    return TRUE;

  }


  // ---------------------------------------------------------------------------
  // Plugin setup
  // ---------------------------------------------------------------------------


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Load translation files.
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * A good reference on how to implement translation in WordPress:
   * http://ottopress.com/2012/internationalization-youre-probably-doing-it-wrong/
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function enable_translation() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Load translations
Kevin Cristiano's avatar
Kevin Cristiano committed
    load_plugin_textdomain(
Kevin Cristiano's avatar
Kevin Cristiano committed
      'civicrm', // Unique name
      FALSE, // Deprecated argument
      dirname( plugin_basename( __FILE__ ) ) . '/languages/' // Relative path to translation files
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Adds menu items to WordPress admin menu.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Callback method for 'admin_menu' hook as set in register_hooks().
   *
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function add_menu_items() {

    $civilogo = file_get_contents( plugin_dir_path( __FILE__ ) . 'assets/civilogo.svg.b64' );

Kevin Cristiano's avatar
Kevin Cristiano committed
    /**
     * Filter the position of the CiviCRM menu item.
     *
     * Currently set to 3.9 + some random digits to reduce risk of conflict.
     *
     * @since 4.4
     *
     * @param float The default menu position.
     * @return float The modified menu position..
     */
    $position = apply_filters( 'civicrm_menu_item_position', '3.904981' );

    // Check for settings file
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ( CIVICRM_INSTALLED ) {

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Add top level menu item
Kevin Cristiano's avatar
Kevin Cristiano committed
      $menu_page = add_menu_page(
        __( 'CiviCRM', 'civicrm' ),
        __( 'CiviCRM', 'civicrm' ),
        'access_civicrm',
        'CiviCRM',
        array( $this, 'invoke' ),
        $civilogo,
Kevin Cristiano's avatar
Kevin Cristiano committed
        $position
Kevin Cristiano's avatar
Kevin Cristiano committed
      );

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Add core resources prior to page load
Kevin Cristiano's avatar
Kevin Cristiano committed
      add_action( 'load-' . $menu_page, array( $this, 'admin_page_load' ) );

    } else {

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Add top level menu item
Kevin Cristiano's avatar
Kevin Cristiano committed
      $menu_page = add_menu_page(
        __( 'CiviCRM Installer', 'civicrm' ),
        __( 'CiviCRM Installer', 'civicrm' ),
        'manage_options',
        'civicrm-install',
        array( $this, 'run_installer' ),
        $civilogo,
Kevin Cristiano's avatar
Kevin Cristiano committed
        $position
Kevin Cristiano's avatar
Kevin Cristiano committed
      // Add scripts and styles like this
      add_action( 'admin_print_scripts-' . $menu_page, array( $this, 'admin_installer_js' ) );
      add_action( 'admin_print_styles-' . $menu_page, array( $this, 'admin_installer_css' ) );
      add_action( 'admin_head-' . $menu_page, array( $this, 'admin_installer_head' ), 50 );
Kevin Cristiano's avatar
Kevin Cristiano committed
      */

    }

  }


  // ---------------------------------------------------------------------------
  // Installation
  // ---------------------------------------------------------------------------


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Callback method for add_options_page() that runs the CiviCRM installer.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function run_installer() {
Kevin Cristiano's avatar
Kevin Cristiano committed
    $this->assertPhpSupport();
    $civicrmCore = CIVICRM_PLUGIN_DIR . 'civicrm';

    $setupPaths = array(
      implode(DIRECTORY_SEPARATOR, ['vendor', 'civicrm', 'civicrm-setup']),
      implode(DIRECTORY_SEPARATOR, ['packages', 'civicrm-setup',]),
      implode(DIRECTORY_SEPARATOR, ['setup']),
    );
    foreach ($setupPaths as $setupPath) {
      $loader = implode(DIRECTORY_SEPARATOR, [$civicrmCore, $setupPath, 'civicrm-setup-autoload.php']);
      if (file_exists($civicrmCore . DIRECTORY_SEPARATOR . '.use-civicrm-setup') && file_exists($loader)) {
        require_once $loader;
        require_once implode(DIRECTORY_SEPARATOR, [$civicrmCore, 'CRM', 'Core', 'ClassLoader.php']);
        CRM_Core_ClassLoader::singleton()->register();
        \Civi\Setup::assertProtocolCompatibility(1.0);
        \Civi\Setup::init([
          'cms' => 'WordPress',
          'srcPath' => $civicrmCore,
        ]);
        $ctrl = \Civi\Setup::instance()->createController()->getCtrl();
        $ctrl->setUrls(array(
          'ctrl' => admin_url() . "options-general.php?page=civicrm-install",
          'res' => CIVICRM_PLUGIN_URL . 'civicrm/' . strtr($setupPath, DIRECTORY_SEPARATOR, '/') . '/res/',
          'jquery.js' => CIVICRM_PLUGIN_URL . 'civicrm/bower_components/jquery/dist/jquery.min.js',
          'font-awesome.css' => CIVICRM_PLUGIN_URL . 'civicrm/bower_components/font-awesome/css/font-awesome.min.css',
          'finished' => admin_url('admin.php?page=CiviCRM&q=civicrm&reset=1'),
        ));
        \Civi\Setup\BasicRunner::run($ctrl);
        return;
      }
    }
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Uses CIVICRM_PLUGIN_DIR instead of WP_PLUGIN_DIR
Kevin Cristiano's avatar
Kevin Cristiano committed
    $installFile =
      CIVICRM_PLUGIN_DIR .
      'civicrm' . DIRECTORY_SEPARATOR .
      'install' . DIRECTORY_SEPARATOR .
      'index.php';

    // Notice: Undefined variable: siteDir in:
    // CIVICRM_PLUGIN_DIR/civicrm/install/index.php on line 456
    include ( $installFile );

  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Callback method for missing settings file in register_hooks().
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function show_setup_warning() {

    $installLink = admin_url() . "options-general.php?page=civicrm-install";
    echo '<div id="civicrm-warning" class="updated fade">' .
       '<p><strong>' .
       __( 'CiviCRM is almost ready.', 'civicrm' ) .
       '</strong> ' .
       sprintf(
        __( 'You must <a href="%s">configure CiviCRM</a> for it to work.', 'civicrm' ),
        $installLink
       ) .
       '</p></div>';

  }


  // ---------------------------------------------------------------------------
  // HTML head
  // ---------------------------------------------------------------------------


  /**
   * Perform necessary stuff prior to CiviCRM's admin page being loaded
   * This needs to be a method because it can then be hooked into WP at the
Kevin Cristiano's avatar
Kevin Cristiano committed
   * right time.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.6
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function admin_page_load() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // This is required for AJAX calls in WordPress admin
Kevin Cristiano's avatar
Kevin Cristiano committed
    $_REQUEST['noheader'] = $_GET['noheader'] = TRUE;
Kevin Cristiano's avatar
Kevin Cristiano committed

    // Add resources for back end
Kevin Cristiano's avatar
Kevin Cristiano committed
    $this->add_core_resources( FALSE );

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Check setting for path to wp-load.php
Kevin Cristiano's avatar
Kevin Cristiano committed
    $this->add_wpload_setting();

  }


  /**
   * When CiviCRM is loaded in WP Admin, check for the existence of a setting
   * which holds the path to wp-load.php. This is the only reliable way to
   * bootstrap WordPress from CiviCRM.
   *
   * CMW: I'm not entirely happy with this approach, because the value will be
   * different for different installs (e.g. when a dev site is migrated to live)
   * A better approach would be to store this setting in civicrm.settings.php as
   * a constant, but doing that involves a complicated process of getting a new
   * setting registered in the installer.
   *
   * Also, it needs to be decided whether this value should be tied to a CiviCRM
   * 'domain', since a single CiviCRM install could potentially be used by a
   * number of WordPress installs. This is not relevant to its use in WordPress
   * 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');
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.6.3
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function add_wpload_setting() {

    if (!$this->initialize()) {
      return;
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Get path to wp-load.php
Kevin Cristiano's avatar
Kevin Cristiano committed
    $path = ABSPATH . 'wp-load.php';

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Get the setting, if it exists
Kevin Cristiano's avatar
Kevin Cristiano committed
    $setting = CRM_Core_BAO_Setting::getItem('CiviCRM Preferences', 'wpLoadPhp');

Kevin Cristiano's avatar
Kevin Cristiano committed
    // If we don't have one, create it
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ( is_null( $setting ) ) {
      CRM_Core_BAO_Setting::setItem($path, 'CiviCRM Preferences', 'wpLoadPhp');
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Is it different to the one we've stored?
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ( $setting !== $path ) {
Kevin Cristiano's avatar
Kevin Cristiano committed
      // Yes - set new path (this could be because we've changed server or location)
Kevin Cristiano's avatar
Kevin Cristiano committed
      CRM_Core_BAO_Setting::setItem($path, 'CiviCRM Preferences', 'wpLoadPhp');
    }

  }


  /**
   * Perform necessary stuff prior to CiviCRM being loaded on the front end
   * This needs to be a method because it can then be hooked into WP at the
Kevin Cristiano's avatar
Kevin Cristiano committed
   * right time.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.6
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function front_end_page_load() {

    static $frontend_loaded = FALSE;
    if ( $frontend_loaded ) {
      return;
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Add resources for front end
Kevin Cristiano's avatar
Kevin Cristiano committed
    $this->add_core_resources( TRUE );

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Merge CiviCRM's HTML header with the WordPress theme's header
Kevin Cristiano's avatar
Kevin Cristiano committed
    add_action( 'wp_head', array( $this, 'wp_head' ) );

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Set flag so this only happens once
Kevin Cristiano's avatar
Kevin Cristiano committed
    $frontend_loaded = TRUE;

  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Load only the CiviCRM CSS.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * This is needed because $this->front_end_page_load() is only called when
   * there is a single CiviCRM entity present on a page or archive and, whilst
   * we don't want all the Javascript to load, we do want stylesheets.
   *
   * @since 4.6
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function front_end_css_load() {

    static $frontend_css_loaded = FALSE;
    if ( $frontend_css_loaded ) {
      return;
    }

    if (!$this->initialize()) {
      return;
    }

    $config = CRM_Core_Config::singleton();

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Default custom CSS to standalone
Kevin Cristiano's avatar
Kevin Cristiano committed
    $dependent = NULL;

    // Load core CSS
    if (!CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'disable_core_css')) {

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Enqueue stylesheet
Kevin Cristiano's avatar
Kevin Cristiano committed
      wp_enqueue_style(
        'civicrm_css',
        $config->resourceBase . 'css/civicrm.css',
Kevin Cristiano's avatar
Kevin Cristiano committed
        NULL, // Dependencies
        CIVICRM_PLUGIN_VERSION, // Version
        'all' // Media
Kevin Cristiano's avatar
Kevin Cristiano committed
      );

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Custom CSS is dependent
Kevin Cristiano's avatar
Kevin Cristiano committed
      $dependent = array( 'civicrm_css' );

    }

    // Load custom CSS
    if (!empty($config->customCSSURL)) {
      wp_enqueue_style(
        'civicrm_custom_css',
        $config->customCSSURL,
Kevin Cristiano's avatar
Kevin Cristiano committed
        $dependent, // Dependencies
        CIVICRM_PLUGIN_VERSION, // Version
        'all' // Media
Kevin Cristiano's avatar
Kevin Cristiano committed
    // Set flag so this only happens once
Kevin Cristiano's avatar
Kevin Cristiano committed
    $frontend_css_loaded = TRUE;

  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Add CiviCRM core resources.
   *
   * @since 4.6
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @param bool $front_end True if on WP front end, false otherwise.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function add_core_resources( $front_end = TRUE ) {

    if (!$this->initialize()) {
      return;
    }

    $config = CRM_Core_Config::singleton();
    $config->userFrameworkFrontend = $front_end;

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Add CiviCRM core resources
Kevin Cristiano's avatar
Kevin Cristiano committed
    CRM_Core_Resources::singleton()->addCoreResources();

  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Merge CiviCRM's HTML header with the WordPress theme's header.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Callback from WordPress 'admin_head' and 'wp_head' hooks.
   *
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function wp_head() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // CRM-11823 - If CiviCRM bootstrapped, then merge its HTML header with the CMS's header
Kevin Cristiano's avatar
Kevin Cristiano committed
    global $civicrm_root;
    if ( empty( $civicrm_root ) ) {
      return;
    }

    $region = CRM_Core_Region::instance('html-header', FALSE);
    if ( $region ) {
      echo '<!-- CiviCRM html header -->';
      echo $region->render( '' );
    }

  }


  // ---------------------------------------------------------------------------
  // CiviCRM Invocation (this outputs Civi's markup)
  // ---------------------------------------------------------------------------


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Invoke CiviCRM in a WordPress context.
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Callback function from add_menu_page()
   * Callback from WordPress 'init' and 'the_content' hooks
   * Also called by shortcode_render() and _civicrm_update_user()
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function invoke() {

    static $alreadyInvoked = FALSE;
    if ( $alreadyInvoked ) {
      return;
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Bail if this is called via a content-preprocessing plugin
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ( $this->is_page_request() && !in_the_loop() && !is_admin() ) {
      return;
    }

    if (!$this->initialize()) {
      return;
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    /*
     * CRM-12523
     * WordPress has it's own timezone calculations
     * CiviCRM relies on the php default timezone which WP
     * overrides with UTC in wp-settings.php
     */
Kevin Cristiano's avatar
Kevin Cristiano committed
    $wpBaseTimezone = date_default_timezone_get();
    $wpUserTimezone = get_option('timezone_string');
    if ($wpUserTimezone) {
      date_default_timezone_set($wpUserTimezone);
      CRM_Core_Config::singleton()->userSystem->setMySQLTimeZone();
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    /*
     * CRM-95XX
     * At this point we are calling a CiviCRM function
     * WP always quotes the request, CiviCRM needs to reverse what it just did.
     */
Kevin Cristiano's avatar
Kevin Cristiano committed
    $this->remove_wp_magic_quotes();

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Required for AJAX calls
    if ($this->civicrm_in_wordpress()) {
      $_REQUEST['noheader'] = $_GET['noheader'] = TRUE;
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Code inside invoke() requires the current user to be set up
    $current_user = wp_get_current_user();

Kevin Cristiano's avatar
Kevin Cristiano committed
     * Bypass synchronize if running upgrade to avoid any serious non-recoverable
     * error which might hinder the upgrade process.
     */
    if ( CRM_Utils_Array::value('q', $_GET) != 'civicrm/upgrade' ) {
      $this->users->sync_user( $current_user );
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Set flag
Kevin Cristiano's avatar
Kevin Cristiano committed
    $alreadyInvoked = TRUE;

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Get args
Kevin Cristiano's avatar
Kevin Cristiano committed
    $argdata = $this->get_request_args();

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Set dashboard as default if args are empty
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ( empty( $argdata['argString'] ) ) {
      $_GET['q'] = 'civicrm/dashboard';
      $_GET['reset'] = 1;
Kevin Cristiano's avatar
Kevin Cristiano committed
      $argdata['args'] = array('civicrm', 'dashboard');
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Do the business
Kevin Cristiano's avatar
Kevin Cristiano committed
    CRM_Core_Invoke::invoke($argdata['args']);

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Restore WP's timezone
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ($wpBaseTimezone) {
      date_default_timezone_set($wpBaseTimezone);
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Restore WP's arrays
Kevin Cristiano's avatar
Kevin Cristiano committed
    $this->restore_wp_magic_quotes();

Kevin Cristiano's avatar
Kevin Cristiano committed
    /**
     * Broadcast that CiviCRM has been invoked.
     *
     * @since 4.4
     */
Kevin Cristiano's avatar
Kevin Cristiano committed
    do_action( 'civicrm_invoked' );

  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Non-destructively override WordPress magic quotes.
   *
   * Only called by invoke() to undo WordPress default behaviour.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 5.7 Rewritten to work with query vars.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  private function remove_wp_magic_quotes() {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Save original arrays
Kevin Cristiano's avatar
Kevin Cristiano committed
    $this->wp_get     = $_GET;
    $this->wp_post    = $_POST;
    $this->wp_cookie  = $_COOKIE;
    $this->wp_request = $_REQUEST;

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Reassign globals
Kevin Cristiano's avatar
Kevin Cristiano committed
    $_GET     = stripslashes_deep( $_GET );
    $_POST    = stripslashes_deep( $_POST );
    $_COOKIE  = stripslashes_deep( $_COOKIE );
    $_REQUEST = stripslashes_deep( $_REQUEST );

    // Test for query var
    $q = get_query_var( 'q' );
    if (!empty($q)) {

Kevin Cristiano's avatar
Kevin Cristiano committed
      $page = get_query_var( 'civiwp' );
Kevin Cristiano's avatar
Kevin Cristiano committed
      $reset = get_query_var( 'reset' );
      $id = get_query_var( 'id' );
      $html = get_query_var( 'html' );
      $snippet = get_query_var( 'snippet' );

      $action = get_query_var( 'action' );
      $mode = get_query_var( 'mode' );
      $cid = get_query_var( 'cid' );
      $gid = get_query_var( 'gid' );
      $sid = get_query_var( 'sid' );
      $cs = get_query_var( 'cs' );
      $force = get_query_var( 'force' );

      $_REQUEST['q'] = $_GET['q'] = $q;
Kevin Cristiano's avatar
Kevin Cristiano committed
      $_REQUEST['civiwp'] = $_GET['civiwp'] = 'CiviCRM';
Kevin Cristiano's avatar
Kevin Cristiano committed
      if (!empty($reset)) { $_REQUEST['reset'] = $_GET['reset'] = $reset; }
      if (!empty($id)) { $_REQUEST['id'] = $_GET['id'] = $id; }
      if (!empty($html)) { $_REQUEST['html'] = $_GET['html'] = $html; }
      if (!empty($snippet)) { $_REQUEST['snippet'] = $_GET['snippet'] = $snippet; }

      if (!empty($action)) { $_REQUEST['action'] = $_GET['action'] = $action; }
      if (!empty($mode)) { $_REQUEST['mode'] = $_GET['mode'] = $mode; }
      if (!empty($cid)) { $_REQUEST['cid'] = $_GET['cid'] = $cid; }
      if (!empty($gid)) { $_REQUEST['gid'] = $_GET['gid'] = $gid; }
      if (!empty($sid)) { $_REQUEST['sid'] = $_GET['sid'] = $sid; }
      if (!empty($cs)) { $_REQUEST['cs'] = $_GET['cs'] = $cs; }
      if (!empty($force)) { $_REQUEST['force'] = $_GET['force'] = $force; }

      /**
       * Broadcast that CiviCRM query vars have been assigned.
       *
       * Use in combination with `civicrm_query_vars` filter to ensure that any
       * other query vars are included in the assignment to the super-global
       * arrays.
       *
       * @since 5.7
       */
      do_action( 'civicrm_query_vars_assigned' );

    }
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Restore WordPress magic quotes.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Only called by invoke() to redo WordPress default behaviour.
   *
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  private function restore_wp_magic_quotes() {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Restore original arrays
Kevin Cristiano's avatar
Kevin Cristiano committed
    $_GET     = $this->wp_get;
    $_POST    = $this->wp_post;
    $_COOKIE  = $this->wp_cookie;
    $_REQUEST = $this->wp_request;

  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Detect Ajax, snippet, or file requests.
   *
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @return boolean True if request is for a CiviCRM page, false otherwise.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function is_page_request() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Assume not a CiviCRM page
    $return = FALSE;

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Kick out if not CiviCRM
Kevin Cristiano's avatar
Kevin Cristiano committed
    if (!$this->initialize()) {
Kevin Cristiano's avatar
Kevin Cristiano committed
      return $return;
Kevin Cristiano's avatar
Kevin Cristiano committed
    // Get args
Kevin Cristiano's avatar
Kevin Cristiano committed
    $argdata = $this->get_request_args();

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Grab query var
    $html = get_query_var( 'html' );
    if (empty($html)) {
      $html = isset($_GET['html']) ? $_GET['html'] : '';
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    /*
     * FIXME: It's not sustainable to hardcode a whitelist of all of non-HTML
     * pages. Maybe the menu-XML should include some metadata to make this
     * unnecessary?
     */
Kevin Cristiano's avatar
Kevin Cristiano committed
    if (CRM_Utils_Array::value('HTTP_X_REQUESTED_WITH', $_SERVER) == 'XMLHttpRequest'
        || ($argdata['args'][0] == 'civicrm' && in_array($argdata['args'][1], array('ajax', 'file')) )
        || !empty($_REQUEST['snippet'])
Kevin Cristiano's avatar
Kevin Cristiano committed
        || strpos($argdata['argString'], 'civicrm/event/ical') === 0 && empty($html)
Kevin Cristiano's avatar
Kevin Cristiano committed
        || strpos($argdata['argString'], 'civicrm/contact/imagefile') === 0
    ) {
Kevin Cristiano's avatar
Kevin Cristiano committed
      $return = FALSE;
Kevin Cristiano's avatar
Kevin Cristiano committed
    }
    else {
Kevin Cristiano's avatar
Kevin Cristiano committed
      $return = TRUE;
Kevin Cristiano's avatar
Kevin Cristiano committed
    }
Kevin Cristiano's avatar
Kevin Cristiano committed

    return $return;

Kevin Cristiano's avatar
Kevin Cristiano committed
   * Get arguments and request string from query vars.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.6
   *
   * @return array $argdata Array containing request arguments and request string.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function get_request_args() {

    $argString = NULL;
    $args = array();
Kevin Cristiano's avatar
Kevin Cristiano committed

    // Get path from query vars
    $q = get_query_var( 'q' );
    if (empty($q)) {
      $q = isset($_GET['q']) ? $_GET['q'] : '';
    }

    // Fix 'civicrm/civicrm' elements derived from CRM:url()
    // @see https://lab.civicrm.org/dev/rc/issues/5#note_16205
    if (defined('CIVICRM_CLEANURL') && CIVICRM_CLEANURL) {
      if (substr($q, 0, 16) === 'civicrm/civicrm/') {
        $q = str_replace('civicrm/civicrm/', 'civicrm/', $q);
        $_REQUEST['q'] = $_GET['q'] = $q;
        set_query_var( 'q', $q );
      }
    }

    if (!empty($q)) {
      $argString = trim($q);
Kevin Cristiano's avatar
Kevin Cristiano committed
      $args = explode('/', $argString);
    }
    $args = array_pad($args, 2, '');

    return array(
      'args' => $args,
      'argString' => $argString
    );

  }

Kevin Cristiano's avatar
Kevin Cristiano committed
  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Add CiviCRM's title to the header's <title> tag.
   *
   * @since 4.6
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @param string $title The title to set.
   * @return string The computed title.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function set_admin_title($title) {
    global $civicrm_wp_title;
    if (!$civicrm_wp_title) {
      return $title;
    }
    // Replace 1st occurance of "CiviCRM" in the title
    $pos = strpos($title, 'CiviCRM');
    if ($pos !== FALSE) {
      return substr_replace($title, $civicrm_wp_title, $pos, 7);
    }
    return $civicrm_wp_title;
  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Override a WordPress page title with the CiviCRM entity title.
   *
   * Callback method for 'single_page_title' hook, always called from WP front-end.
   *
   * @since 4.6
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @param string $post_title The title of the WordPress page or post.
   * @param object $post The WordPress post object the title applies to.
   * @return string $civicrm_wp_title The title of the CiviCRM entity.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function single_page_title( $post_title, $post ) {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Sanity check and override
Kevin Cristiano's avatar
Kevin Cristiano committed
    global $civicrm_wp_title;
    if (!empty($civicrm_wp_title)) {
      return $civicrm_wp_title;
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Fallback
Kevin Cristiano's avatar
Kevin Cristiano committed
    return $post_title;

  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Remove edit link from page content.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Callback from 'edit_post_link' hook.
   *
   * @since 4.6
   *
   * @return string Always empty.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function clear_edit_post_link() {
    return '';
  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Remove edit link in WP Admin Bar.
   *
   * Callback from 'wp_before_admin_bar_render' hook.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.6
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function clear_edit_post_menu_item() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Access object
Kevin Cristiano's avatar
Kevin Cristiano committed
    global $wp_admin_bar;

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Bail if in admin
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ( is_admin() ) return;

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Remove the menu item from front end
Kevin Cristiano's avatar
Kevin Cristiano committed
    $wp_admin_bar->remove_menu( 'edit' );

  }


  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Get base URL.
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * 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
Kevin Cristiano's avatar
Kevin Cristiano committed
   * CRM_Utils_System_WordPress::url().
   *
   * 27-09-2016
   * CRM-16421 CRM-17633 WIP Changes to support WP in it's own directory
   * https://wiki.civicrm.org/confluence/display/CRM/WordPress+installed+in+its+own+directory+issues
   * For now leave hard coded wp-admin references.
Kevin Cristiano's avatar
Kevin Cristiano committed
   * TODO: remove wp-admin references and replace with admin_url() in the future.
   * TODO: Look at best way to get path to admin_url.
   *
   * @since 4.4
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @param bool $absolute Passing TRUE prepends the scheme and domain, FALSE doesn't.
   * @param bool $frontend Passing FALSE returns the admin URL.
   * @param $forceBackend Passing TRUE overrides $frontend and returns the admin URL.
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @return mixed|null|string
   */
  public function get_base_url($absolute, $frontend, $forceBackend) {
    $config = CRM_Core_Config::singleton();
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ((is_admin() && !$frontend) || $forceBackend) {
      return Civi::paths()->getUrl('[wp.backend]/.', $absolute ? 'absolute' : 'relative');
Kevin Cristiano's avatar
Kevin Cristiano committed
    }
    else {
      return Civi::paths()->getUrl('[wp.frontend]/.', $absolute ? 'absolute' : 'relative');
Kevin Cristiano's avatar
Kevin Cristiano committed
} // Class CiviCRM_For_WordPress ends
Kevin Cristiano's avatar
Kevin Cristiano committed


/*
--------------------------------------------------------------------------------
Procedures start here
--------------------------------------------------------------------------------
*/


/**
 * The main function responsible for returning the CiviCRM_For_WordPress instance
 * to functions everywhere.
 *
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Use this function like you would a global variable, except without needing to
 * declare the global.
Kevin Cristiano's avatar
Kevin Cristiano committed
 *
 * Example: $civi = civi_wp();
 *
Kevin Cristiano's avatar
Kevin Cristiano committed
 * @since 4.4
 *
 * @return CiviCRM_For_WordPress The plugin instance.
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
function civi_wp() {
  return CiviCRM_For_WordPress::singleton();
}


Kevin Cristiano's avatar
Kevin Cristiano committed
/*
 * Instantiate CiviCRM_For_WordPress immediately.
 * See CiviCRM_For_WordPress::setup_instance()
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
Kevin Cristiano's avatar
Kevin Cristiano committed
civi_wp();
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Tell WordPress to call plugin activation method - no longer calls legacy
Kevin Cristiano's avatar
Kevin Cristiano committed
 * global scope function.
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
register_activation_hook( CIVICRM_PLUGIN_FILE, array( civi_wp(), 'activate' ) );


Kevin Cristiano's avatar
Kevin Cristiano committed
 * Tell WordPress to call plugin deactivation method - needed in order to reset
 * the option that is set on activation.
 */
register_deactivation_hook( CIVICRM_PLUGIN_FILE, array( civi_wp(), 'deactivate' ) );


Kevin Cristiano's avatar
Kevin Cristiano committed
// Uninstall uses the 'uninstall.php' method
// See: http://codex.wordpress.org/Function_Reference/register_uninstall_hook
Kevin Cristiano's avatar
Kevin Cristiano committed



/*
--------------------------------------------------------------------------------
The global scope functions below are to maintain backwards compatibility with
previous versions of the CiviCRM WordPress plugin.
--------------------------------------------------------------------------------
*/


/**
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Add CiviCRM access capabilities to WordPress roles.
 *
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Called by postProcess() in civicrm/CRM/ACL/Form/WordPress/Permissions.php
 * Also a callback for the 'init' hook in civi_wp()->register_hooks()
Kevin Cristiano's avatar
Kevin Cristiano committed
 *
 * @since 4.3
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
function wp_civicrm_capability() {
  civi_wp()->users->set_access_capabilities();
}

/**
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Test if CiviCRM is currently being displayed in WordPress.
 *
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Called by setTitle() in civicrm/CRM/Utils/System/WordPress.php
 * Also called at the top of this plugin file to determine AJAX status
Kevin Cristiano's avatar
Kevin Cristiano committed
 *
 * @since 4.3
 *
 * @return bool True if CiviCRM is displayed in WordPress, false otherwise.
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
function civicrm_wp_in_civicrm() {
  return civi_wp()->civicrm_in_wordpress();
}

/**
 * This was the original name of the initialization function and is
Kevin Cristiano's avatar
Kevin Cristiano committed
 * retained for backward compatibility.
 *
 * @since 4.3
 *
 * @return bool True if CiviCRM is initialized, false otherwise.
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
function civicrm_wp_initialize() {
  return civi_wp()->initialize();
}

/**
 * Initialize CiviCRM. Call this function from other modules too if
 * they use the CiviCRM API.
Kevin Cristiano's avatar
Kevin Cristiano committed
 *
 * @since 4.3
 *
 * @return bool True if CiviCRM is initialized, false otherwise.
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
function civicrm_initialize() {
  return civi_wp()->initialize();
}

/**
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Callback from 'edit_post_link' hook to remove edit link in civicrm_set_post_blank().
 *
 * @since 4.3
 *
 * @return string Always empty.
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
function civicrm_set_blank() {
  return civi_wp()->clear_edit_post_link();
}

/**
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Authentication function used by civicrm_wp_frontend().
 *
 * @since 4.3
 *
 * @param array $args The page arguments array.
 * @return bool True if authenticated, false otherwise.
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
function civicrm_check_permission( $args ) {
  return civi_wp()->users->check_permission( $args );
}

/**
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Called when authentication fails in civicrm_wp_frontend().
 *
 * @since 4.3
 *
 * @return string Warning message.
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
function civicrm_set_frontendmessage() {
  return civi_wp()->users->get_permission_denied();
}

/**
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Invoke CiviCRM in a WordPress context.
 *
 * Callback function from add_menu_page().
 * Callback from WordPress 'init' and 'the_content' hooks.
 * Also used by civicrm_wp_shortcode_includes() and _civicrm_update_user().
 *
 * @since 4.3
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
function civicrm_wp_invoke() {
  civi_wp()->invoke();
}

/**
 * Method that runs only when civicrm plugin is activated.
Kevin Cristiano's avatar
Kevin Cristiano committed
 *
 * @since 4.3
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
function civicrm_activate() {
  civi_wp()->activate();
}

/**
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Set WordPress user capabilities.
 *
 * Function to create anonymous_user' role, if 'anonymous_user' role is not in
 * the wordpress installation and assign minimum capabilities for all wordpress roles.
 * This function is called on plugin activation and also from upgrade_4_3_alpha1().
 *
 * @since 4.3
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
function civicrm_wp_set_capabilities() {
  civi_wp()->users->set_wp_user_capabilities();
}

/**
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Callback function for add_options_page() that runs the CiviCRM installer.
 *
 * @since 4.3
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
function civicrm_run_installer() {
  civi_wp()->run_installer();
}

/**
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Function to get the contact type.
 *
 * @since 4.3
 *
 * @param string $default The contact type.
 * @return string $ctype The contact type.
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
function civicrm_get_ctype( $default = NULL ) {
  return civi_wp()->users->get_civicrm_contact_type( $default );
}

/**
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Getter function for global $wp_set_breadCrumb.
 *
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Called by appendBreadCrumb() in civicrm/CRM/Utils/System/WordPress.php
Kevin Cristiano's avatar
Kevin Cristiano committed
 *
 * @since 4.3
 *
 * @return string $wp_set_breadCrumb The breadcrumb markup.
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
function wp_get_breadcrumb() {
  global $wp_set_breadCrumb;
  return $wp_set_breadCrumb;
}

/**
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Setter function for global $wp_set_breadCrumb.
 *
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Called by appendBreadCrumb() in civicrm/CRM/Utils/System/WordPress.php
 * Called by resetBreadCrumb() in civicrm/CRM/Utils/System/WordPress.php
Kevin Cristiano's avatar
Kevin Cristiano committed
 *
 * @since 4.3
 *
 * @param string $breadCrumb The desired breadcrumb markup.
 * @return string $wp_set_breadCrumb The breadcrumb markup.
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
function wp_set_breadcrumb( $breadCrumb ) {
  global $wp_set_breadCrumb;
  $wp_set_breadCrumb = $breadCrumb;
  return $wp_set_breadCrumb;
}


/**
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Incorporate WP-CLI Integration.
 *
 * Based on drush civicrm functionality, work done by Andy Walker.
Kevin Cristiano's avatar
Kevin Cristiano committed
 * https://github.com/andy-walker/wp-cli-civicrm
Kevin Cristiano's avatar
Kevin Cristiano committed
 *
 * @since 4.5
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
if ( defined('WP_CLI') && WP_CLI ) {
Kevin Cristiano's avatar
Kevin Cristiano committed
  // Changed from __DIR__ because of possible symlink issues
Kevin Cristiano's avatar
Kevin Cristiano committed
  include_once CIVICRM_PLUGIN_DIR . 'wp-cli/civicrm.php';
}