Initial commit with Symfony 2.1+Vendors

Signed-off-by: Gergely POLONKAI (W00d5t0ck) <polesz@w00d5t0ck.info>
This commit is contained in:
Polonkai Gergely
2012-07-01 09:52:20 +02:00
commit 082a0130c2
5381 changed files with 416709 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bundle\MonologBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;
/**
* Registers processors in Monolog loggers or handlers.
*
* @author Christophe Coevoet <stof@notk.org>
*/
class AddProcessorsPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('monolog.logger')) {
return;
}
foreach ($container->findTaggedServiceIds('monolog.processor') as $id => $tags) {
foreach ($tags as $tag) {
if (!empty($tag['channel']) && !empty($tag['handler'])) {
throw new \InvalidArgumentException(sprintf('you cannot specify both the "handler" and "channel" attributes for the "monolog.processor" tag on service "%s"', $id));
}
if (!empty($tag['handler'])) {
$definition = $container->findDefinition(sprintf('monolog.handler.%s', $tag['handler']));
} elseif (!empty($tag['channel'])) {
if ('app' === $tag['channel']) {
$definition = $container->getDefinition('monolog.logger');
} else {
$definition = $container->getDefinition(sprintf('monolog.logger.%s', $tag['channel']));
}
} else {
$definition = $container->getDefinition('monolog.logger_prototype');
}
if (!empty($tag['method'])) {
$processor = array(new Reference($id), $tag['method']);
} else {
// If no method is defined, fallback to use __invoke
$processor = new Reference($id);
}
$definition->addMethodCall('pushProcessor', array($processor));
}
}
}
}

View File

@@ -0,0 +1,49 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bundle\MonologBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Definition;
use Monolog\Logger;
/**
* Adds the DebugHandler when the profiler is enabled.
*
* @author Christophe Coevoet <stof@notk.org>
*/
class DebugHandlerPass implements CompilerPassInterface
{
private $channelPass;
public function __construct(LoggerChannelPass $channelPass)
{
$this->channelPass = $channelPass;
}
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('profiler')) {
return;
}
$debugHandler = new Definition('%monolog.handler.debug.class%', array(Logger::DEBUG, true));
$container->setDefinition('monolog.handler.debug', $debugHandler);
foreach ($this->channelPass->getChannels() as $channel) {
$container
->getDefinition($channel === 'app' ? 'monolog.logger' : 'monolog.logger.'.$channel)
->addMethodCall('pushHandler', array(new Reference('monolog.handler.debug')));
}
}
}

View File

@@ -0,0 +1,105 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bundle\MonologBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
/**
* Replaces the default logger by another one with its own channel for tagged services.
*
* @author Christophe Coevoet <stof@notk.org>
*/
class LoggerChannelPass implements CompilerPassInterface
{
protected $channels = array('app');
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('monolog.logger')) {
return;
}
foreach ($container->findTaggedServiceIds('monolog.logger') as $id => $tags) {
foreach ($tags as $tag) {
if (empty($tag['channel']) || 'app' === $tag['channel']) {
continue;
}
$definition = $container->getDefinition($id);
$loggerId = sprintf('monolog.logger.%s', $tag['channel']);
$this->createLogger($tag['channel'], $loggerId, $container);
foreach ($definition->getArguments() as $index => $argument) {
if ($argument instanceof Reference && 'logger' === (string) $argument) {
$definition->replaceArgument($index, new Reference($loggerId, $argument->getInvalidBehavior(), $argument->isStrict()));
}
}
$calls = $definition->getMethodCalls();
foreach ($calls as $i => $call) {
foreach ($call[1] as $index => $argument) {
if ($argument instanceof Reference && 'logger' === (string) $argument) {
$calls[$i][1][$index] = new Reference($loggerId, $argument->getInvalidBehavior(), $argument->isStrict());
}
}
}
$definition->setMethodCalls($calls);
}
}
$handlersToChannels = $container->getParameter('monolog.handlers_to_channels');
foreach ($handlersToChannels as $handler => $channels) {
foreach ($this->processChannels($channels) as $channel) {
try {
$logger = $container->getDefinition($channel === 'app' ? 'monolog.logger' : 'monolog.logger.'.$channel);
} catch (InvalidArgumentException $e) {
$msg = 'Monolog configuration error: The logging channel "'.$channel.'" assigned to the "'.substr($handler, 16).'" handler does not exist.';
throw new \InvalidArgumentException($msg, 0, $e);
}
$logger->addMethodCall('pushHandler', array(new Reference($handler)));
}
}
}
public function getChannels()
{
return $this->channels;
}
protected function processChannels($configuration)
{
if (null === $configuration) {
return $this->channels;
}
if ('inclusive' === $configuration['type']) {
return $configuration['elements'];
}
return array_diff($this->channels, $configuration['elements']);
}
protected function createLogger($channel, $loggerId, ContainerBuilder $container)
{
if (!in_array($channel, $this->channels)) {
$logger = new DefinitionDecorator('monolog.logger_prototype');
$logger->replaceArgument(0, $channel);
$container->setDefinition($loggerId, $logger);
$this->channels[] = $channel;
}
}
}

