Commit | Line | Data |
---|---|---|
fa184193 TO |
1 | <?php |
2 | namespace Civi\Core; | |
46bcf597 | 3 | |
0085db83 | 4 | use Civi\Core\Event\SystemInstallEvent; |
10760fa1 | 5 | use Civi\Core\Lock\LockManager; |
40787e18 | 6 | use Symfony\Component\Config\ConfigCache; |
fa184193 TO |
7 | use Symfony\Component\DependencyInjection\ContainerBuilder; |
8 | use Symfony\Component\DependencyInjection\Definition; | |
40787e18 | 9 | use Symfony\Component\DependencyInjection\Dumper\PhpDumper; |
fa184193 | 10 | use Symfony\Component\DependencyInjection\Reference; |
40787e18 | 11 | use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; |
fa184193 TO |
12 | |
13 | // TODO use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; | |
14 | ||
6550386a EM |
15 | /** |
16 | * Class Container | |
17 | * @package Civi\Core | |
18 | */ | |
fa184193 TO |
19 | class Container { |
20 | ||
21 | const SELF = 'civi_container_factory'; | |
22 | ||
fa184193 | 23 | /** |
04855556 TO |
24 | * @param bool $reset |
25 | * Whether to forcibly rebuild the entire container. | |
fa184193 TO |
26 | * @return \Symfony\Component\DependencyInjection\TaggedContainerInterface |
27 | */ | |
378e2654 | 28 | public static function singleton($reset = FALSE) { |
7f835399 TO |
29 | if ($reset || !isset(\Civi::$statics[__CLASS__]['container'])) { |
30 | self::boot(TRUE); | |
fa184193 | 31 | } |
7f835399 | 32 | return \Civi::$statics[__CLASS__]['container']; |
fa184193 TO |
33 | } |
34 | ||
35 | /** | |
40787e18 TO |
36 | * Find a cached container definition or construct a new one. |
37 | * | |
38 | * There are many weird contexts in which Civi initializes (eg different | |
39 | * variations of multitenancy and different permutations of CMS/CRM bootstrap), | |
40 | * and hook_container may fire a bit differently in each context. To mitigate | |
41 | * risk of leaks between environments, we compute a unique envID | |
42 | * (md5(DB_NAME, HTTP_HOST, SCRIPT_FILENAME, etc)) and use separate caches for | |
43 | * each (eg "templates_c/CachedCiviContainer.$ENVID.php"). | |
44 | * | |
45 | * Constants: | |
46 | * - CIVICRM_CONTAINER_CACHE -- 'always' [default], 'never', 'auto' | |
47 | * - CIVICRM_DSN | |
48 | * - CIVICRM_DOMAIN_ID | |
49 | * - CIVICRM_TEMPLATE_COMPILEDIR | |
50 | * | |
34f3bbd9 | 51 | * @return \Symfony\Component\DependencyInjection\ContainerInterface |
40787e18 TO |
52 | */ |
53 | public function loadContainer() { | |
54 | // Note: The container's raison d'etre is to manage construction of other | |
55 | // services. Consequently, we assume a minimal service available -- the classloader | |
56 | // has been setup, and civicrm.settings.php is loaded, but nothing else works. | |
57 | ||
5497e016 | 58 | $cacheMode = defined('CIVICRM_CONTAINER_CACHE') ? CIVICRM_CONTAINER_CACHE : 'auto'; |
40787e18 TO |
59 | |
60 | // In pre-installation environments, don't bother with caching. | |
61 | if (!defined('CIVICRM_TEMPLATE_COMPILEDIR') || !defined('CIVICRM_DSN') || $cacheMode === 'never' || \CRM_Utils_System::isInUpgradeMode()) { | |
12e01332 TO |
62 | $containerBuilder = $this->createContainer(); |
63 | $containerBuilder->compile(); | |
64 | return $containerBuilder; | |
40787e18 TO |
65 | } |
66 | ||
83617886 | 67 | $envId = \CRM_Core_Config_Runtime::getId(); |
40787e18 TO |
68 | $file = CIVICRM_TEMPLATE_COMPILEDIR . "/CachedCiviContainer.{$envId}.php"; |
69 | $containerConfigCache = new ConfigCache($file, $cacheMode === 'auto'); | |
40787e18 TO |
70 | if (!$containerConfigCache->isFresh()) { |
71 | $containerBuilder = $this->createContainer(); | |
72 | $containerBuilder->compile(); | |
73 | $dumper = new PhpDumper($containerBuilder); | |
74 | $containerConfigCache->write( | |
c64f69d9 | 75 | $dumper->dump(['class' => 'CachedCiviContainer']), |
40787e18 TO |
76 | $containerBuilder->getResources() |
77 | ); | |
78 | } | |
79 | ||
80 | require_once $file; | |
81 | $c = new \CachedCiviContainer(); | |
40787e18 TO |
82 | return $c; |
83 | } | |
84 | ||
85 | /** | |
86 | * Construct a new container. | |
87 | * | |
34f3bbd9 | 88 | * @var \Symfony\Component\DependencyInjection\ContainerBuilder |
77b97be7 | 89 | * @return \Symfony\Component\DependencyInjection\ContainerBuilder |
fa184193 TO |
90 | */ |
91 | public function createContainer() { | |
92 | $civicrm_base_path = dirname(dirname(__DIR__)); | |
93 | $container = new ContainerBuilder(); | |
40787e18 TO |
94 | $container->addCompilerPass(new RegisterListenersPass('dispatcher')); |
95 | $container->addObjectResource($this); | |
fa184193 | 96 | $container->setParameter('civicrm_base_path', $civicrm_base_path); |
40787e18 | 97 | //$container->set(self::SELF, $this); |
762dc04d TO |
98 | |
99 | $container->addResource(new \Symfony\Component\Config\Resource\FileResource(__FILE__)); | |
100 | ||
40787e18 TO |
101 | $container->setDefinition(self::SELF, new Definition( |
102 | 'Civi\Core\Container', | |
c64f69d9 | 103 | [] |
40787e18 | 104 | )); |
fa184193 | 105 | |
505d8b83 TO |
106 | // TODO Move configuration to an external file; define caching structure |
107 | // if (empty($configDirectories)) { | |
108 | // throw new \Exception(__CLASS__ . ': Missing required properties (civicrmRoot, configDirectories)'); | |
109 | // } | |
110 | // $locator = new FileLocator($configDirectories); | |
111 | // $loaderResolver = new LoaderResolver(array( | |
112 | // new YamlFileLoader($container, $locator) | |
113 | // )); | |
114 | // $delegatingLoader = new DelegatingLoader($loaderResolver); | |
115 | // foreach (array('services.yml') as $file) { | |
116 | // $yamlUserFiles = $locator->locate($file, NULL, FALSE); | |
117 | // foreach ($yamlUserFiles as $file) { | |
118 | // $delegatingLoader->load($file); | |
119 | // } | |
120 | // } | |
fa184193 | 121 | |
16072ce1 | 122 | $container->setDefinition('angular', new Definition( |
40787e18 | 123 | 'Civi\Angular\Manager', |
c64f69d9 | 124 | [] |
16072ce1 | 125 | )) |
c64f69d9 | 126 | ->setFactory([new Reference(self::SELF), 'createAngularManager']); |
16072ce1 | 127 | |
fa184193 | 128 | $container->setDefinition('dispatcher', new Definition( |
762dc04d | 129 | 'Civi\Core\CiviEventDispatcher', |
c64f69d9 | 130 | [new Reference('service_container')] |
fa184193 | 131 | )) |
c64f69d9 | 132 | ->setFactory([new Reference(self::SELF), 'createEventDispatcher']); |
fa184193 | 133 | |
c65db512 | 134 | $container->setDefinition('magic_function_provider', new Definition( |
40787e18 | 135 | 'Civi\API\Provider\MagicFunctionProvider', |
c64f69d9 | 136 | [] |
c65db512 TO |
137 | )); |
138 | ||
0f643fb2 | 139 | $container->setDefinition('civi_api_kernel', new Definition( |
40787e18 | 140 | 'Civi\API\Kernel', |
c64f69d9 | 141 | [new Reference('dispatcher'), new Reference('magic_function_provider')] |
0f643fb2 | 142 | )) |
c64f69d9 | 143 | ->setFactory([new Reference(self::SELF), 'createApiKernel']); |
0f643fb2 | 144 | |
7b4bbb34 | 145 | $container->setDefinition('cxn_reg_client', new Definition( |
40787e18 | 146 | 'Civi\Cxn\Rpc\RegistrationClient', |
c64f69d9 | 147 | [] |
7b4bbb34 | 148 | )) |
5eda8e9b | 149 | ->setFactory('CRM_Cxn_BAO_Cxn::createRegistrationClient'); |
7b4bbb34 | 150 | |
c64f69d9 | 151 | $container->setDefinition('psr_log', new Definition('CRM_Core_Error_Log', [])); |
6e5ad5ee | 152 | |
c64f69d9 | 153 | $basicCaches = [ |
7a19d718 TO |
154 | 'js_strings' => 'js_strings', |
155 | 'community_messages' => 'community_messages', | |
b1fc1ab0 | 156 | 'checks' => 'checks', |
19707a63 | 157 | 'session' => 'CiviCRM Session', |
90cdaa0e | 158 | 'long' => 'long', |
c64f69d9 | 159 | ]; |
7a19d718 TO |
160 | foreach ($basicCaches as $cacheSvc => $cacheGrp) { |
161 | $container->setDefinition("cache.{$cacheSvc}", new Definition( | |
a4704404 | 162 | 'CRM_Utils_Cache_Interface', |
c64f69d9 CW |
163 | [ |
164 | [ | |
7a19d718 | 165 | 'name' => $cacheGrp, |
c64f69d9 CW |
166 | 'type' => ['*memory*', 'SqlGroup', 'ArrayCache'], |
167 | ], | |
168 | ] | |
a892989e | 169 | ))->setFactory('CRM_Utils_Cache::create'); |
a4704404 | 170 | } |
3a84c0ab | 171 | |
4ed867e0 TO |
172 | $container->setDefinition('sql_triggers', new Definition( |
173 | 'Civi\Core\SqlTriggers', | |
c64f69d9 | 174 | [] |
4ed867e0 TO |
175 | )); |
176 | ||
87e3fe24 TO |
177 | $container->setDefinition('asset_builder', new Definition( |
178 | 'Civi\Core\AssetBuilder', | |
c64f69d9 | 179 | [] |
87e3fe24 TO |
180 | )); |
181 | ||
247eb841 | 182 | $container->setDefinition('pear_mail', new Definition('Mail')) |
a892989e | 183 | ->setFactory('CRM_Utils_Mail::createMailer'); |
247eb841 | 184 | |
7f835399 TO |
185 | if (empty(\Civi::$statics[__CLASS__]['boot'])) { |
186 | throw new \RuntimeException("Cannot initialize container. Boot services are undefined."); | |
187 | } | |
188 | foreach (\Civi::$statics[__CLASS__]['boot'] as $bootService => $def) { | |
56eafc21 | 189 | $container->setDefinition($bootService, new Definition())->setSynthetic(TRUE); |
83617886 TO |
190 | } |
191 | ||
c8074a93 | 192 | // Expose legacy singletons as services in the container. |
c64f69d9 | 193 | $singletons = [ |
c8074a93 | 194 | 'httpClient' => 'CRM_Utils_HttpClient', |
7b5937fe | 195 | 'cache.default' => 'CRM_Utils_Cache', |
a7c57397 | 196 | 'i18n' => 'CRM_Core_I18n', |
c8074a93 TO |
197 | // Maybe? 'config' => 'CRM_Core_Config', |
198 | // Maybe? 'smarty' => 'CRM_Core_Smarty', | |
c64f69d9 | 199 | ]; |
c8074a93 TO |
200 | foreach ($singletons as $name => $class) { |
201 | $container->setDefinition($name, new Definition( | |
202 | $class | |
203 | )) | |
c64f69d9 | 204 | ->setFactory([$class, 'singleton']); |
c8074a93 | 205 | } |
90cdaa0e | 206 | $container->setAlias('cache.short', 'cache.default'); |
c8074a93 | 207 | |
223ba025 TO |
208 | $container->setDefinition('resources', new Definition( |
209 | 'CRM_Core_Resources', | |
210 | [new Reference('service_container')] | |
c64f69d9 | 211 | ))->setFactory([new Reference(self::SELF), 'createResources']); |
223ba025 | 212 | |
780fd0e3 | 213 | $container->setDefinition('prevnext', new Definition( |
99098349 TO |
214 | 'CRM_Core_PrevNextCache_Interface', |
215 | [new Reference('service_container')] | |
c64f69d9 | 216 | ))->setFactory([new Reference(self::SELF), 'createPrevNextCache']); |
99098349 TO |
217 | |
218 | $container->setDefinition('prevnext.driver.sql', new Definition( | |
780fd0e3 TO |
219 | 'CRM_Core_PrevNextCache_Sql', |
220 | [] | |
221 | )); | |
222 | ||
751f3d98 TO |
223 | $container->setDefinition('prevnext.driver.redis', new Definition( |
224 | 'CRM_Core_PrevNextCache_Redis', | |
225 | [new Reference('cache_config')] | |
226 | )); | |
227 | ||
228 | $container->setDefinition('cache_config', new Definition('ArrayObject')) | |
c64f69d9 | 229 | ->setFactory([new Reference(self::SELF), 'createCacheConfig']); |
751f3d98 | 230 | |
e7a6eae8 SL |
231 | $container->setDefinition('civi.mailing.triggers', new Definition( |
232 | 'Civi\Core\SqlTrigger\TimestampTriggers', | |
c64f69d9 CW |
233 | ['civicrm_mailing', 'Mailing'] |
234 | ))->addTag('kernel.event_listener', ['event' => 'hook_civicrm_triggerInfo', 'method' => 'onTriggerInfo']); | |
e7a6eae8 | 235 | |
e0a667ad TO |
236 | $container->setDefinition('civi.activity.triggers', new Definition( |
237 | 'Civi\Core\SqlTrigger\TimestampTriggers', | |
c64f69d9 CW |
238 | ['civicrm_activity', 'Activity'] |
239 | ))->addTag('kernel.event_listener', ['event' => 'hook_civicrm_triggerInfo', 'method' => 'onTriggerInfo']); | |
e0a667ad TO |
240 | |
241 | $container->setDefinition('civi.case.triggers', new Definition( | |
242 | 'Civi\Core\SqlTrigger\TimestampTriggers', | |
c64f69d9 CW |
243 | ['civicrm_case', 'Case'] |
244 | ))->addTag('kernel.event_listener', ['event' => 'hook_civicrm_triggerInfo', 'method' => 'onTriggerInfo']); | |
e0a667ad | 245 | |
b21ffed7 TO |
246 | $container->setDefinition('civi.case.staticTriggers', new Definition( |
247 | 'Civi\Core\SqlTrigger\StaticTriggers', | |
c64f69d9 CW |
248 | [ |
249 | [ | |
250 | [ | |
251 | 'upgrade_check' => ['table' => 'civicrm_case', 'column' => 'modified_date'], | |
b21ffed7 TO |
252 | 'table' => 'civicrm_case_activity', |
253 | 'when' => 'AFTER', | |
c64f69d9 | 254 | 'event' => ['INSERT'], |
b21ffed7 | 255 | 'sql' => "\nUPDATE civicrm_case SET modified_date = CURRENT_TIMESTAMP WHERE id = NEW.case_id;\n", |
c64f69d9 CW |
256 | ], |
257 | [ | |
258 | 'upgrade_check' => ['table' => 'civicrm_case', 'column' => 'modified_date'], | |
b21ffed7 TO |
259 | 'table' => 'civicrm_activity', |
260 | 'when' => 'BEFORE', | |
c64f69d9 | 261 | 'event' => ['UPDATE', 'DELETE'], |
b21ffed7 | 262 | 'sql' => "\nUPDATE civicrm_case SET modified_date = CURRENT_TIMESTAMP WHERE id IN (SELECT ca.case_id FROM civicrm_case_activity ca WHERE ca.activity_id = OLD.id);\n", |
c64f69d9 CW |
263 | ], |
264 | ], | |
265 | ] | |
b21ffed7 | 266 | )) |
c64f69d9 | 267 | ->addTag('kernel.event_listener', ['event' => 'hook_civicrm_triggerInfo', 'method' => 'onTriggerInfo']); |
b21ffed7 | 268 | |
43ceab3f TO |
269 | $container->setDefinition('civi_token_compat', new Definition( |
270 | 'Civi\Token\TokenCompatSubscriber', | |
c64f69d9 | 271 | [] |
43ceab3f | 272 | ))->addTag('kernel.event_subscriber'); |
56df2d06 TO |
273 | $container->setDefinition("crm_mailing_action_tokens", new Definition( |
274 | "CRM_Mailing_ActionTokens", | |
c64f69d9 | 275 | [] |
56df2d06 | 276 | ))->addTag('kernel.event_subscriber'); |
43ceab3f | 277 | |
c64f69d9 | 278 | foreach (['Activity', 'Contribute', 'Event', 'Mailing', 'Member'] as $comp) { |
46f5566c TO |
279 | $container->setDefinition("crm_" . strtolower($comp) . "_tokens", new Definition( |
280 | "CRM_{$comp}_Tokens", | |
c64f69d9 | 281 | [] |
46f5566c TO |
282 | ))->addTag('kernel.event_subscriber'); |
283 | } | |
50a23755 | 284 | |
aa4343bc | 285 | if (\CRM_Utils_Constant::value('CIVICRM_FLEXMAILER_HACK_SERVICES')) { |
c64f69d9 | 286 | \Civi\Core\Resolver::singleton()->call(CIVICRM_FLEXMAILER_HACK_SERVICES, [$container]); |
aa4343bc TO |
287 | } |
288 | ||
40787e18 TO |
289 | \CRM_Utils_Hook::container($container); |
290 | ||
fa184193 TO |
291 | return $container; |
292 | } | |
293 | ||
16072ce1 TO |
294 | /** |
295 | * @return \Civi\Angular\Manager | |
296 | */ | |
297 | public function createAngularManager() { | |
298 | return new \Civi\Angular\Manager(\CRM_Core_Resources::singleton()); | |
299 | } | |
300 | ||
fa184193 | 301 | /** |
34f3bbd9 | 302 | * @param \Symfony\Component\DependencyInjection\ContainerInterface $container |
43ceab3f | 303 | * @return \Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher |
fa184193 | 304 | */ |
40787e18 | 305 | public function createEventDispatcher($container) { |
762dc04d | 306 | $dispatcher = new CiviEventDispatcher($container); |
c64f69d9 CW |
307 | $dispatcher->addListener(SystemInstallEvent::EVENT_NAME, ['\Civi\Core\InstallationCanary', 'check']); |
308 | $dispatcher->addListener(SystemInstallEvent::EVENT_NAME, ['\Civi\Core\DatabaseInitializer', 'initialize']); | |
309 | $dispatcher->addListener(SystemInstallEvent::EVENT_NAME, ['\Civi\Core\LocalizationInitializer', 'initialize']); | |
310 | $dispatcher->addListener('hook_civicrm_pre', ['\Civi\Core\Event\PreEvent', 'dispatchSubevent'], 100); | |
311 | $dispatcher->addListener('hook_civicrm_post', ['\Civi\Core\Event\PostEvent', 'dispatchSubevent'], 100); | |
312 | $dispatcher->addListener('hook_civicrm_post::Activity', ['\Civi\CCase\Events', 'fireCaseChange']); | |
313 | $dispatcher->addListener('hook_civicrm_post::Case', ['\Civi\CCase\Events', 'fireCaseChange']); | |
314 | $dispatcher->addListener('hook_civicrm_caseChange', ['\Civi\CCase\Events', 'delegateToXmlListeners']); | |
315 | $dispatcher->addListener('hook_civicrm_caseChange', ['\Civi\CCase\SequenceListener', 'onCaseChange_static']); | |
316 | $dispatcher->addListener('hook_civicrm_eventDefs', ['\Civi\Core\CiviEventInspector', 'findBuiltInEvents']); | |
0d0031a0 | 317 | // TODO We need a better code-convention for metadata about non-hook events. |
c64f69d9 CW |
318 | $dispatcher->addListener('hook_civicrm_eventDefs', ['\Civi\API\Events', 'hookEventDefs']); |
319 | $dispatcher->addListener('hook_civicrm_eventDefs', ['\Civi\Core\Event\SystemInstallEvent', 'hookEventDefs']); | |
320 | $dispatcher->addListener('hook_civicrm_buildAsset', ['\Civi\Angular\Page\Modules', 'buildAngularModules']); | |
321 | $dispatcher->addListener('hook_civicrm_buildAsset', ['\CRM_Utils_VisualBundle', 'buildAssetJs']); | |
322 | $dispatcher->addListener('hook_civicrm_buildAsset', ['\CRM_Utils_VisualBundle', 'buildAssetCss']); | |
f22fb451 | 323 | $dispatcher->addListener('hook_civicrm_buildAsset', ['\CRM_Core_Resources', 'renderMenubarStylesheet']); |
303017a1 | 324 | $dispatcher->addListener('hook_civicrm_coreResourceList', ['\CRM_Utils_System', 'appendCoreResources']); |
62c20d1e | 325 | $dispatcher->addListener('hook_civicrm_getAssetUrl', ['\CRM_Utils_System', 'alterAssetUrl']); |
c64f69d9 CW |
326 | $dispatcher->addListener('civi.dao.postInsert', ['\CRM_Core_BAO_RecurringEntity', 'triggerInsert']); |
327 | $dispatcher->addListener('civi.dao.postUpdate', ['\CRM_Core_BAO_RecurringEntity', 'triggerUpdate']); | |
328 | $dispatcher->addListener('civi.dao.postDelete', ['\CRM_Core_BAO_RecurringEntity', 'triggerDelete']); | |
329 | $dispatcher->addListener('hook_civicrm_unhandled_exception', [ | |
9ae2d27b TO |
330 | 'CRM_Core_LegacyErrorHandler', |
331 | 'handleException', | |
c64f69d9 CW |
332 | ], -200); |
333 | $dispatcher->addListener(\Civi\ActionSchedule\Events::MAPPINGS, ['CRM_Activity_ActionMapping', 'onRegisterActionMappings']); | |
334 | $dispatcher->addListener(\Civi\ActionSchedule\Events::MAPPINGS, ['CRM_Contact_ActionMapping', 'onRegisterActionMappings']); | |
335 | $dispatcher->addListener(\Civi\ActionSchedule\Events::MAPPINGS, ['CRM_Contribute_ActionMapping_ByPage', 'onRegisterActionMappings']); | |
336 | $dispatcher->addListener(\Civi\ActionSchedule\Events::MAPPINGS, ['CRM_Contribute_ActionMapping_ByType', 'onRegisterActionMappings']); | |
337 | $dispatcher->addListener(\Civi\ActionSchedule\Events::MAPPINGS, ['CRM_Event_ActionMapping', 'onRegisterActionMappings']); | |
338 | $dispatcher->addListener(\Civi\ActionSchedule\Events::MAPPINGS, ['CRM_Member_ActionMapping', 'onRegisterActionMappings']); | |
46f5566c | 339 | |
aa4343bc | 340 | if (\CRM_Utils_Constant::value('CIVICRM_FLEXMAILER_HACK_LISTENERS')) { |
c64f69d9 | 341 | \Civi\Core\Resolver::singleton()->call(CIVICRM_FLEXMAILER_HACK_LISTENERS, [$dispatcher]); |
aa4343bc TO |
342 | } |
343 | ||
fa184193 TO |
344 | return $dispatcher; |
345 | } | |
0f643fb2 | 346 | |
10760fa1 | 347 | /** |
34f3bbd9 | 348 | * @return \Civi\Core\Lock\LockManager |
10760fa1 | 349 | */ |
83617886 | 350 | public static function createLockManager() { |
10760fa1 TO |
351 | // Ideally, downstream implementers could override any definitions in |
352 | // the container. For now, we'll make-do with some define()s. | |
353 | $lm = new LockManager(); | |
354 | $lm | |
c64f69d9 CW |
355 | ->register('/^cache\./', defined('CIVICRM_CACHE_LOCK') ? CIVICRM_CACHE_LOCK : ['CRM_Core_Lock', 'createScopedLock']) |
356 | ->register('/^data\./', defined('CIVICRM_DATA_LOCK') ? CIVICRM_DATA_LOCK : ['CRM_Core_Lock', 'createScopedLock']) | |
357 | ->register('/^worker\.mailing\.send\./', defined('CIVICRM_WORK_LOCK') ? CIVICRM_WORK_LOCK : ['CRM_Core_Lock', 'createCivimailLock']) | |
358 | ->register('/^worker\./', defined('CIVICRM_WORK_LOCK') ? CIVICRM_WORK_LOCK : ['CRM_Core_Lock', 'createScopedLock']); | |
10760fa1 TO |
359 | |
360 | // Registrations may use complex resolver expressions, but (as a micro-optimization) | |
361 | // the default factory is specified as an array. | |
362 | ||
363 | return $lm; | |
364 | } | |
365 | ||
0f643fb2 TO |
366 | /** |
367 | * @param \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher | |
2a6da8d7 EM |
368 | * @param $magicFunctionProvider |
369 | * | |
0f643fb2 TO |
370 | * @return \Civi\API\Kernel |
371 | */ | |
c65db512 | 372 | public function createApiKernel($dispatcher, $magicFunctionProvider) { |
0a946de2 | 373 | $dispatcher->addSubscriber(new \Civi\API\Subscriber\ChainSubscriber()); |
b55bc593 | 374 | $dispatcher->addSubscriber(new \Civi\API\Subscriber\TransactionSubscriber()); |
bace5cd9 | 375 | $dispatcher->addSubscriber(new \Civi\API\Subscriber\I18nSubscriber()); |
c65db512 | 376 | $dispatcher->addSubscriber($magicFunctionProvider); |
d0c9daa4 | 377 | $dispatcher->addSubscriber(new \Civi\API\Subscriber\PermissionCheck()); |
dcef11bd | 378 | $dispatcher->addSubscriber(new \Civi\API\Subscriber\APIv3SchemaAdapter()); |
c64f69d9 | 379 | $dispatcher->addSubscriber(new \Civi\API\Subscriber\WrapperAdapter([ |
6d3bdc98 TO |
380 | \CRM_Utils_API_HTMLInputCoder::singleton(), |
381 | \CRM_Utils_API_NullOutputCoder::singleton(), | |
382 | \CRM_Utils_API_ReloadOption::singleton(), | |
383 | \CRM_Utils_API_MatchOption::singleton(), | |
c64f69d9 | 384 | ])); |
0661f62b | 385 | $dispatcher->addSubscriber(new \Civi\API\Subscriber\XDebugSubscriber()); |
82376c19 TO |
386 | $kernel = new \Civi\API\Kernel($dispatcher); |
387 | ||
388 | $reflectionProvider = new \Civi\API\Provider\ReflectionProvider($kernel); | |
389 | $dispatcher->addSubscriber($reflectionProvider); | |
390 | ||
56154d36 TO |
391 | $dispatcher->addSubscriber(new \Civi\API\Subscriber\DynamicFKAuthorization( |
392 | $kernel, | |
393 | 'Attachment', | |
c64f69d9 | 394 | ['create', 'get', 'delete'], |
2e37a19f | 395 | // Given a file ID, determine the entity+table it's attached to. |
56154d36 TO |
396 | 'SELECT if(cf.id,1,0) as is_valid, cef.entity_table, cef.entity_id |
397 | FROM civicrm_file cf | |
398 | LEFT JOIN civicrm_entity_file cef ON cf.id = cef.file_id | |
399 | WHERE cf.id = %1', | |
29468114 TO |
400 | // Get a list of custom fields (field_name,table_name,extends) |
401 | 'SELECT concat("custom_",fld.id) as field_name, | |
402 | grp.table_name as table_name, | |
403 | grp.extends as extends | |
404 | FROM civicrm_custom_field fld | |
405 | INNER JOIN civicrm_custom_group grp ON fld.custom_group_id = grp.id | |
406 | WHERE fld.data_type = "File" | |
407 | ', | |
c64f69d9 | 408 | ['civicrm_activity', 'civicrm_mailing', 'civicrm_contact', 'civicrm_grant'] |
56154d36 TO |
409 | )); |
410 | ||
c64f69d9 | 411 | $kernel->setApiProviders([ |
82376c19 TO |
412 | $reflectionProvider, |
413 | $magicFunctionProvider, | |
c64f69d9 | 414 | ]); |
82376c19 | 415 | |
0f643fb2 TO |
416 | return $kernel; |
417 | } | |
96025800 | 418 | |
223ba025 | 419 | /** |
34f3bbd9 | 420 | * @param \Symfony\Component\DependencyInjection\ContainerInterface $container |
223ba025 TO |
421 | * @return \CRM_Core_Resources |
422 | */ | |
423 | public static function createResources($container) { | |
424 | $sys = \CRM_Extension_System::singleton(); | |
425 | return new \CRM_Core_Resources( | |
426 | $sys->getMapper(), | |
427 | $container->get('cache.js_strings'), | |
428 | \CRM_Core_Config::isUpgradeMode() ? NULL : 'resCacheCode' | |
429 | ); | |
430 | } | |
431 | ||
99098349 | 432 | /** |
34f3bbd9 | 433 | * @param \Symfony\Component\DependencyInjection\ContainerInterface $container |
99098349 TO |
434 | * @return \CRM_Core_PrevNextCache_Interface |
435 | */ | |
436 | public static function createPrevNextCache($container) { | |
e28bf654 TO |
437 | $setting = \Civi::settings()->get('prevNextBackend'); |
438 | if ($setting === 'default') { | |
f76de01c TO |
439 | // For initial release (5.8.x), continue defaulting to SQL. |
440 | $isTransitional = version_compare(\CRM_Utils_System::version(), '5.9.alpha1', '<'); | |
e28bf654 TO |
441 | $cacheDriver = \CRM_Utils_Cache::getCacheDriver(); |
442 | $service = 'prevnext.driver.' . strtolower($cacheDriver); | |
f76de01c | 443 | return $container->has($service) && !$isTransitional |
e28bf654 TO |
444 | ? $container->get($service) |
445 | : $container->get('prevnext.driver.sql'); | |
446 | } | |
447 | else { | |
448 | return $container->get('prevnext.driver.' . $setting); | |
449 | } | |
99098349 TO |
450 | } |
451 | ||
751f3d98 TO |
452 | public static function createCacheConfig() { |
453 | $driver = \CRM_Utils_Cache::getCacheDriver(); | |
454 | $settings = \CRM_Utils_Cache::getCacheSettings($driver); | |
455 | $settings['driver'] = $driver; | |
456 | return new \ArrayObject($settings); | |
457 | } | |
458 | ||
83617886 TO |
459 | /** |
460 | * Get a list of boot services. | |
461 | * | |
462 | * These are services which must be setup *before* the container can operate. | |
463 | * | |
7f835399 | 464 | * @param bool $loadFromDB |
83617886 TO |
465 | * @throws \CRM_Core_Exception |
466 | */ | |
7f835399 | 467 | public static function boot($loadFromDB) { |
56eafc21 | 468 | // Array(string $serviceId => object $serviceInstance). |
c64f69d9 | 469 | $bootServices = []; |
7f835399 | 470 | \Civi::$statics[__CLASS__]['boot'] = &$bootServices; |
d4330c62 | 471 | |
56eafc21 | 472 | $bootServices['runtime'] = $runtime = new \CRM_Core_Config_Runtime(); |
7f835399 | 473 | $runtime->initialize($loadFromDB); |
d4330c62 | 474 | |
56eafc21 | 475 | $bootServices['paths'] = new \Civi\Core\Paths(); |
d4330c62 | 476 | |
7f835399 | 477 | $class = $runtime->userFrameworkClass; |
56eafc21 | 478 | $bootServices['userSystem'] = $userSystem = new $class(); |
7f835399 TO |
479 | $userSystem->initialize(); |
480 | ||
481 | $userPermissionClass = 'CRM_Core_Permission_' . $runtime->userFramework; | |
56eafc21 | 482 | $bootServices['userPermissionClass'] = new $userPermissionClass(); |
7f835399 | 483 | |
c64f69d9 | 484 | $bootServices['cache.settings'] = \CRM_Utils_Cache::create([ |
56eafc21 | 485 | 'name' => 'settings', |
c64f69d9 CW |
486 | 'type' => ['*memory*', 'SqlGroup', 'ArrayCache'], |
487 | ]); | |
7f835399 | 488 | |
56eafc21 | 489 | $bootServices['settings_manager'] = new \Civi\Core\SettingsManager($bootServices['cache.settings']); |
7f835399 | 490 | |
56eafc21 | 491 | $bootServices['lockManager'] = self::createLockManager(); |
7f835399 TO |
492 | |
493 | if ($loadFromDB && $runtime->dsn) { | |
3a036b15 | 494 | \CRM_Core_DAO::init($runtime->dsn); |
edbcbd96 | 495 | \CRM_Utils_Hook::singleton(TRUE); |
7f835399 | 496 | \CRM_Extension_System::singleton(TRUE); |
4025c773 | 497 | \CRM_Extension_System::singleton(TRUE)->getClassLoader()->register(); |
7f835399 | 498 | |
1b81ed50 | 499 | $runtime->includeCustomPath(); |
500 | ||
7f835399 | 501 | $c = new self(); |
56eafc21 TO |
502 | $container = $c->loadContainer(); |
503 | foreach ($bootServices as $name => $obj) { | |
504 | $container->set($name, $obj); | |
505 | } | |
506 | \Civi::$statics[__CLASS__]['container'] = $container; | |
83617886 | 507 | } |
83617886 TO |
508 | } |
509 | ||
510 | public static function getBootService($name) { | |
56eafc21 | 511 | return \Civi::$statics[__CLASS__]['boot'][$name]; |
83617886 TO |
512 | } |
513 | ||
4d8e83b6 TO |
514 | /** |
515 | * Determine whether the container services are available. | |
516 | * | |
517 | * @return bool | |
518 | */ | |
519 | public static function isContainerBooted() { | |
520 | return isset(\Civi::$statics[__CLASS__]['container']); | |
521 | } | |
522 | ||
fa184193 | 523 | } |