PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/DependencyInjection/MonologExtension.php

https://github.com/hason/MonologBundle
PHP | 506 lines | 414 code | 65 blank | 27 comment | 28 complexity | 3015071ac78b1d9c4125a64b6aba03e3 MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Bundle\MonologBundle\DependencyInjection;
  11. use Symfony\Component\HttpKernel\DependencyInjection\Extension;
  12. use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
  13. use Symfony\Component\DependencyInjection\ContainerBuilder;
  14. use Symfony\Component\Config\FileLocator;
  15. use Symfony\Component\DependencyInjection\Definition;
  16. use Symfony\Component\DependencyInjection\Reference;
  17. use Symfony\Component\DependencyInjection\ContainerInterface;
  18. /**
  19. * MonologExtension is an extension for the Monolog library.
  20. *
  21. * @author Jordi Boggiano <j.boggiano@seld.be>
  22. * @author Christophe Coevoet <stof@notk.org>
  23. */
  24. class MonologExtension extends Extension
  25. {
  26. private $nestedHandlers = array();
  27. private $swiftMailerHandlers = array();
  28. /**
  29. * Loads the Monolog configuration.
  30. *
  31. * @param array $configs An array of configuration settings
  32. * @param ContainerBuilder $container A ContainerBuilder instance
  33. */
  34. public function load(array $configs, ContainerBuilder $container)
  35. {
  36. $configuration = $this->getConfiguration($configs, $container);
  37. $config = $this->processConfiguration($configuration, $configs);
  38. if (isset($config['handlers'])) {
  39. $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
  40. $loader->load('monolog.xml');
  41. $container->setAlias('logger', 'monolog.logger');
  42. $handlers = array();
  43. foreach ($config['handlers'] as $name => $handler) {
  44. $handlers[$handler['priority']][] = array(
  45. 'id' => $this->buildHandler($container, $name, $handler),
  46. 'channels' => isset($handler['channels']) ? $handler['channels'] : null
  47. );
  48. }
  49. $container->setParameter(
  50. 'monolog.swift_mailer.handlers',
  51. $this->swiftMailerHandlers
  52. );
  53. ksort($handlers);
  54. $sortedHandlers = array();
  55. foreach ($handlers as $priorityHandlers) {
  56. foreach (array_reverse($priorityHandlers) as $handler) {
  57. $sortedHandlers[] = $handler;
  58. }
  59. }
  60. $handlersToChannels = array();
  61. foreach ($sortedHandlers as $handler) {
  62. if (!in_array($handler['id'], $this->nestedHandlers)) {
  63. $handlersToChannels[$handler['id']] = $handler['channels'];
  64. }
  65. }
  66. $container->setParameter('monolog.handlers_to_channels', $handlersToChannels);
  67. $this->addClassesToCompile(array(
  68. 'Monolog\\Formatter\\FormatterInterface',
  69. 'Monolog\\Formatter\\LineFormatter',
  70. 'Monolog\\Handler\\HandlerInterface',
  71. 'Monolog\\Handler\\AbstractHandler',
  72. 'Monolog\\Handler\\AbstractProcessingHandler',
  73. 'Monolog\\Handler\\StreamHandler',
  74. 'Monolog\\Handler\\FingersCrossedHandler',
  75. 'Monolog\\Handler\\TestHandler',
  76. 'Monolog\\Logger',
  77. 'Symfony\\Bridge\\Monolog\\Logger',
  78. 'Symfony\\Bridge\\Monolog\\Handler\\DebugHandler',
  79. 'Monolog\\Handler\\FingersCrossed\\ActivationStrategyInterface',
  80. 'Monolog\\Handler\\FingersCrossed\\ErrorLevelActivationStrategy',
  81. ));
  82. }
  83. $container->setParameter('monolog.additional_channels', isset($config['channels']) ? $config['channels'] : array());
  84. }
  85. /**
  86. * Returns the base path for the XSD files.
  87. *
  88. * @return string The XSD base path
  89. */
  90. public function getXsdValidationBasePath()
  91. {
  92. return __DIR__.'/../Resources/config/schema';
  93. }
  94. public function getNamespace()
  95. {
  96. return 'http://symfony.com/schema/dic/monolog';
  97. }
  98. private function buildHandler(ContainerBuilder $container, $name, array $handler)
  99. {
  100. $handlerId = $this->getHandlerId($name);
  101. $definition = new Definition(sprintf('%%monolog.handler.%s.class%%', $handler['type']));
  102. $handler['level'] = is_int($handler['level']) ? $handler['level'] : constant('Monolog\Logger::'.strtoupper($handler['level']));
  103. switch ($handler['type']) {
  104. case 'service':
  105. $container->setAlias($handlerId, $handler['id']);
  106. return $handlerId;
  107. case 'stream':
  108. $definition->setArguments(array(
  109. $handler['path'],
  110. $handler['level'],
  111. $handler['bubble'],
  112. ));
  113. break;
  114. case 'console':
  115. if (!class_exists('Symfony\Bridge\Monolog\Handler\ConsoleHandler')) {
  116. throw new \RuntimeException('The console handler requires symfony/monolog-bridge 2.4+');
  117. }
  118. $definition->setArguments(array(
  119. null,
  120. $handler['bubble'],
  121. isset($handler['verbosity_levels']) ? $handler['verbosity_levels'] : array()
  122. ));
  123. $definition->addTag('kernel.event_subscriber');
  124. break;
  125. case 'firephp':
  126. $definition->setArguments(array(
  127. $handler['level'],
  128. $handler['bubble'],
  129. ));
  130. $definition->addTag('kernel.event_listener', array('event' => 'kernel.response', 'method' => 'onKernelResponse'));
  131. break;
  132. case 'gelf':
  133. if (isset($handler['publisher']['id'])) {
  134. $publisherId = $handler['publisher']['id'];
  135. } elseif (class_exists('Gelf\Transport\UdpTransport')) {
  136. $transport = new Definition("Gelf\Transport\UdpTransport", array(
  137. $handler['publisher']['hostname'],
  138. $handler['publisher']['port'],
  139. $handler['publisher']['chunk_size'],
  140. ));
  141. $transportId = uniqid('monolog.gelf.transport.');
  142. $transport->setPublic(false);
  143. $container->setDefinition($transportId, $transport);
  144. $publisher = new Definition("%monolog.gelfphp.publisher.class%", array());
  145. $publisher->addMethodCall('addTransport', array(new Reference($transportId)));
  146. $publisherId = uniqid('monolog.gelf.publisher.');
  147. $publisher->setPublic(false);
  148. $container->setDefinition($publisherId, $publisher);
  149. } elseif (class_exists('Gelf\MessagePublisher')) {
  150. $publisher = new Definition("%monolog.gelf.publisher.class%", array(
  151. $handler['publisher']['hostname'],
  152. $handler['publisher']['port'],
  153. $handler['publisher']['chunk_size'],
  154. ));
  155. $publisherId = uniqid('monolog.gelf.publisher.');
  156. $publisher->setPublic(false);
  157. $container->setDefinition($publisherId, $publisher);
  158. } else {
  159. throw new \RuntimeException('The gelf handler requires the graylog2/gelf-php package to be installed');
  160. }
  161. $definition->setArguments(array(
  162. new Reference($publisherId),
  163. $handler['level'],
  164. $handler['bubble'],
  165. ));
  166. break;
  167. case 'mongo':
  168. if (isset($handler['mongo']['id'])) {
  169. $clientId = $handler['mongo']['id'];
  170. } else {
  171. $server = 'mongodb://';
  172. if(isset($handler['mongo']['user'])) {
  173. $server .= $handler['mongo']['user'] . ':' . $handler['mongo']['pass'] . '@';
  174. }
  175. $server .= $handler['mongo']['host'] . ':' . $handler['mongo']['port'];
  176. $client = new Definition("%monolog.mongo.client.class%", array(
  177. $server
  178. ));
  179. $clientId = uniqid('monolog.mongo.client.');
  180. $client->setPublic(false);
  181. $container->setDefinition($clientId, $client);
  182. }
  183. $definition->setArguments(array(
  184. new Reference($clientId),
  185. $handler['mongo']['database'],
  186. $handler['mongo']['collection'],
  187. $handler['level'],
  188. $handler['bubble'],
  189. ));
  190. break;
  191. case 'chromephp':
  192. $definition->setArguments(array(
  193. $handler['level'],
  194. $handler['bubble'],
  195. ));
  196. $definition->addTag('kernel.event_listener', array('event' => 'kernel.response', 'method' => 'onKernelResponse'));
  197. break;
  198. case 'rotating_file':
  199. $definition->setArguments(array(
  200. $handler['path'],
  201. $handler['max_files'],
  202. $handler['level'],
  203. $handler['bubble'],
  204. ));
  205. break;
  206. case 'fingers_crossed':
  207. $handler['action_level'] = is_int($handler['action_level']) ? $handler['action_level'] : constant('Monolog\Logger::'.strtoupper($handler['action_level']));
  208. $nestedHandlerId = $this->getHandlerId($handler['handler']);
  209. $this->nestedHandlers[] = $nestedHandlerId;
  210. if (isset($handler['activation_strategy'])) {
  211. $activation = new Reference($handler['activation_strategy']);
  212. } elseif (!empty($handler['excluded_404s'])) {
  213. $activationDef = new Definition('%monolog.activation_strategy.not_found.class%', array($handler['excluded_404s'], $handler['action_level']));
  214. $activationDef->addMethodCall('setRequest', array(new Reference('request', ContainerInterface::NULL_ON_INVALID_REFERENCE, false)));
  215. $container->setDefinition($handlerId.'.not_found_strategy', $activationDef);
  216. $activation = new Reference($handlerId.'.not_found_strategy');
  217. } else {
  218. $activation = $handler['action_level'];
  219. }
  220. $definition->setArguments(array(
  221. new Reference($nestedHandlerId),
  222. $activation,
  223. $handler['buffer_size'],
  224. $handler['bubble'],
  225. $handler['stop_buffering'],
  226. ));
  227. break;
  228. case 'buffer':
  229. $nestedHandlerId = $this->getHandlerId($handler['handler']);
  230. $this->nestedHandlers[] = $nestedHandlerId;
  231. $definition->setArguments(array(
  232. new Reference($nestedHandlerId),
  233. $handler['buffer_size'],
  234. $handler['level'],
  235. $handler['bubble'],
  236. ));
  237. break;
  238. case 'group':
  239. $references = array();
  240. foreach ($handler['members'] as $nestedHandler) {
  241. $nestedHandlerId = $this->getHandlerId($nestedHandler);
  242. $this->nestedHandlers[] = $nestedHandlerId;
  243. $references[] = new Reference($nestedHandlerId);
  244. }
  245. $definition->setArguments(array(
  246. $references,
  247. $handler['bubble'],
  248. ));
  249. break;
  250. case 'syslog':
  251. $definition->setArguments(array(
  252. $handler['ident'],
  253. $handler['facility'],
  254. $handler['level'],
  255. $handler['bubble'],
  256. $handler['logopts'],
  257. ));
  258. break;
  259. case 'syslogudp':
  260. $definition->setArguments(array(
  261. $handler['host'],
  262. $handler['port'],
  263. $handler['facility'],
  264. $handler['level'],
  265. $handler['bubble'],
  266. ));
  267. break;
  268. case 'swift_mailer':
  269. $oldHandler = false;
  270. // fallback for older symfony versions that don't have the new SwiftMailerHandler in the bridge
  271. $newHandlerClass = $container->getParameterBag()->resolveValue($definition->getClass());
  272. if (!class_exists($newHandlerClass)) {
  273. $definition = new Definition('Monolog\Handler\SwiftMailerHandler');
  274. $oldHandler = true;
  275. }
  276. if (isset($handler['email_prototype'])) {
  277. if (!empty($handler['email_prototype']['method'])) {
  278. $prototype = array(new Reference($handler['email_prototype']['id']), $handler['email_prototype']['method']);
  279. } else {
  280. $prototype = new Reference($handler['email_prototype']['id']);
  281. }
  282. } else {
  283. $message = new Definition('Swift_Message');
  284. $message->setFactoryMethod('createMessage');
  285. $message->setPublic(false);
  286. $message->addMethodCall('setFrom', array($handler['from_email']));
  287. $message->addMethodCall('setTo', array($handler['to_email']));
  288. $message->addMethodCall('setSubject', array($handler['subject']));
  289. if(isset($handler['mailer'])){
  290. $mailer = $handler['mailer'];
  291. } else {
  292. $mailer = 'mailer';
  293. }
  294. $message->setFactoryService($mailer);
  295. if (isset($handler['content_type'])) {
  296. $message->addMethodCall('setContentType', array($handler['content_type']));
  297. }
  298. $messageId = sprintf('%s.mail_prototype', $handlerId);
  299. $container->setDefinition($messageId, $message);
  300. $prototype = new Reference($messageId);
  301. }
  302. $definition->setArguments(array(
  303. new Reference($handler['mailer']),
  304. $prototype,
  305. $handler['level'],
  306. $handler['bubble'],
  307. ));
  308. if (!$oldHandler) {
  309. $this->swiftMailerHandlers[] = $handlerId;
  310. $definition->addTag('kernel.event_listener', array('event' => 'kernel.terminate', 'method' => 'onKernelTerminate'));
  311. if (method_exists($newHandlerClass, 'onCliTerminate')) {
  312. $definition->addTag('kernel.event_listener', array('event' => 'console.terminate', 'method' => 'onCliTerminate'));
  313. }
  314. }
  315. break;
  316. case 'native_mailer':
  317. $definition->setArguments(array(
  318. $handler['to_email'],
  319. $handler['subject'],
  320. $handler['from_email'],
  321. $handler['level'],
  322. $handler['bubble'],
  323. ));
  324. break;
  325. case 'socket':
  326. $definition->setArguments(array(
  327. $handler['connection_string'],
  328. $handler['level'],
  329. $handler['bubble'],
  330. ));
  331. if (isset($handler['timeout'])) {
  332. $definition->addMethodCall('setTimeout', array($handler['timeout']));
  333. }
  334. if (isset($handler['connection_timeout'])) {
  335. $definition->addMethodCall('setConnectionTimeout', array($handler['connection_timeout']));
  336. }
  337. if (isset($handler['persistent'])) {
  338. $definition->addMethodCall('setPersistent', array($handler['persistent']));
  339. }
  340. break;
  341. case 'pushover':
  342. $definition->setArguments(array(
  343. $handler['token'],
  344. $handler['user'],
  345. $handler['title'],
  346. $handler['level'],
  347. $handler['bubble'],
  348. ));
  349. break;
  350. case 'hipchat':
  351. $definition->setArguments(array(
  352. $handler['token'],
  353. $handler['room'],
  354. $handler['nickname'],
  355. $handler['notify'],
  356. $handler['level'],
  357. $handler['bubble'],
  358. ));
  359. break;
  360. case 'cube':
  361. $definition->setArguments(array(
  362. $handler['url'],
  363. $handler['level'],
  364. $handler['bubble'],
  365. ));
  366. break;
  367. case 'amqp':
  368. $definition->setArguments(array(
  369. new Reference($handler['exchange']),
  370. $handler['exchange_name'],
  371. $handler['level'],
  372. $handler['bubble'],
  373. ));
  374. break;
  375. case 'error_log':
  376. $definition->setArguments(array(
  377. $handler['message_type'],
  378. $handler['level'],
  379. $handler['bubble'],
  380. ));
  381. break;
  382. case 'raven':
  383. $clientId = 'monolog.raven.client.' . sha1($handler['dsn']);
  384. if (null !== $handler['client_id']) {
  385. $clientId = $handler['client_id'];
  386. }
  387. if (!$container->hasDefinition($clientId)) {
  388. $client = new Definition("Raven_Client", array(
  389. $handler['dsn']
  390. ));
  391. $client->setPublic(false);
  392. $container->setDefinition($clientId, $client);
  393. }
  394. $definition->setArguments(array(
  395. new Reference($clientId),
  396. $handler['level'],
  397. $handler['bubble'],
  398. ));
  399. break;
  400. case 'loggly':
  401. $definition->setArguments(array(
  402. $handler['token'],
  403. $handler['level'],
  404. $handler['bubble'],
  405. ));
  406. if (!empty($handler['tags'])) {
  407. $definition->addMethodCall('setTag', array(implode(',', $handler['tags'])));
  408. }
  409. break;
  410. case 'logentries':
  411. $definition->setArguments(array(
  412. $handler['token'],
  413. $handler['use_ssl'],
  414. $handler['level'],
  415. $handler['bubble'],
  416. ));
  417. break;
  418. // Handlers using the constructor of AbstractHandler without adding their own arguments
  419. case 'newrelic':
  420. case 'test':
  421. case 'null':
  422. case 'debug':
  423. $definition->setArguments(array(
  424. $handler['level'],
  425. $handler['bubble'],
  426. ));
  427. break;
  428. default:
  429. throw new \InvalidArgumentException(sprintf('Invalid handler type "%s" given for handler "%s"', $handler['type'], $name));
  430. }
  431. if (!empty($handler['formatter'])) {
  432. $definition->addMethodCall('setFormatter', array(new Reference($handler['formatter'])));
  433. }
  434. $container->setDefinition($handlerId, $definition);
  435. return $handlerId;
  436. }
  437. private function getHandlerId($name)
  438. {
  439. return sprintf('monolog.handler.%s', $name);
  440. }
  441. }