View File

@@ -0,0 +1,215 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bundle\MonologBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
/**
* This class contains the configuration information for the bundle
*
* This information is solely responsible for how the different configuration
* sections are normalized, and merged.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @author Christophe Coevoet <stof@notk.org>
*/
class Configuration implements ConfigurationInterface
{
/**
* Generates the configuration tree builder.
*
* @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('monolog');
$rootNode
->fixXmlConfig('handler')
->children()
->arrayNode('handlers')
->canBeUnset()
->useAttributeAsKey('name')
->prototype('array')
->fixXmlConfig('member')
->canBeUnset()
->children()
->scalarNode('type')
->isRequired()
->treatNullLike('null')
->beforeNormalization()
->always()
->then(function($v) { return strtolower($v); })
->end()
->end()
->scalarNode('id')->end()
->scalarNode('priority')->defaultValue(0)->end()
->scalarNode('level')->defaultValue('DEBUG')->end()
->booleanNode('bubble')->defaultTrue()->end()
->scalarNode('path')->defaultValue('%kernel.logs_dir%/%kernel.environment%.log')->end() // stream and rotating
->scalarNode('ident')->defaultFalse()->end() // syslog
->scalarNode('facility')->defaultValue('user')->end() // syslog
->scalarNode('max_files')->defaultValue(0)->end() // rotating
->scalarNode('action_level')->defaultValue('WARNING')->end() // fingers_crossed
->scalarNode('activation_strategy')->defaultNull()->end() // fingers_crossed
->booleanNode('stop_buffering')->defaultTrue()->end()// fingers_crossed
->scalarNode('buffer_size')->defaultValue(0)->end() // fingers_crossed and buffer
->scalarNode('handler')->end() // fingers_crossed and buffer
->arrayNode('publisher')
->canBeUnset()
->beforeNormalization()
->ifString()
->then(function($v) { return array('id'=> $v); })
->end()
->children()
->scalarNode('id')->end()
->scalarNode('hostname')->end()
->scalarNode('port')->defaultValue(12201)->end()
->scalarNode('chunk_size')->defaultValue(1420)->end()
->end()
->validate()
->ifTrue(function($v) {
return !isset($v['id']) && !isset($v['hostname']);
})
->thenInvalid('What must be set is either the hostname or the id.')
->end()
->end() // gelf
->arrayNode('members') // group
->canBeUnset()
->performNoDeepMerging()
->prototype('scalar')->end()
->end()
->scalarNode('from_email')->end() // swift_mailer and native_mailer
->scalarNode('to_email')->end() // swift_mailer and native_mailer
->scalarNode('subject')->end() // swift_mailer and native_mailer
->arrayNode('email_prototype') // swift_mailer
->canBeUnset()
->beforeNormalization()
->ifString()
->then(function($v) { return array('id' => $v); })
->end()
->children()
->scalarNode('id')->isRequired()->end()
->scalarNode('factory-method')->defaultNull()->end()
->end()
->end()
->arrayNode('channels')
->fixXmlConfig('channel', 'elements')
->canBeUnset()
->beforeNormalization()
->ifString()
->then(function($v) { return array('elements' => array($v)); })
->end()
->beforeNormalization()
->ifTrue(function($v) { return is_array($v) && is_numeric(key($v)); })
->then(function($v) { return array('elements' => $v); })
->end()
->validate()
->ifTrue(function($v) { return empty($v); })
->thenUnset()
->end()
->validate()
->always(function ($v) {
$isExclusive = null;
if (isset($v['type'])) {
$isExclusive = 'exclusive' === $v['type'];
}
$elements = array();
foreach ($v['elements'] as $element) {
if (0 === strpos($element, '!')) {
if (false === $isExclusive) {
throw new InvalidConfigurationException('Cannot combine exclusive/inclusive definitions in channels list.');
}
$elements[] = substr($element, 1);
$isExclusive = true;
} else {
if (true === $isExclusive) {
throw new InvalidConfigurationException('Cannot combine exclusive/inclusive definitions in channels list');
}
$elements[] = $element;
$isExclusive = false;
}
}
return array('type' => $isExclusive ? 'exclusive' : 'inclusive', 'elements' => $elements);
})
->end()
->children()
->scalarNode('type')
->validate()
->ifNotInArray(array('inclusive', 'exclusive'))
->thenInvalid('The type of channels has to be inclusive or exclusive')
->end()
->end()
->arrayNode('elements')
->prototype('scalar')->end()
->end()
->end()
->end()
->scalarNode('formatter')->end()
->end()
->validate()
->ifTrue(function($v) { return ('fingers_crossed' === $v['type'] || 'buffer' === $v['type']) && 1 !== count($v['handler']); })
->thenInvalid('The handler has to be specified to use a FingersCrossedHandler or BufferHandler')
->end()
->validate()
->ifTrue(function($v) { return 'swift_mailer' === $v['type'] && empty($v['email_prototype']) && (empty($v['from_email']) || empty($v['to_email']) || empty($v['subject'])); })
->thenInvalid('The sender, recipient and subject or an email prototype have to be specified to use a SwiftMailerHandler')
->end()
->validate()
->ifTrue(function($v) { return 'native_mailer' === $v['type'] && (empty($v['from_email']) || empty($v['to_email']) || empty($v['subject'])); })
->thenInvalid('The sender, recipient and subject have to be specified to use a NativeMailerHandler')
->end()
->validate()
->ifTrue(function($v) { return 'service' === $v['type'] && !isset($v['id']); })
->thenInvalid('The id has to be specified to use a service as handler')
->end()
->validate()
->ifTrue(function($v) { return 'gelf' === $v['type'] && !isset($v['publisher']); })
->thenInvalid('The publisher has to be specified to use a GelfHandler')
->end()
->end()
->validate()
->ifTrue(function($v) { return isset($v['debug']); })
->thenInvalid('The "debug" name cannot be used as it is reserved for the handler of the profiler')
->end()
->example(array(
'syslog' => array(
'type' => 'stream',
'path' => '/var/log/symfony.log',
'level' => 'ERROR',
'bubble' => 'false',
'formatter' => 'my_formatter',
'processors' => array('some_callable')
),
'main' => array(
'type' => 'fingers_crossed',
'action_level' => 'WARNING',
'buffer_size' => 30,
'handler' => 'custom',
),
'custom' => array(
'type' => 'service',
'id' => 'my_handler'
)
))
->end()
->end()
;
return $treeBuilder;
}
}

View File

@@ -0,0 +1,289 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bundle\MonologBundle\DependencyInjection;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
/**
* MonologExtension is an extension for the Monolog library.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @author Christophe Coevoet <stof@notk.org>
*/
class MonologExtension extends Extension
{
private $nestedHandlers = array();
/**
* Loads the Monolog configuration.
*
* @param array $configs An array of configuration settings
* @param ContainerBuilder $container A ContainerBuilder instance
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = $this->getConfiguration($configs, $container);
$config = $this->processConfiguration($configuration, $configs);
if (isset($config['handlers'])) {
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('monolog.xml');
$container->setAlias('logger', 'monolog.logger');
$handlers = array();
foreach ($config['handlers'] as $name => $handler) {
$handlers[] = array(
'id' => $this->buildHandler($container, $name, $handler),
'priority' => $handler['priority'],
'channels' => isset($handler['channels']) ? $handler['channels'] : null
);
}
$handlers = array_reverse($handlers);
uasort($handlers, function($a, $b) {
if ($a['priority'] == $b['priority']) {
return 0;
}
return $a['priority'] < $b['priority'] ? -1 : 1;
});
$handlersToChannels = array();
foreach ($handlers as $handler) {
if (!in_array($handler['id'], $this->nestedHandlers)) {
$handlersToChannels[$handler['id']] = $handler['channels'];
}
}
$container->setParameter('monolog.handlers_to_channels', $handlersToChannels);
$this->addClassesToCompile(array(
'Monolog\\Formatter\\FormatterInterface',
'Monolog\\Formatter\\LineFormatter',
'Monolog\\Handler\\HandlerInterface',
'Monolog\\Handler\\AbstractHandler',
'Monolog\\Handler\\AbstractProcessingHandler',
'Monolog\\Handler\\StreamHandler',
'Monolog\\Handler\\FingersCrossedHandler',
'Monolog\\Handler\\TestHandler',
'Monolog\\Logger',
'Symfony\\Bridge\\Monolog\\Logger',
'Symfony\\Bridge\\Monolog\\Handler\\DebugHandler',
));
}
}
/**
* Returns the base path for the XSD files.
*
* @return string The XSD base path
*/
public function getXsdValidationBasePath()
{
return __DIR__.'/../Resources/config/schema';
}
public function getNamespace()
{
return 'http://symfony.com/schema/dic/monolog';
}
private function buildHandler(ContainerBuilder $container, $name, array $handler)
{
$handlerId = $this->getHandlerId($name);
$definition = new Definition(sprintf('%%monolog.handler.%s.class%%', $handler['type']));
$handler['level'] = is_int($handler['level']) ? $handler['level'] : constant('Monolog\Logger::'.strtoupper($handler['level']));
switch ($handler['type']) {
case 'service':
$container->setAlias($handlerId, $handler['id']);
return $handlerId;
case 'stream':
$definition->setArguments(array(
$handler['path'],
$handler['level'],
$handler['bubble'],
));
break;
case 'firephp':
$definition->setArguments(array(
$handler['level'],
$handler['bubble'],
));
$definition->addTag('kernel.event_listener', array('event' => 'kernel.response', 'method' => 'onKernelResponse'));
break;
case 'gelf':
if (isset($handler['publisher']['id'])) {
$publisherId = $handler['publisher']['id'];
} else {
$publisher = new Definition("%monolog.gelf.publisher.class%", array(
$handler['publisher']['hostname'],
$handler['publisher']['port'],
$handler['publisher']['chunk_size'],
));
$publisherId = 'monolog.gelf.publisher';
$publisher->setPublic(false);
$container->setDefinition($publisherId, $publisher);
}
$definition->setArguments(array(
new Reference($publisherId),
$handler['level'],
$handler['bubble'],
));
break;
case 'chromephp':
$definition->setArguments(array(
$handler['level'],
$handler['bubble'],
));
$definition->addTag('kernel.event_listener', array('event' => 'kernel.response', 'method' => 'onKernelResponse'));
break;
case 'rotating_file':
$definition->setArguments(array(
$handler['path'],
$handler['max_files'],
$handler['level'],
$handler['bubble'],
));
break;
case 'fingers_crossed':
$handler['action_level'] = is_int($handler['action_level']) ? $handler['action_level'] : constant('Monolog\Logger::'.strtoupper($handler['action_level']));
$nestedHandlerId = $this->getHandlerId($handler['handler']);
$this->nestedHandlers[] = $nestedHandlerId;
if (isset($handler['activation_strategy'])) {
$activation = new Reference($handler['activation_strategy']);
} else {
$activation = $handler['action_level'];
}
$definition->setArguments(array(
new Reference($nestedHandlerId),
$activation,
$handler['buffer_size'],
$handler['bubble'],
$handler['stop_buffering'],
));
break;
case 'buffer':
$nestedHandlerId = $this->getHandlerId($handler['handler']);
$this->nestedHandlers[] = $nestedHandlerId;
$definition->setArguments(array(
new Reference($nestedHandlerId),
$handler['buffer_size'],
$handler['level'],
$handler['bubble'],
));
break;
case 'group':
$references = array();
foreach ($handler['members'] as $nestedHandler) {
$nestedHandlerId = $this->getHandlerId($nestedHandler);
$this->nestedHandlers[] = $nestedHandlerId;
$references[] = new Reference($nestedHandlerId);
}
$definition->setArguments(array(
$references,
$handler['bubble'],
));
break;
case 'syslog':
$definition->setArguments(array(
$handler['ident'],
$handler['facility'],
$handler['level'],
$handler['bubble'],
));
break;
case 'swift_mailer':
if (isset($handler['email_prototype'])) {
if (!empty($handler['email_prototype']['method'])) {
$prototype = array(new Reference($handler['email_prototype']['id']), $handler['email_prototype']['method']);
} else {
$prototype = new Reference($handler['email_prototype']['id']);
}
} else {
$message = new Definition('Swift_Message');
$message->setFactoryService('mailer');
$message->setFactoryMethod('createMessage');
$message->setPublic(false);
$message->addMethodCall('setFrom', array($handler['from_email']));
$message->addMethodCall('setTo', array($handler['to_email']));
$message->addMethodCall('setSubject', array($handler['subject']));
$messageId = sprintf('%s.mail_prototype', $handlerId);
$container->setDefinition($messageId, $message);
$prototype = new Reference($messageId);
}
$definition->setArguments(array(
new Reference('mailer'),
$prototype,
$handler['level'],
$handler['bubble'],
));
break;
case 'native_mailer':
$definition->setArguments(array(
$handler['to_email'],
$handler['subject'],
$handler['from_email'],
$handler['level'],
$handler['bubble'],
));
break;
// Handlers using the constructor of AbstractHandler without adding their own arguments
case 'test':
case 'null':
case 'debug':
$definition->setArguments(array(
$handler['level'],
$handler['bubble'],
));
break;
default:
throw new \InvalidArgumentException(sprintf('Invalid handler type "%s" given for handler "%s"', $handler['type'], $name));
}
if (!empty($handler['formatter'])) {
$definition->addMethodCall('setFormatter', array(new Reference($handler['formatter'])));
}
$container->setDefinition($handlerId, $definition);
return $handlerId;
}
private function getHandlerId($name)
{
return sprintf('monolog.handler.%s', $name);
}
}