Commit | Line | Data |
---|---|---|
1c3c3394 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
4 | | Copyright CiviCRM LLC. All rights reserved. | | |
5 | | | | |
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 | | |
9 | +--------------------------------------------------------------------+ | |
10 | */ | |
11 | ||
12 | /** | |
13 | * | |
14 | * @package CRM | |
15 | * @copyright CiviCRM LLC https://civicrm.org/licensing | |
16 | */ | |
17 | class CRM_Upgrade_DispatchPolicy { | |
18 | ||
19 | /** | |
20 | * Determine the dispatch policy | |
21 | * | |
22 | * @param string $phase | |
23 | * Ex: 'upgrade.main' or 'upgrade.finish'. | |
24 | * @return array | |
25 | * @see \Civi\Core\CiviEventDispatcher::setDispatchPolicy() | |
26 | */ | |
27 | public static function get($phase) { | |
28 | ||
29 | // Should hooks dispatch while applying CiviCRM DB upgrades? The answer is | |
30 | // mixed: it depends on the specific hook and the specific upgrade-step. | |
31 | // | |
32 | // Some example considerations: | |
c3a19c11 | 33 | // |
1c3c3394 TO |
34 | // - If the "log_civicrm_*" tables and triggers are to be reconciled during |
35 | // the upgrade, then one probably needs access to the list of tables and | |
36 | // triggers defined by extensions. These are provided by hooks. | |
37 | // - If a hook fires while the DB has stale schema, and if the hook's logic | |
38 | // has a direct (SQL) or indirect (BAO/API) dependency on the schema, then | |
39 | // the hook is prone to fail. (Ex: CiviCRM 4.x and the migration from | |
40 | // civicrm_domain.config_backend to civicrm_setting.) | |
41 | // - If *any* hook from an extension is called, then it may use classes | |
42 | // from the same extension, so the classloader / include-path / hook_config | |
43 | // should be operational. | |
44 | // - If there is a general system flush at the end of the upgrade (to rebuild | |
45 | // important data-structures -- routing tables, container cache, metadata | |
46 | // cache, etc), then there's a huge number of hooks that should fire. | |
47 | // - When hooks (or variations like "rules") are used to define business-logic, | |
48 | // they probably are not intended to fire during DB upgrade. Then again, | |
49 | // upgrade-logic is usually written with lower-level semantics that avoid firing hooks. | |
50 | // | |
c3a19c11 TO |
51 | // To balance these mixed considerations, the upgrade runs in two phases: |
52 | // | |
53 | // - Defensive/conservative/closed phase ("upgrade.main"): Likely mismatch | |
54 | // between schema+code. Low-confidence in most services (APIs/hooks/etc). | |
55 | // Ignore caches/indices/etc. Only perform low-level schema revisions. | |
56 | // - Constructive/liberal/open phase ("upgrade.finish"): Schema+code match. | |
57 | // Higher confidence in most services (APIs/hooks/etc). | |
58 | // Rehydrate caches/indices/etc. | |
59 | // | |
1c3c3394 | 60 | // Related discussions: |
c3a19c11 TO |
61 | // |
62 | // - https://github.com/civicrm/civicrm-core/pull/17126 | |
1c3c3394 TO |
63 | // - https://github.com/civicrm/civicrm-core/pull/13551 |
64 | // - https://lab.civicrm.org/dev/core/issues/1449 | |
65 | // - https://lab.civicrm.org/dev/core/issues/1460 | |
66 | ||
67 | $strict = getenv('CIVICRM_UPGRADE_STRICT') || CRM_Utils_Constant::value('CIVICRM_UPGRADE_STRICT'); | |
68 | $policies = []; | |
69 | ||
70 | // The "upgrade.main" policy applies during the planning and incremental revisions. | |
71 | // It's more restrictive, preventing interference from unexpected callpaths. | |
72 | $policies['upgrade.main'] = [ | |
73 | 'hook_civicrm_config' => 'run', | |
a9033ca7 TO |
74 | // cleanupPermissions() in some UF's can be destructive. Running prematurely could be actively harmful. |
75 | 'hook_civicrm_permission' => 'fail', | |
aa7a6575 | 76 | 'hook_civicrm_crypto' => 'drop', |
1c3c3394 TO |
77 | '/^hook_civicrm_(pre|post)$/' => 'drop', |
78 | '/^hook_civicrm_/' => $strict ? 'warn-drop' : 'drop', | |
79 | '/^civi\./' => 'run', | |
80 | '/./' => $strict ? 'warn-drop' : 'drop', | |
81 | ]; | |
82 | ||
83 | // The "upgrade.finish" policy applies at the end while performing the final clear/rebuild. | |
84 | // It's more permissive, allowing more data-structures to rehydrate correctly. | |
85 | $policies['upgrade.finish'] = [ | |
86 | '/^hook_civicrm_(pre|post)$/' => 'drop', | |
87 | '/./' => 'run', | |
88 | ]; | |
89 | ||
90 | // For comparison, "upgrade.old" is an estimation of the previous policy. It | |
91 | // was applied at all times during the upgrade. | |
92 | $policies['upgrade.old'] = [ | |
93 | 'hook_civicrm_alterSettingsFolders' => 'run', | |
94 | 'hook_civicrm_alterSettingsMetaData' => 'run', | |
95 | 'hook_civicrm_triggerInfo' => 'run', | |
96 | 'hook_civicrm_alterLogTables' => 'run', | |
97 | 'hook_civicrm_container' => 'run', | |
98 | 'hook_civicrm_permission' => 'run', | |
99 | 'hook_civicrm_managed' => 'run', | |
100 | 'hook_civicrm_config' => 'run', | |
101 | '/^hook_civicrm_(pre|post)$/' => 'drop', | |
102 | '/^hook_civicrm_/' => 'drop', | |
103 | '/^civi\./' => 'run', | |
104 | '/./' => 'run', | |
105 | ]; | |
106 | ||
29b6189c TO |
107 | // return $policies['upgrade.old']; |
108 | return $policies[$phase]; | |
1c3c3394 TO |
109 | } |
110 | ||
111 | } |