1<?php 2/** 3 * Matomo - free/libre analytics platform 4 * 5 * @link https://matomo.org 6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later 7 */ 8 9namespace Piwik\Container; 10 11use DI\Container; 12use DI\ContainerBuilder; 13use Piwik\Application\Kernel\GlobalSettingsProvider; 14use Piwik\Application\Kernel\PluginList; 15use Piwik\Plugin\Manager; 16 17/** 18 * Creates a configured DI container. 19 */ 20class ContainerFactory 21{ 22 /** 23 * @var PluginList 24 */ 25 private $pluginList; 26 27 /** 28 * @var GlobalSettingsProvider 29 */ 30 private $settings; 31 32 /** 33 * Optional environment configs to load. 34 * 35 * @var string[] 36 */ 37 private $environments; 38 39 /** 40 * @var array[] 41 */ 42 private $definitions; 43 44 /** 45 * @param PluginList $pluginList 46 * @param GlobalSettingsProvider $settings 47 * @param string[] $environment Optional environment configs to load. 48 * @param array[] $definitions 49 */ 50 public function __construct(PluginList $pluginList, GlobalSettingsProvider $settings, array $environments = array(), array $definitions = array()) 51 { 52 $this->pluginList = $pluginList; 53 $this->settings = $settings; 54 $this->environments = $environments; 55 $this->definitions = $definitions; 56 } 57 58 /** 59 * @link http://php-di.org/doc/container-configuration.html 60 * @throws \Exception 61 * @return Container 62 */ 63 public function create() 64 { 65 $builder = new ContainerBuilder(); 66 67 $builder->useAnnotations(false); 68 69 // INI config 70 $builder->addDefinitions(new IniConfigDefinitionSource($this->settings)); 71 72 // Global config 73 $builder->addDefinitions(PIWIK_DOCUMENT_ROOT . '/config/global.php'); 74 75 // Plugin configs 76 $this->addPluginConfigs($builder); 77 78 // Development config 79 if ($this->isDevelopmentModeEnabled()) { 80 $this->addEnvironmentConfig($builder, 'dev'); 81 } 82 83 // Environment config 84 foreach ($this->environments as $environment) { 85 $this->addEnvironmentConfig($builder, $environment); 86 } 87 88 // User config 89 if (file_exists(PIWIK_USER_PATH . '/config/config.php') 90 && !in_array('test', $this->environments, true)) { 91 $builder->addDefinitions(PIWIK_USER_PATH . '/config/config.php'); 92 } 93 94 if (!empty($this->definitions)) { 95 foreach ($this->definitions as $definitionArray) { 96 $builder->addDefinitions($definitionArray); 97 } 98 } 99 100 $container = $builder->build(); 101 $container->set('Piwik\Application\Kernel\PluginList', $this->pluginList); 102 $container->set('Piwik\Application\Kernel\GlobalSettingsProvider', $this->settings); 103 104 return $container; 105 } 106 107 private function addEnvironmentConfig(ContainerBuilder $builder, $environment) 108 { 109 if (!$environment) { 110 return; 111 } 112 113 $file = sprintf('%s/config/environment/%s.php', PIWIK_USER_PATH, $environment); 114 115 if (file_exists($file)) { 116 $builder->addDefinitions($file); 117 } 118 119 // add plugin environment configs 120 $plugins = $this->pluginList->getActivatedPlugins(); 121 122 if ($this->shouldSortPlugins()) { 123 $plugins = $this->sortPlugins($plugins); 124 } 125 126 foreach ($plugins as $plugin) { 127 $baseDir = Manager::getPluginDirectory($plugin); 128 129 $environmentFile = $baseDir . '/config/' . $environment . '.php'; 130 if (file_exists($environmentFile)) { 131 $builder->addDefinitions($environmentFile); 132 } 133 } 134 } 135 136 private function addPluginConfigs(ContainerBuilder $builder) 137 { 138 $plugins = $this->pluginList->getActivatedPlugins(); 139 140 if ($this->shouldSortPlugins()) { 141 $plugins = $this->sortPlugins($plugins); 142 } 143 144 foreach ($plugins as $plugin) { 145 $baseDir = Manager::getPluginDirectory($plugin); 146 147 $file = $baseDir . '/config/config.php'; 148 if (file_exists($file)) { 149 $builder->addDefinitions($file); 150 } 151 } 152 } 153 154 /** 155 * This method is required for Matomo Cloud to allow for custom sorting of plugin order 156 * 157 * @return bool 158 */ 159 private function shouldSortPlugins() 160 { 161 return isset($GLOBALS['MATOMO_SORT_PLUGINS']) && is_callable($GLOBALS['MATOMO_SORT_PLUGINS']); 162 } 163 164 /** 165 * @param array $plugins 166 * @return array 167 */ 168 private function sortPlugins(array $plugins) 169 { 170 return call_user_func($GLOBALS['MATOMO_SORT_PLUGINS'], $plugins); 171 } 172 173 private function isDevelopmentModeEnabled() 174 { 175 $section = $this->settings->getSection('Development'); 176 return (bool) @$section['enabled']; // TODO: code redundancy w/ Development. hopefully ok for now. 177 } 178} 179