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