/src/Propel/Runtime/ServiceContainer/StandardServiceContainer.php

https://github.com/fabienpomerol/Propel2 · PHP · 487 lines · 215 code · 52 blank · 220 comment · 15 complexity · ac4546ad0fb17ae82b658d0e8e454377 MD5 · raw file

  1. <?php
  2. /**
  3. * This file is part of the Propel package.
  4. * For the full copyright and license information, please view the LICENSE
  5. * file that was distributed with this source code.
  6. *
  7. * @license MIT License
  8. */
  9. namespace Propel\Runtime\ServiceContainer;
  10. use Propel\Runtime\Adapter\AdapterFactory;
  11. use Propel\Runtime\Adapter\AdapterInterface;
  12. use Propel\Runtime\Adapter\Exception\AdapterException;
  13. use Preopl\Runtime\Exception\UnexpectedValueException;
  14. use Propel\Runtime\Connection\ConnectionInterface;
  15. use Propel\Runtime\Connection\ConnectionManagerInterface;
  16. use Propel\Runtime\Connection\ConnectionManagerSingle;
  17. use Propel\Runtime\Map\DatabaseMap;
  18. use Monolog\Logger;
  19. class StandardServiceContainer implements ServiceContainerInterface
  20. {
  21. /**
  22. * @var array[\Propel\Runtime\Adapter\AdapterInterface] List of database adapter instances
  23. */
  24. protected $adapters = array();
  25. /**
  26. * @var array[string] List of database adapter classes
  27. */
  28. protected $adapterClasses = array();
  29. /**
  30. * @var string
  31. */
  32. protected $defaultDatasource = ServiceContainerInterface::DEFAULT_DATASOURCE_NAME;
  33. /**
  34. * @var string
  35. */
  36. protected $databaseMapClass = ServiceContainerInterface::DEFAULT_DATABASE_MAP_CLASS;
  37. /**
  38. * @var array[\Propel\Runtime\Map\DatabaseMap] List of database map instances
  39. */
  40. protected $databaseMaps = array();
  41. /**
  42. * @var array[\Propel\Runtime\Connection\ConnectionManagerInterface] List of connection managers
  43. */
  44. protected $connectionManagers = array();
  45. /**
  46. * @var string
  47. */
  48. protected $profilerClass = ServiceContainerInterface::DEFAULT_PROFILER_CLASS;
  49. /**
  50. * @var array
  51. */
  52. protected $profilerConfiguration = array();
  53. /**
  54. * @var \Propel\Runtime\Util\Profiler
  55. */
  56. protected $profiler;
  57. /**
  58. * @var array[\Monolog\Logger] list of loggers
  59. */
  60. protected $loggers = array();
  61. /**
  62. * @var array
  63. */
  64. protected $loggerConfigurations = array();
  65. /**
  66. * @return string
  67. */
  68. public function getDefaultDatasource()
  69. {
  70. return $this->defaultDatasource;
  71. }
  72. /**
  73. * @param string $defaultDatasource
  74. */
  75. public function setDefaultDatasource($defaultDatasource)
  76. {
  77. $this->defaultDatasource = $defaultDatasource;
  78. }
  79. /**
  80. * Get the adapter class for a given datasource.
  81. *
  82. * @param string $name The datasource name
  83. *
  84. * @return string
  85. */
  86. public function getAdapterClass($name = null)
  87. {
  88. if (null === $name) {
  89. $name = $this->getDefaultDatasource();
  90. }
  91. return $this->adapterClasses[$name];
  92. }
  93. /**
  94. * Set the adapter class for a given datasource.
  95. *
  96. * This allows for lazy-loading adapter objects in getAdapter().
  97. *
  98. * @param string $name The datasource name
  99. * @param string $adapterClass
  100. */
  101. public function setAdapterClass($name, $adapterClass)
  102. {
  103. $this->adapterClasses[$name] = $adapterClass;
  104. unset($this->adapters[$name]);
  105. }
  106. /**
  107. * Reset existing adapters classes and set new classes for all datasources.
  108. *
  109. * @param array $adapters A list of adapters
  110. */
  111. public function setAdapterClasses($adapterClasses)
  112. {
  113. $this->adapterClasses = $adapterClasses;
  114. $this->adapters = array();
  115. }
  116. /**
  117. * Get the adapter for a given datasource.
  118. *
  119. * If the adapter does not yet exist, build it using the related adapterClass.
  120. *
  121. * @param string $name The datasource name
  122. *
  123. * @return Propel\Runtime\Adapter\AdapterInterface
  124. */
  125. public function getAdapter($name = null)
  126. {
  127. if (null === $name) {
  128. $name = $this->getDefaultDatasource();
  129. }
  130. if (!isset($this->adapters[$name])) {
  131. if (!isset($this->adapterClasses[$name])) {
  132. throw new AdapterException(sprintf('No adapter class defined for datasource "%s"', $name));
  133. }
  134. $this->adapters[$name] = AdapterFactory::create($this->adapterClasses[$name]);
  135. }
  136. return $this->adapters[$name];
  137. }
  138. /**
  139. * Set the adapter for a given datasource.
  140. *
  141. * @param string $name The datasource name
  142. * @param \Propel\Runtime\Adapter\AdapterInterface $adapter
  143. */
  144. public function setAdapter($name, AdapterInterface $adapter)
  145. {
  146. $this->adapters[$name] = $adapter;
  147. $this->adapterClasses[$name] = get_class($adapter);
  148. }
  149. /**
  150. * Reset existing adapters and set new adapters for all datasources.
  151. *
  152. * @param array $adapters A list of adapters
  153. */
  154. public function setAdapters($adapters)
  155. {
  156. $this->adapterClasses = array();
  157. $this->adapters = array();
  158. foreach ($adapters as $name => $adapter) {
  159. $this->setAdapter($name, $adapter);
  160. }
  161. }
  162. /**
  163. * @param string $databaseMapClass
  164. */
  165. public function setDatabaseMapClass($databaseMapClass)
  166. {
  167. $this->databaseMapClass = $databaseMapClass;
  168. }
  169. /**
  170. * Get the database map for a given datasource.
  171. *
  172. * The database maps are "registered" by the generated map builder classes.
  173. *
  174. * @param string $name The datasource name
  175. *
  176. * @return \Propel\Runtime\Map\DatabaseMap
  177. */
  178. public function getDatabaseMap($name = null)
  179. {
  180. if (null === $name) {
  181. $name = $this->getDefaultDatasource();
  182. }
  183. if (!isset($this->databaseMaps[$name])) {
  184. $class = $this->databaseMapClass;
  185. $this->databaseMaps[$name] = new $class($name);
  186. }
  187. return $this->databaseMaps[$name];
  188. }
  189. /**
  190. * Set the database map object to use for a given datasource.
  191. *
  192. * @param string $name The datasource name
  193. * @param \Propel\Runtime\Map\DatabaseMap $databaseMap
  194. */
  195. public function setDatabaseMap($name, DatabaseMap $databaseMap)
  196. {
  197. $this->databaseMaps[$name] = $databaseMap;
  198. }
  199. /**
  200. * @param string $name The datasource name
  201. * @param \Propel\Runtime\Connection\ConnectionManagerInterface $manager
  202. */
  203. public function setConnectionManager($name, ConnectionManagerInterface $manager)
  204. {
  205. if (isset($this->connectionManagers[$name])) {
  206. $this->connectionManagers[$name]->closeConnections();
  207. }
  208. if (!$manager->getName()) {
  209. $manager->setName($name);
  210. }
  211. $this->connectionManagers[$name] = $manager;
  212. }
  213. /**
  214. * @param string $name The datasource name
  215. *
  216. * @return \Propel\Runtime\Connection\ConnectionManagerInterface
  217. */
  218. public function getConnectionManager($name)
  219. {
  220. return $this->connectionManagers[$name];
  221. }
  222. /**
  223. * @return array[\Propel\Runtime\Connection\ConnectionManagerInterface]
  224. */
  225. public function getConnectionManagers()
  226. {
  227. return $this->connectionManagers;
  228. }
  229. /**
  230. * Close any associated resource handles.
  231. *
  232. * This method frees any database connection handles that have been
  233. * opened by the getConnection() method.
  234. */
  235. public function closeConnections()
  236. {
  237. foreach ($this->connectionManagers as $manager) {
  238. $manager->closeConnections();
  239. }
  240. }
  241. /**
  242. * Get a connection for a given datasource.
  243. *
  244. * If the connection has not been opened, open it using the related
  245. * connectionSettings. If the connection has already been opened, return it.
  246. *
  247. * @param string $name The datasource name
  248. * @param string $mode The connection mode (this applies to replication systems).
  249. *
  250. * @return \Propel\Runtime\Connection\ConnectionInterface A database connection
  251. */
  252. public function getConnection($name = null, $mode = ServiceContainerInterface::CONNECTION_WRITE)
  253. {
  254. if (null === $name) {
  255. $name = $this->getDefaultDatasource();
  256. }
  257. if (ServiceContainerInterface::CONNECTION_READ === $mode) {
  258. return $this->getReadConnection($name);
  259. }
  260. return $this->getWriteConnection($name);
  261. }
  262. /**
  263. * Get a write connection for a given datasource.
  264. *
  265. * If the connection has not been opened, open it using the related
  266. * connectionSettings. If the connection has already been opened, return it.
  267. *
  268. * @param string $name The datasource name that is used to look up the DSN
  269. * from the runtime configuration file. Empty name not allowed.
  270. *
  271. * @return ConnectionInterface A database connection
  272. *
  273. * @throws \Propel\Runtime\Adapter\Exception\AdapterException - if connection is not properly configured
  274. */
  275. public function getWriteConnection($name)
  276. {
  277. return $this->getConnectionManager($name)->getWriteConnection($this->getAdapter($name));
  278. }
  279. /**
  280. * Get a read connection for a given datasource.
  281. *
  282. * If the slave connection has not been opened, open it using a random read connection
  283. * setting for the related datasource. If no read connection setting exist, return the master
  284. * connection. If the slave connection has already been opened, return it.
  285. *
  286. * @param string $name The datasource name that is used to look up the DSN
  287. * from the runtime configuration file. Empty name not allowed.
  288. *
  289. * @return ConnectionInterface A database connection
  290. */
  291. public function getReadConnection($name)
  292. {
  293. return $this->getConnectionManager($name)->getReadConnection($this->getAdapter($name));
  294. }
  295. /**
  296. * Shortcut to define a single connectino for a datasource.
  297. *
  298. * @param string $name The datasource name
  299. * @param \Propel\Runtime\Connection\ConnectionInterface A database connection
  300. */
  301. public function setConnection($name, ConnectionInterface $connection)
  302. {
  303. $manager = new ConnectionManagerSingle();
  304. $manager->setConnection($connection);
  305. $this->setConnectionManager($name, $manager);
  306. }
  307. /**
  308. * Override the default profiler class.
  309. *
  310. * The service container uses this class to instanctiate a new profiler when
  311. * getProfiler() is called.
  312. *
  313. * @param string $profilerClass
  314. */
  315. public function setProfilerClass($profilerClass)
  316. {
  317. $this->profilerClass = $profilerClass;
  318. $this->profiler = null;
  319. }
  320. /**
  321. * Set the profiler configuration.
  322. * @see \Propel\Runtime\Util\Profiler::setConfiguration()
  323. *
  324. * @param array $profilerConfiguration
  325. */
  326. public function setProfilerConfiguration($profilerConfiguration)
  327. {
  328. $this->profilerConfiguration = $profilerConfiguration;
  329. $this->profiler = null;
  330. }
  331. /**
  332. * Set the profiler instance.
  333. *
  334. * @param \Propel\Runtime\Util\Profiler $profiler
  335. */
  336. public function setProfiler($profiler)
  337. {
  338. $this->profiler = $profiler;
  339. }
  340. /**
  341. * Get a profiler instance.
  342. *
  343. * If no profiler is set, create one using profilerClass and profilerConfiguration.
  344. *
  345. * @return \Propel\Runtime\Util\Profiler
  346. */
  347. public function getProfiler()
  348. {
  349. if (null === $this->profiler) {
  350. $class = $this->profilerClass;
  351. $profiler = new $class();
  352. if (!empty($this->profilerConfiguration)) {
  353. $profiler->setConfiguration($this->profilerConfiguration);
  354. }
  355. $this->profiler = $profiler;
  356. }
  357. return $this->profiler;
  358. }
  359. /**
  360. * @return Boolean
  361. */
  362. public function hasLogger($name = 'defaultLogger')
  363. {
  364. return null !== $this->getLogger($name);
  365. }
  366. /**
  367. * Get a logger instance
  368. *
  369. * @return \Monolog\Logger
  370. */
  371. public function getLogger($name = 'defaultLogger')
  372. {
  373. if (!isset($this->loggers[$name])) {
  374. $this->loggers[$name] = $this->buildLogger($name);
  375. }
  376. return $this->loggers[$name];
  377. }
  378. /**
  379. * @param string $name the name of the logger to be set
  380. * @param \Monolog\Logger $logger A logger instance
  381. */
  382. public function setLogger($name, Logger $logger)
  383. {
  384. $this->loggers[$name] = $logger;
  385. }
  386. protected function buildLogger($name = 'defaultLogger')
  387. {
  388. if (!isset($this->loggerConfigurations[$name])) {
  389. return 'defaultLogger' !== $name ? $this->getLogger() : null;
  390. }
  391. $logger = new Logger($name);
  392. $configuration = $this->loggerConfigurations[$name];
  393. switch ($configuration['type']) {
  394. case 'stream':
  395. $handler = new \Monolog\Handler\StreamHandler($configuration['path'], isset($configuration['level']) ? $configuration['level'] : null, isset($configuration['bubble']) ? $configuration['bubble'] : null);
  396. break;
  397. case 'rotating_file':
  398. $handler = new \Monolog\Handler\RotatingFileHandler($configuration['path'], isset($configuration['max_files']) ? $configuration['max_files'] : null, isset($configuration['level']) ? $configuration['level'] : null, isset($configuration['bubble']) ? $configuration['bubble'] : null);
  399. break;
  400. case 'syslog':
  401. $handler = new \Monolog\Handler\SyslogHandler($configuration['ident'], isset($configuration['facility']) ? $configuration['facility'] : null, isset($configuration['level']) ? $configuration['level'] : null, isset($configuration['bubble']) ? $configuration['bubble'] : null);
  402. break;
  403. default:
  404. throw new UnexpectedValueException(sprintf('Handler type "%s" not supported by StandardServiceContainer. Try setting the Logger manually, or use another ServiceContainer.', $configuration['type']));
  405. break;
  406. }
  407. $logger->pushHandler($handler);
  408. return $logger;
  409. }
  410. /**
  411. * Set the configuration for the logger of a given datasource.
  412. *
  413. * A logger configuration must contain a 'handlers' key defining one
  414. * or more handlers of type stream, rotating_file, or syslog.
  415. * You can also create more complex loggers by hand and set them directly
  416. * using setLogger().
  417. *
  418. * @example
  419. * <code>
  420. * $sc->setLoggerConfiguration('bookstore', array(
  421. * 'handlers' => array('stream' => array('path' => '/var/log/Propel.log'))
  422. * ));
  423. * </code>
  424. *
  425. * @param string $name
  426. * @param array $loggerConfiguration
  427. */
  428. public function setLoggerConfiguration($name, $loggerConfiguration)
  429. {
  430. $this->loggerConfigurations[$name] = $loggerConfiguration;
  431. }
  432. final private function __clone()
  433. {
  434. }
  435. }