Newer
Older
<?php
/*
Plugin Name: CiviCRM
Description: CiviCRM - Growing and Sustaining Relationships
Author URI: https://civicrm.org/
Plugin URI: https://wiki.civicrm.org/confluence/display/CRMDOC/Installing+CiviCRM+for+WordPress
License: AGPL3
Text Domain: civicrm
Domain Path: /languages
*/
/*
+--------------------------------------------------------------------+
+--------------------------------------------------------------------+
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
*
*/
/*
--------------------------------------------------------------------------------
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/
--------------------------------------------------------------------------------
*/
// Set version here: when it changes, will force JS to reload
define( 'CIVICRM_PLUGIN_VERSION', '4.7' );
if (!defined('CIVICRM_PLUGIN_FILE')) {
define( 'CIVICRM_PLUGIN_FILE', __FILE__ );
}
if (!defined( 'CIVICRM_PLUGIN_URL')) {
define( 'CIVICRM_PLUGIN_URL', plugin_dir_url(CIVICRM_PLUGIN_FILE) );
}
if (!defined( 'CIVICRM_PLUGIN_DIR')) {
define( 'CIVICRM_PLUGIN_DIR', plugin_dir_path(CIVICRM_PLUGIN_FILE) );
}
* 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' ) ) {
* 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.
*/
$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 );
}
else {
define( 'CIVICRM_SETTINGS_PATH', $wp_civi_settings );
}
if ( file_exists( CIVICRM_SETTINGS_PATH ) ) {
define( 'CIVICRM_INSTALLED', TRUE );
} else {
define( 'CIVICRM_INSTALLED', FALSE );
}
// Prevent CiviCRM from rendering its own header
* Define CiviCRM_For_WordPress Class.
*
* @since 4.4
* Plugin instance.
*
* @since 4.4
* @access private
* @var object $instance The plugin instance.
* Plugin context (broad).
*
* @since 4.4
* @access public
* @var bool $in_wordpress The broad plugin context.
/**
* Plugin context (specific).
*
* @since 4.4
* @access public
* @var str $context The specific plugin context.
*/
* Shortcodes management object.
*
* @since 4.4
* @access public
* @var object CiviCRM_For_WordPress_Shortcodes The shortcodes management object.
* Modal dialog management object.
*
* @since 4.4
* @access public
* @var object CiviCRM_For_WordPress_Shortcodes_Modal The modal dialog management object.
* Basepage management object.
*
* @since 4.4
* @access public
* @var object CiviCRM_For_WordPress_Basepage The basepage management object.
* User management object.
*
* @since 4.4
* @access public
* @var object CiviCRM_For_WordPress_Users The user management object.
*/
public $users;
// ---------------------------------------------------------------------------
// Setup
// ---------------------------------------------------------------------------
/**
* Getter method which returns the CiviCRM instance and optionally creates one
* if it does not already exist. Standard CiviCRM singleton pattern.
*
* @since 4.4
*
* @return object CiviCRM_For_WordPress The CiviCRM plugin instance.
// Delay setup until 'plugins_loaded' to allow other plugins to load as well
add_action( 'plugins_loaded', array( self::$instance, 'setup_instance' ) );
* Dummy instance constructor.
*
* @since 4.4
* Dummy magic method to prevent CiviCRM_For_WordPress from being cloned.
*
* @since 4.4
*/
public function __clone() {
_doing_it_wrong( __FUNCTION__, __( 'Only one instance of CiviCRM_For_WordPress please', 'civicrm' ), '4.4' );
}
/**
* Dummy magic method to prevent CiviCRM_For_WordPress from being unserialized.
*
* @since 4.4
*/
public function __wakeup() {
_doing_it_wrong( __FUNCTION__, __( 'Please do not serialize CiviCRM_For_WordPress', 'civicrm' ), '4.4' );
}
/**
* 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.
add_option( 'civicrm_activation_in_progress', 'true' );
}
/**
// Bail if not activating
if ( get_option( 'civicrm_activation_in_progress' ) !== 'true' ) {
return;
// Bail if not in WordPress admin
if ( !is_admin() ) {
return;
}
/**
* Broadcast that activation actions need to happen now.
*
* @since 5.6
*/
do_action( 'civicrm_activation' );
// Change option so this action never fires again
update_option( 'civicrm_activation_in_progress', 'false' );
* 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.
/**
* Broadcast that deactivation actions need to happen now.
*
* @since 5.6
*/
do_action( 'civicrm_deactivation' );
if ( isset( self::$in_wordpress ) ) {
wp_die( __( 'Only one instance of CiviCRM_For_WordPress please', 'civicrm' ) );
}
// Get existing session ID
$session_id = session_id();
/*
* 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.
*/
if ( empty( $session_id ) && ! ( defined( 'WP_CLI' ) && WP_CLI ) ) {
// Use translation files
$this->enable_translation();
// Register all hooks on init
add_action( 'init', array( $this, 'register_hooks' ) );
/**
* Broadcast that this plugin is now loaded.
*
* @since 4.4
*/
do_action( 'civicrm_instance_loaded' );
}
/**
* 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
*
* It is NOT true when CiviCRM is called via a shortcode.
self::$in_wordpress = ( isset( $_GET['page'] ) && $_GET['page'] == 'CiviCRM' ) ? TRUE : FALSE;
}
/**
* Getter for testing if CiviCRM is currently being displayed in WordPress.
*
* @see $this->civicrm_in_wordpress_set()
*
* @since 4.4
*
* @return bool $in_wordpress True if CiviCRM is displayed in WordPress, false otherwise.
/**
* 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.
*/
return apply_filters( 'civicrm_in_wordpress', self::$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
*
* The following codes correspond to the different contexts:
*
* (a) 'admin'
* (b) 'basepage'
* (c) 'nonpage'
* (d) 'shortcode'
*
* @since 4.4
*
* @param string $context One of the four context codes above.
*/
public function civicrm_context_set( $context ) {
* Getter for determining how CiviCRM is currently being displayed in WordPress.
*
* @see $this->civicrm_context_set()
*
* @since 4.4
*
* @return string The context in which CiviCRM is displayed in WordPress.
/**
* 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.
*/
return apply_filters( 'civicrm_context', self::$context );
}
// ---------------------------------------------------------------------------
// Files
// ---------------------------------------------------------------------------
/**
include_once CIVICRM_PLUGIN_DIR . 'includes/civicrm.users.php';
$this->users = new CiviCRM_For_WordPress_Users;
include_once CIVICRM_PLUGIN_DIR . 'includes/civicrm.shortcodes.php';
$this->shortcodes = new CiviCRM_For_WordPress_Shortcodes;
include_once CIVICRM_PLUGIN_DIR . 'includes/civicrm.shortcodes.modal.php';
$this->modal = new CiviCRM_For_WordPress_Shortcodes_Modal;
include_once CIVICRM_PLUGIN_DIR . 'includes/civicrm.basepage.php';
$this->basepage = new CiviCRM_For_WordPress_Basepage;
}
// ---------------------------------------------------------------------------
// Hooks
// ---------------------------------------------------------------------------
/**
$this->register_hooks_admin();
return;
}
// 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
*/
public function register_hooks_front_end() {
// Prevent multiple calls
static $alreadyRegistered = FALSE;
if ( $alreadyRegistered ) {
return;
}
$alreadyRegistered = TRUE;
// Store context
$this->civicrm_in_wordpress_set();
// When embedded via wpBasePage or AJAX call...
* 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() ) {
add_action( 'wp', array( $this, 'front_end_page_load' ) );
// Echo all output when WP has been set up but nothing has been rendered
add_action( 'wp', array( $this, 'invoke' ) );
return;
}
// If we get here, we must be in a wpBasePage context
$this->basepage->register_hooks();
return;
}
// That leaves us with handling shortcodes, should they exist
$this->shortcodes->register_hooks();
}
/**
$this->users->register_hooks();
}
/**
* Register hooks to handle CiviCRM in a WordPress admin context.
add_action( 'admin_menu', array( $this, 'add_menu_items' ) );
add_filter( 'admin_title', array( $this, 'set_admin_title' ) );
add_action('admin_head', array( $this, 'wp_head' ), 50);
// If settings file does not exist, show notice with link to installer
if ( ! CIVICRM_INSTALLED ) {
if ( isset( $_GET['page'] ) && $_GET['page'] == 'civicrm-install' ) {
// Set install type
$_GET['civicrm_install_type'] = 'wordpress';
add_action( 'admin_notices', array( $this, 'show_setup_warning' ) );
}
}
$this->modal->register_hooks();
}
// ---------------------------------------------------------------------------
// CiviCRM Initialisation
// ---------------------------------------------------------------------------
/**
* @return bool $success True if CiviCRM is initialized, false otherwise.
*/
public function initialize() {
static $initialized = FALSE;
static $failure = FALSE;
if ( $failure ) {
return FALSE;
}
if ( ! $initialized ) {
// Check for php version and ensure its greater than minPhpVersion
$minPhpVersion = '5.3.4';
if ( version_compare( PHP_VERSION, $minPhpVersion ) < 0 ) {
echo '<p>' .
sprintf(
__( 'CiviCRM requires PHP Version %s or greater. You are running PHP Version %s', 'civicrm' ),
$minPhpVersion,
PHP_VERSION
) .
'<p>';
exit();
}
if ( ! CIVICRM_INSTALLED ) {
$error = FALSE;
} elseif ( file_exists( CIVICRM_SETTINGS_PATH) ) {
$error = include_once ( CIVICRM_SETTINGS_PATH );
}
require_once 'CRM/Core/ClassLoader.php';
CRM_Core_ClassLoader::singleton()->register();
$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/";
$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
);
$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;
}
// Access global defined in civicrm.settings.php
// This does pretty much all of the civicrm initialization
if ( ! file_exists( $civicrm_root . 'CRM/Core/Config.php' ) ) {
$error = FALSE;
} else {
$error = include_once ( 'CRM/Core/Config.php' );
}
$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'> » " .
sprintf(
__( 'civicrm_root is currently set to: <em>%s</em>.', 'civicrm' ),
$civicrm_root
) .
"</p><p class='error'>" . $errorMsgAdd . "</p></strong>"
);
// Initialize the system by creating a config object
// Sync procedure sets session values for logged in users
require_once 'CRM/Core/BAO/UFMatch.php';
CRM_Core_BAO_UFMatch::synchronize(
$current_user, // User object
FALSE, // Do not update
'WordPress', // CMS
$this->users->get_civicrm_contact_type('Individual')
);
}
}
/**
* Broadcast that CiviCRM is now initialized.
*
* @since 4.4
*/
return TRUE;
}
// ---------------------------------------------------------------------------
// Plugin setup
// ---------------------------------------------------------------------------
/**
* A good reference on how to implement translation in WordPress:
* http://ottopress.com/2012/internationalization-youre-probably-doing-it-wrong/
*
'civicrm', // Unique name
FALSE, // Deprecated argument
dirname( plugin_basename( __FILE__ ) ) . '/languages/' // Relative path to translation files
* Callback method for 'admin_menu' hook as set in register_hooks().
*
* @since 4.4
$civilogo = file_get_contents( plugin_dir_path( __FILE__ ) . 'assets/civilogo.svg.b64' );
/**
* 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
$menu_page = add_menu_page(
__( 'CiviCRM', 'civicrm' ),
__( 'CiviCRM', 'civicrm' ),
'access_civicrm',
'CiviCRM',
array( $this, 'invoke' ),
$civilogo,
add_action( 'load-' . $menu_page, array( $this, 'admin_page_load' ) );
} else {
$menu_page = add_menu_page(
__( 'CiviCRM Installer', 'civicrm' ),
__( 'CiviCRM Installer', 'civicrm' ),
'manage_options',
'civicrm-install',
array( $this, 'run_installer' ),
$civilogo,
// 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 );
*/
}
}
// ---------------------------------------------------------------------------
// Installation
// ---------------------------------------------------------------------------
/**
* Callback method for add_options_page() that runs the CiviCRM installer.
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
$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;
}
}
// Uses CIVICRM_PLUGIN_DIR instead of WP_PLUGIN_DIR
$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 );
}
/**
* Callback method for missing settings file in register_hooks().
*/
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
// This is required for AJAX calls in WordPress admin
$_GET['noheader'] = TRUE;
// Add resources for back end
$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.
*