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