Merge pull request #14062 from civicrm/5.13
[civicrm-core.git] / CRM / Utils / Hook / WordPress.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
fee14197 4 | CiviCRM version 5 |
6a488035 5 +--------------------------------------------------------------------+
6b83d5bd 6 | Copyright CiviCRM LLC (c) 2004-2019 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
29 *
30 * @package CRM
6b83d5bd 31 * @copyright CiviCRM LLC (c) 2004-2019
6a488035
TO
32 */
33class CRM_Utils_Hook_WordPress extends CRM_Utils_Hook {
3db28451
CW
34
35 /**
36 * @var bool
37 */
38 private $isBuilt = FALSE;
39
40 /**
41 * @var array(string)
42 */
43 private $allModules = NULL;
44
45 /**
46 * @var array(string)
47 */
48 private $civiModules = NULL;
49
50 /**
51 * @var array(string)
52 */
53 private $wordpressModules = NULL;
54
55 /**
56 * @var array(string)
57 */
be2fb01f 58 private $hooksThatReturn = [
3db28451
CW
59 'civicrm_upgrade',
60 'civicrm_caseSummary',
61 'civicrm_dashboard',
be2fb01f 62 ];
3db28451 63
5bc392e6 64 /**
fe482240 65 * Invoke hooks.
5bc392e6 66 *
77855840
TO
67 * @param int $numParams
68 * Number of parameters to pass to the hook.
69 * @param mixed $arg1
70 * Parameter to be passed to the hook.
71 * @param mixed $arg2
72 * Parameter to be passed to the hook.
73 * @param mixed $arg3
74 * Parameter to be passed to the hook.
75 * @param mixed $arg4
76 * Parameter to be passed to the hook.
77 * @param mixed $arg5
78 * Parameter to be passed to the hook.
79 * @param mixed $arg6
80 * Parameter to be passed to the hook.
81 * @param string $fnSuffix
82 * Function suffix, this is effectively the hook name.
5bc392e6
EM
83 *
84 * @return mixed
85 */
354345c9 86 public function invokeViaUF(
3db28451 87 $numParams,
87dab4a4 88 &$arg1, &$arg2, &$arg3, &$arg4, &$arg5, &$arg6,
6a488035
TO
89 $fnSuffix
90 ) {
e7292422 91
50bfb460
SB
92 // do_action_ref_array is the default way of calling WordPress hooks
93 // because for the most part no return value is wanted. However, this is
94 // only generally true, so using do_action_ref_array() is only called for those
95 // hooks which do not require a return value. We exclude the following, which
96 // are incompatible with the WordPress Plugin API:
97 //
98 // civicrm_upgrade
99 // http://wiki.civicrm.org/confluence/display/CRMDOC43/hook_civicrm_upgrade
100 //
101 // civicrm_caseSummary
102 // http://wiki.civicrm.org/confluence/display/CRMDOC43/hook_civicrm_caseSummary
103 //
104 // civicrm_dashboard
105 // http://wiki.civicrm.org/confluence/display/CRMDOC43/hook_civicrm_dashboard
e7292422 106
3db28451 107 // distinguish between types of hook
353ffa53 108 if (!in_array($fnSuffix, $this->hooksThatReturn)) {
e7292422 109
3db28451 110 // only pass the arguments that have values
e7292422 111 $args = array_slice(
481a74f4 112 array(&$arg1, &$arg2, &$arg3, &$arg4, &$arg5, &$arg6),
e7292422 113 0,
3db28451
CW
114 $numParams
115 );
e7292422 116
50bfb460
SB
117 // Use WordPress Plugins API to modify $args
118 //
119 // Because $args are passed as references to the WordPress callbacks,
120 // runHooks subsequently receives appropriately modified parameters.
e7292422 121
3db28451
CW
122 // protect from REST calls
123 if (function_exists('do_action_ref_array')) {
481a74f4 124 do_action_ref_array($fnSuffix, $args);
3db28451 125 }
e7292422 126
3db28451 127 }
e7292422 128
50bfb460
SB
129 // The following is based on the logic of the Joomla hook file by allowing
130 // WordPress callbacks to do their stuff before runHooks gets called.
131
132 // It also follows the logic of the Drupal hook file by building the "module"
133 // (read "plugin") list and then calling runHooks directly. This should avoid
134 // the need for the post-processing that the Joomla hook file does.
135
136 // Note that hooks which require a return value are incompatible with the
137 // signature of apply_filters_ref_array and must therefore be called in
138 // global scope, like in Drupal. It's not ideal, but plugins can always route
139 // these calls to methods in their classes.
140
141 // At some point, those hooks could be pre-processed and called via the WordPress
142 // Plugin API, but it would change their signature and require the CiviCRM docs
143 // to be rewritten for those calls in WordPress. So it's been done this way for
144 // now. Ideally these hooks will be deprecated in favour of hooks that do not
145 // require return values.
e7292422 146
3db28451
CW
147 // build list of registered plugin codes
148 $this->buildModuleList();
e7292422 149
3db28451
CW
150 // Call runHooks the same way Drupal does
151 $moduleResult = $this->runHooks(
e7292422 152 $this->allModules,
3db28451 153 $fnSuffix,
e7292422 154 $numParams,
3db28451 155 $arg1, $arg2, $arg3, $arg4, $arg5, $arg6
6a488035 156 );
e7292422 157
3db28451
CW
158 // finally, return
159 return empty($moduleResult) ? TRUE : $moduleResult;
e7292422 160
6a488035 161 }
e7292422 162
3db28451
CW
163 /**
164 * Build the list of plugins ("modules" in CiviCRM terminology) to be processed for hooks.
3d469574 165 *
3db28451
CW
166 * We need to do this to preserve the CiviCRM hook signatures for hooks that require
167 * a return value, since the WordPress Plugin API seems to be incompatible with them.
e7292422 168 *
3db28451
CW
169 * Copied and adapted from: CRM/Utils/Hook/Drupal6.php
170 */
00be9182 171 public function buildModuleList() {
3db28451 172 if ($this->isBuilt === FALSE) {
e7292422 173
3db28451 174 if ($this->wordpressModules === NULL) {
e7292422 175
3db28451
CW
176 // include custom PHP file - copied from parent->commonBuildModuleList()
177 $config = CRM_Core_Config::singleton();
178 if (!empty($config->customPHPPathDir) &&
179 file_exists("{$config->customPHPPathDir}/civicrmHooks.php")
180 ) {
8efdc1d4 181 @include_once "{$config->customPHPPathDir}/civicrmHooks.php";
3db28451
CW
182 }
183
184 // initialise with the pre-existing 'wordpress' prefix
be2fb01f 185 $this->wordpressModules = ['wordpress'];
e7292422 186
50bfb460
SB
187 // Use WordPress Plugin API to build list
188 // a plugin simply needs to declare its "unique_plugin_code" thus:
189 // add_filter('civicrm_wp_plugin_codes', 'function_that_returns_my_unique_plugin_code');
e7292422 190
3db28451
CW
191 // protect from REST calls
192 if (function_exists('apply_filters')) {
193 $this->wordpressModules = apply_filters('civicrm_wp_plugin_codes', $this->wordpressModules);
194 }
e7292422 195
3db28451
CW
196 }
197
198 if ($this->civiModules === NULL) {
be2fb01f 199 $this->civiModules = [];
3db28451
CW
200 $this->requireCiviModules($this->civiModules);
201 }
202
e7292422 203 $this->allModules = array_merge((array) $this->wordpressModules, (array) $this->civiModules);
3db28451
CW
204 if ($this->wordpressModules !== NULL && $this->civiModules !== NULL) {
205 // both CRM and CMS have bootstrapped, so this is the final list
206 $this->isBuilt = TRUE;
207 }
e7292422 208
3db28451
CW
209 }
210 }
211
6a488035 212}