diff options
Diffstat (limited to 'vendor/monolog')
50 files changed, 1400 insertions, 200 deletions
diff --git a/vendor/monolog/monolog/.php_cs b/vendor/monolog/monolog/.php_cs new file mode 100644 index 00000000..2511e98c --- /dev/null +++ b/vendor/monolog/monolog/.php_cs @@ -0,0 +1,15 @@ +<?php + +$finder = Symfony\CS\Finder\DefaultFinder::create() + ->files() + ->name('*.php') + ->in(__DIR__.'/src') + ->in(__DIR__.'/tests') +; + +return Symfony\CS\Config\Config::create() + ->fixers(array( + 'psr0', 'encoding', 'short_tag', 'braces', 'elseif', 'eof_ending', 'function_declaration', 'indentation', 'line_after_namespace', 'linefeed', 'lowercase_constants', 'lowercase_keywords', 'multiple_use', 'php_closing_tag', 'trailing_spaces', 'visibility', 'duplicate_semicolon', 'extra_empty_lines', 'include', 'namespace_no_leading_whitespace', 'object_operator', 'operators_spaces', 'phpdoc_params', 'return', 'single_array_no_trailing_comma', 'spaces_cast', 'standardize_not_equal', 'ternary_spaces', 'unused_use', 'whitespacy_lines', + )) + ->finder($finder) +; diff --git a/vendor/monolog/monolog/CHANGELOG.mdown b/vendor/monolog/monolog/CHANGELOG.mdown index 47042c73..41d072e1 100644 --- a/vendor/monolog/monolog/CHANGELOG.mdown +++ b/vendor/monolog/monolog/CHANGELOG.mdown @@ -1,3 +1,27 @@ +### 1.14.0 (2015-06-19) + + * Added PHPConsoleHandler to send record to Chrome's PHP Console extension and library + * Added support for objects implementing __toString in the NormalizerFormatter + * Added support for HipChat's v2 API in HipChatHandler + * Added Logger::setTimezone() to initialize the timezone monolog should use in case date.timezone isn't correct for your app + * Added an option to send formatted message instead of the raw record on PushoverHandler via ->useFormattedMessage(true) + * Fixed curl errors being silently suppressed + +### 1.13.1 (2015-03-09) + + * Fixed regression in HipChat requiring a new token to be created + +### 1.13.0 (2015-03-05) + + * Added Registry::hasLogger to check for the presence of a logger instance + * Added context.user support to RavenHandler + * Added HipChat API v2 support in the HipChatHandler + * Added NativeMailerHandler::addParameter to pass params to the mail() process + * Added context data to SlackHandler when $includeContextAndExtra is true + * Added ability to customize the Swift_Message per-email in SwiftMailerHandler + * Fixed SwiftMailerHandler to lazily create message instances if a callback is provided + * Fixed serialization of INF and NaN values in Normalizer and LineFormatter + ### 1.12.0 (2014-12-29) * Break: HandlerInterface::isHandling now receives a partial record containing only a level key. This was always the intent and does not break any Monolog handler but is strictly speaking a BC break and you should check if you relied on any other field in your own handlers. diff --git a/vendor/monolog/monolog/LICENSE b/vendor/monolog/monolog/LICENSE index 35727045..56e08d55 100644 --- a/vendor/monolog/monolog/LICENSE +++ b/vendor/monolog/monolog/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011-2014 Jordi Boggiano +Copyright (c) 2011-2015 Jordi Boggiano Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/monolog/monolog/README.mdown b/vendor/monolog/monolog/README.mdown index add476a8..af745c8a 100644 --- a/vendor/monolog/monolog/README.mdown +++ b/vendor/monolog/monolog/README.mdown @@ -17,11 +17,18 @@ make sure you can always use another compatible logger at a later time. As of 1.11.0 Monolog public APIs will also accept PSR-3 log levels. Internally Monolog still uses its own level scheme since it predates PSR-3. +Installation +------------ + +Install the latest version with + +```bash +$ composer require monolog/monolog +``` + Usage ----- -Install the latest version with `composer require monolog/monolog` - ```php <?php @@ -154,6 +161,8 @@ Handlers inline `console` messages within Chrome. - _BrowserConsoleHandler_: Handler to send logs to browser's Javascript `console` with no browser extension required. Most browsers supporting `console` API are supported. +- _PHPConsoleHandler_: Handler for [PHP Console](https://chrome.google.com/webstore/detail/php-console/nfhmhhlpfleoednkpnnnkolmclajemef), providing + inline `console` and notification popup messages within Chrome. ### Log to databases @@ -238,6 +247,13 @@ Utilities - _ChannelLevelActivationStrategy_: Activates a FingersCrossedHandler when a certain log level is reached, depending on which channel received the log record. +Third Party Packages +-------------------- + +Third party handlers, formatters and processors are +[listed in the wiki](https://github.com/Seldaek/monolog/wiki/Third-Party-Packages). You +can also add your own there if you publish one. + About ===== @@ -258,12 +274,15 @@ Frameworks Integration can be used very easily with Monolog since it implements the interface. - [Symfony2](http://symfony.com) comes out of the box with Monolog. - [Silex](http://silex.sensiolabs.org/) comes out of the box with Monolog. -- [Laravel 4](http://laravel.com/) comes out of the box with Monolog. +- [Laravel 4 & 5](http://laravel.com/) come out of the box with Monolog. +- [Lumen](http://lumen.laravel.com/) comes out of the box with Monolog. - [PPI](http://www.ppi.io/) comes out of the box with Monolog. - [CakePHP](http://cakephp.org/) is usable with Monolog via the [cakephp-monolog](https://github.com/jadb/cakephp-monolog) plugin. - [Slim](http://www.slimframework.com/) is usable with Monolog via the [Slim-Monolog](https://github.com/Flynsarmy/Slim-Monolog) log writer. - [XOOPS 2.6](http://xoops.org/) comes out of the box with Monolog. - [Aura.Web_Project](https://github.com/auraphp/Aura.Web_Project) comes out of the box with Monolog. +- [Nette Framework](http://nette.org/en/) can be used with Monolog via [Kdyby/Monolog](https://github.com/Kdyby/Monolog) extension. +- [Proton Micro Framework](https://github.com/alexbilbie/Proton) comes out of the box with Monolog. Author ------ diff --git a/vendor/monolog/monolog/composer.json b/vendor/monolog/monolog/composer.json index 43704236..239484b3 100644 --- a/vendor/monolog/monolog/composer.json +++ b/vendor/monolog/monolog/composer.json @@ -17,14 +17,18 @@ "psr/log": "~1.0" }, "require-dev": { - "phpunit/phpunit": "~4.0", + "phpunit/phpunit": "~4.5", "graylog2/gelf-php": "~1.0", - "raven/raven": "~0.5", - "ruflin/elastica": "0.90.*", + "raven/raven": "~0.8", + "ruflin/elastica": ">=0.90 <3.0", "doctrine/couchdb": "~1.0@dev", - "aws/aws-sdk-php": "~2.4, >2.4.8", - "videlalvaro/php-amqplib": "~2.4" + "aws/aws-sdk-php": "^2.4.9", + "videlalvaro/php-amqplib": "~2.4", + "swiftmailer/swiftmailer": "~5.3", + "php-console/php-console": "^3.1.3", + "phpunit/phpunit-mock-objects": "2.3.0" }, + "_": "phpunit/phpunit-mock-objects required in 2.3.0 due to https://github.com/sebastianbergmann/phpunit-mock-objects/issues/223", "suggest": { "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", "raven/raven": "Allow sending log messages to a Sentry server", @@ -34,17 +38,24 @@ "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", "ext-mongo": "Allow sending log messages to a MongoDB server", "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", - "rollbar/rollbar": "Allow sending log messages to Rollbar" + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "php-console/php-console": "Allow sending log messages to Google Chrome" }, "autoload": { "psr-4": {"Monolog\\": "src/Monolog"} }, + "autoload-dev": { + "psr-4": {"Monolog\\": "tests/Monolog"} + }, "provide": { "psr/log-implementation": "1.0.0" }, "extra": { "branch-alias": { - "dev-master": "1.12.x-dev" + "dev-master": "1.14.x-dev" } + }, + "scripts": { + "test": "phpunit" } } diff --git a/vendor/monolog/monolog/phpunit.xml.dist b/vendor/monolog/monolog/phpunit.xml.dist index 17545707..20d82b63 100644 --- a/vendor/monolog/monolog/phpunit.xml.dist +++ b/vendor/monolog/monolog/phpunit.xml.dist @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<phpunit bootstrap="tests/bootstrap.php" colors="true"> +<phpunit bootstrap="vendor/autoload.php" colors="true"> <testsuites> <testsuite name="Monolog Test Suite"> <directory>tests/Monolog/</directory> @@ -12,4 +12,8 @@ <directory suffix=".php">src/Monolog/</directory> </whitelist> </filter> + + <php> + <ini name="date.timezone" value="UTC"/> + </php> </phpunit> diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php index 8d01c64c..1e431750 100644 --- a/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php +++ b/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php @@ -67,19 +67,29 @@ class GelfMessageFormatter extends NormalizerFormatter public function format(array $record) { $record = parent::format($record); + + if (!isset($record['datetime'], $record['message'], $record['level'])) { + throw new \InvalidArgumentException('The record should at least contain datetime, message and level keys, '.var_export($record, true).' given'); + } + $message = new Message(); $message ->setTimestamp($record['datetime']) ->setShortMessage((string) $record['message']) - ->setFacility($record['channel']) ->setHost($this->systemName) - ->setLine(isset($record['extra']['line']) ? $record['extra']['line'] : null) - ->setFile(isset($record['extra']['file']) ? $record['extra']['file'] : null) ->setLevel($this->logLevels[$record['level']]); - // Do not duplicate these values in the additional fields - unset($record['extra']['line']); - unset($record['extra']['file']); + if (isset($record['channel'])) { + $message->setFacility($record['channel']); + } + if (isset($record['extra']['line'])) { + $message->setLine($record['extra']['line']); + unset($record['extra']['line']); + } + if (isset($record['extra']['file'])) { + $message->setFile($record['extra']['file']); + unset($record['extra']['file']); + } foreach ($record['extra'] as $key => $val) { $message->setAdditional($this->extraPrefix . $key, is_scalar($val) ? $val : $this->toJson($val)); diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php index 7963dbf1..e5a1d2c4 100644 --- a/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php +++ b/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php @@ -39,7 +39,7 @@ class JsonFormatter implements FormatterInterface * The batch mode option configures the formatting style for * multiple records. By default, multiple records will be * formatted as a JSON-encoded array. However, for - * compatibility with some API endpoints, alternive styles + * compatibility with some API endpoints, alternative styles * are available. * * @return int diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php index 6983d1a5..388e2266 100644 --- a/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php +++ b/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php @@ -154,6 +154,6 @@ class LineFormatter extends NormalizerFormatter return $str; } - return strtr($str, array("\r\n" => ' ', "\r" => ' ', "\n" => ' ')); + return str_replace(array("\r\n", "\r", "\n"), ' ', $str); } } diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php index beafea64..46bf41b3 100644 --- a/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php +++ b/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php @@ -58,6 +58,15 @@ class NormalizerFormatter implements FormatterInterface protected function normalize($data) { if (null === $data || is_scalar($data)) { + if (is_float($data)) { + if (is_infinite($data)) { + return ($data > 0 ? '' : '-') . 'INF'; + } + if (is_nan($data)) { + return 'NaN'; + } + } + return $data; } @@ -85,7 +94,15 @@ class NormalizerFormatter implements FormatterInterface return $this->normalizeException($data); } - return sprintf("[object] (%s: %s)", get_class($data), $this->toJson($data, true)); + // non-serializable objects that implement __toString stringified + if (method_exists($data, '__toString') && !$data instanceof \JsonSerializable) { + $value = (string) $data; + } else { + // the rest is json-serialized in some way + $value = $this->toJson($data, true); + } + + return sprintf("[object] (%s: %s)", get_class($data), $value); } if (is_resource($data)) { diff --git a/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php index 43190b92..589ff779 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php @@ -26,7 +26,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler /** * {@inheritDoc} * - * Formatted output may contain some formatting markers to be transfered to `console.log` using the %c format. + * Formatted output may contain some formatting markers to be transferred to `console.log` using the %c format. * * Example of formatted string: * @@ -71,7 +71,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler } if (count(self::$records)) { - echo '<script>' . self::generateScript() . '</script>'; + echo '<script>' , self::generateScript() , '</script>'; self::reset(); } } diff --git a/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php index d968720c..db8e6552 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php @@ -116,7 +116,11 @@ class CubeHandler extends AbstractProcessingHandler $data['data'] = $record['context']; $data['data']['level'] = $record['level']; - $this->{'write'.$this->scheme}(json_encode($data)); + if ($this->scheme === 'http') { + $this->writeHttp(json_encode($data)); + } else { + $this->writeUdp(json_encode($data)); + } } private function writeUdp($data) @@ -140,6 +144,8 @@ class CubeHandler extends AbstractProcessingHandler 'Content-Length: ' . strlen('['.$data.']')) ); - return curl_exec($this->httpConnection); + if (curl_exec($this->httpConnection) === false) { + throw new \RuntimeException(sprintf('Curl error (code %s): %s', curl_errno($ch), curl_error($ch))); + } } } diff --git a/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php index a81c9e64..30a85dd6 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php @@ -61,7 +61,10 @@ class FingersCrossedHandler extends AbstractHandler $this->bufferSize = $bufferSize; $this->bubble = $bubble; $this->stopBuffering = $stopBuffering; - $this->passthruLevel = $passthruLevel; + + if ($passthruLevel !== null) { + $this->passthruLevel = Logger::toMonologLevel($passthruLevel); + } if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); diff --git a/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php index 790f6364..28c7b55f 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php @@ -13,6 +13,7 @@ namespace Monolog\Handler; use Gelf\IMessagePublisher; use Gelf\PublisherInterface; +use Gelf\Publisher; use InvalidArgumentException; use Monolog\Logger; use Monolog\Formatter\GelfMessageFormatter; @@ -31,16 +32,16 @@ class GelfHandler extends AbstractProcessingHandler protected $publisher; /** - * @param PublisherInterface|IMessagePublisher $publisher a publisher object - * @param integer $level The minimum logging level at which this handler will be triggered - * @param boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param PublisherInterface|IMessagePublisher|Publisher $publisher a publisher object + * @param integer $level The minimum logging level at which this handler will be triggered + * @param boolean $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct($publisher, $level = Logger::DEBUG, $bubble = true) { parent::__construct($level, $bubble); - if (!$publisher instanceof IMessagePublisher && !$publisher instanceof PublisherInterface) { - throw new InvalidArgumentException("Invalid publisher, expected a Gelf\IMessagePublisher or Gelf\PublisherInterface instance"); + if (!$publisher instanceof Publisher && !$publisher instanceof IMessagePublisher && !$publisher instanceof PublisherInterface) { + throw new InvalidArgumentException("Invalid publisher, expected a Gelf\Publisher, Gelf\IMessagePublisher or Gelf\PublisherInterface instance"); } $this->publisher = $publisher; diff --git a/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php index 29614d31..34d3437f 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php @@ -21,6 +21,7 @@ use Monolog\Logger; * Room - HipChat Room Id or name, where messages are sent * Name - Name used to send the message (from) * notify - Should the message trigger a notification in the clients + * version - The API version to use (HipChatHandler::API_V1 | HipChatHandler::API_V2) * * @author Rafael Dohms <rafael@doh.ms> * @see https://www.hipchat.com/docs/api @@ -28,6 +29,16 @@ use Monolog\Logger; class HipChatHandler extends SocketHandler { /** + * Use API version 1 + */ + const API_V1 = 'v1'; + + /** + * Use API version v2 + */ + const API_V2 = 'v2'; + + /** * The maximum allowed length for the name used in the "from" field. */ const MAXIMUM_NAME_LENGTH = 15; @@ -43,7 +54,7 @@ class HipChatHandler extends SocketHandler private $token; /** - * @var array + * @var string */ private $room; @@ -53,7 +64,7 @@ class HipChatHandler extends SocketHandler private $name; /** - * @var boolean + * @var bool */ private $notify; @@ -63,19 +74,30 @@ class HipChatHandler extends SocketHandler private $format; /** - * @param string $token HipChat API Token - * @param string $room The room that should be alerted of the message (Id or Name) - * @param string $name Name used in the "from" field - * @param bool $notify Trigger a notification in clients or not - * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not - * @param Boolean $useSSL Whether to connect via SSL. - * @param string $format The format of the messages (default to text, can be set to html if you have html in the messages) - * @param string $host The HipChat server hostname. + * @var string */ - public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $format = 'text', $host = 'api.hipchat.com') + private $host; + + /** + * @var string + */ + private $version; + + /** + * @param string $token HipChat API Token + * @param string $room The room that should be alerted of the message (Id or Name) + * @param string $name Name used in the "from" field. Not used for v2 + * @param bool $notify Trigger a notification in clients or not + * @param int $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @param bool $useSSL Whether to connect via SSL. + * @param string $format The format of the messages (default to text, can be set to html if you have html in the messages) + * @param string $host The HipChat server hostname. + * @param string $version The HipChat API version (default HipChatHandler::API_V1) + */ + public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $format = 'text', $host = 'api.hipchat.com', $version = self::API_V1) { - if (!$this->validateStringLength($name, static::MAXIMUM_NAME_LENGTH)) { + if ($version == self::API_V1 && !$this->validateStringLength($name, static::MAXIMUM_NAME_LENGTH)) { throw new \InvalidArgumentException('The supplied name is too long. HipChat\'s v1 API supports names up to 15 UTF-8 characters.'); } @@ -87,6 +109,8 @@ class HipChatHandler extends SocketHandler $this->notify = $notify; $this->room = $room; $this->format = $format; + $this->host = $host; + $this->version = $version; } /** @@ -111,14 +135,20 @@ class HipChatHandler extends SocketHandler private function buildContent($record) { $dataArray = array( - 'from' => $this->name, - 'room_id' => $this->room, - 'notify' => $this->notify, + 'notify' => $this->version == self::API_V1 ? + ($this->notify ? 1 : 0) : + ($this->notify ? 'true' : 'false'), 'message' => $record['formatted'], 'message_format' => $this->format, 'color' => $this->getAlertColor($record['level']), ); + // if we are using the legacy API then we need to send some additional information + if ($this->version == self::API_V1) { + $dataArray['room_id'] = $this->room; + $dataArray['from'] = $this->name; + } + return http_build_query($dataArray); } @@ -130,8 +160,15 @@ class HipChatHandler extends SocketHandler */ private function buildHeader($content) { - $header = "POST /v1/rooms/message?format=json&auth_token=".$this->token." HTTP/1.1\r\n"; - $header .= "Host: api.hipchat.com\r\n"; + if ($this->version == self::API_V1) { + $header = "POST /v1/rooms/message?format=json&auth_token={$this->token} HTTP/1.1\r\n"; + } else { + // needed for rooms with special (spaces, etc) characters in the name + $room = rawurlencode($this->room); + $header = "POST /v2/room/{$room}/notification?auth_token={$this->token} HTTP/1.1\r\n"; + } + + $header .= "Host: {$this->host}\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($content) . "\r\n"; $header .= "\r\n"; @@ -229,19 +266,19 @@ class HipChatHandler extends SocketHandler } $messages[] = $record['message']; - $messgeStr = implode(PHP_EOL, $messages); + $messageStr = implode(PHP_EOL, $messages); $formattedMessages[] = $this->getFormatter()->format($record); $formattedMessageStr = implode('', $formattedMessages); $batchRecord = array( - 'message' => $messgeStr, + 'message' => $messageStr, 'formatted' => $formattedMessageStr, 'context' => array(), 'extra' => array(), ); if (!$this->validateStringLength($batchRecord['formatted'], static::MAXIMUM_MESSAGE_LENGTH)) { - // Pop the last message and implode the remainging messages + // Pop the last message and implode the remaining messages $lastMessage = array_pop($messages); $lastFormattedMessage = array_pop($formattedMessages); $batchRecord['message'] = implode(PHP_EOL, $messages); diff --git a/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php index 8bf388b3..bd56230f 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php @@ -29,7 +29,7 @@ class LogEntriesHandler extends SocketHandler * @param int $level The minimum logging level to trigger this handler * @param boolean $bubble Whether or not messages that are handled should bubble up the stack. * - * @throws MissingExtensionExcpetion If SSL encryption is set to true and OpenSSL is missing + * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing */ public function __construct($token, $useSSL = true, $level = Logger::DEBUG, $bubble = true) { @@ -37,7 +37,7 @@ class LogEntriesHandler extends SocketHandler throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler'); } - $endpoint = $useSSL ? 'ssl://api.logentries.com:20000' : 'data.logentries.com:80'; + $endpoint = $useSSL ? 'ssl://data.logentries.com:443' : 'data.logentries.com:80'; parent::__construct($endpoint, $level, $bubble); $this->logToken = $token; } diff --git a/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php index efd94d30..9785cec0 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php @@ -19,6 +19,7 @@ use Monolog\Formatter\LogglyFormatter; * * @author Przemek Sobstel <przemek@sobstel.org> * @author Adam Pancutt <adam@pancutt.com> + * @author Gregory Barchard <gregory@barchard.net> */ class LogglyHandler extends AbstractProcessingHandler { @@ -28,7 +29,7 @@ class LogglyHandler extends AbstractProcessingHandler protected $token; - protected $tag; + protected $tag = array(); public function __construct($token, $level = Logger::DEBUG, $bubble = true) { @@ -43,12 +44,16 @@ class LogglyHandler extends AbstractProcessingHandler public function setTag($tag) { - $this->tag = $tag; + $tag = !empty($tag) ? $tag : array(); + $this->tag = is_array($tag) ? $tag : array($tag); } public function addTag($tag) { - $this->tag = (strlen($this->tag) > 0) ? $this->tag .','. $tag : $tag; + if (!empty($tag)) { + $tag = is_array($tag) ? $tag : array($tag); + $this->tag = array_unique(array_merge($this->tag, $tag)); + } } protected function write(array $record) @@ -75,8 +80,8 @@ class LogglyHandler extends AbstractProcessingHandler $headers = array('Content-Type: application/json'); - if ($this->tag) { - $headers[] = "X-LOGGLY-TAG: {$this->tag}"; + if (!empty($this->tag)) { + $headers[] = 'X-LOGGLY-TAG: '.implode(',', $this->tag); } $ch = curl_init(); @@ -87,7 +92,10 @@ class LogglyHandler extends AbstractProcessingHandler curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_exec($ch); + if (curl_exec($ch) === false) { + throw new \RuntimeException(sprintf('Curl error (code %s): %s', curl_errno($ch), curl_error($ch))); + } + curl_close($ch); } diff --git a/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php index 86292727..50ed6380 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php @@ -40,7 +40,7 @@ abstract class MailHandler extends AbstractProcessingHandler /** * Send a mail with the given content * - * @param string $content + * @param string $content formatted email body to be sent * @param array $records the array of log records that formed this content */ abstract protected function send($content, array $records); diff --git a/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php index 60a2901e..6726e1e4 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php @@ -63,7 +63,9 @@ class MandrillHandler extends MailHandler 'async' => false, ))); - curl_exec($ch); + if (curl_exec($ch) === false) { + throw new \RuntimeException(sprintf('Curl error (code %s): %s', curl_errno($ch), curl_error($ch))); + } curl_close($ch); } } diff --git a/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php index 0fe6b642..5118a0e2 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php @@ -40,6 +40,12 @@ class NativeMailerHandler extends MailHandler protected $headers = array(); /** + * Optional parameters for the message + * @var array + */ + protected $parameters = array(); + + /** * The wordwrap length for the message * @var integer */ @@ -78,7 +84,7 @@ class NativeMailerHandler extends MailHandler * Add headers to the message * * @param string|array $headers Custom added headers - * @return null + * @return self */ public function addHeader($headers) { @@ -88,6 +94,21 @@ class NativeMailerHandler extends MailHandler } $this->headers[] = $header; } + + return $this; + } + + /** + * Add parameters to the message + * + * @param string|array $parameters Custom added parameters + * @return self + */ + public function addParameter($parameters) + { + $this->parameters = array_merge($this->parameters, (array) $parameters); + + return $this; } /** @@ -102,7 +123,7 @@ class NativeMailerHandler extends MailHandler $headers .= 'MIME-Version: 1.0' . "\r\n"; } foreach ($this->to as $to) { - mail($to, $this->subject, $content, $headers); + mail($to, $this->subject, $content, $headers, implode(' ', $this->parameters)); } } @@ -145,7 +166,7 @@ class NativeMailerHandler extends MailHandler public function setEncoding($encoding) { if (strpos($encoding, "\n") !== false || strpos($encoding, "\r") !== false) { - throw new \InvalidArgumentException('The content type can not contain newline characters to prevent email header injection'); + throw new \InvalidArgumentException('The encoding can not contain newline characters to prevent email header injection'); } $this->encoding = $encoding; diff --git a/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php index 9807410d..8cb4ab38 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php @@ -12,11 +12,14 @@ namespace Monolog\Handler; use Monolog\Logger; +use Monolog\Formatter\NormalizerFormatter; /** - * Class to record a log on a NewRelic application + * Class to record a log on a NewRelic application. + * Enabling New Relic High Security mode may prevent capture of useful information. * * @see https://docs.newrelic.com/docs/agents/php-agent + * @see https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security */ class NewRelicHandler extends AbstractProcessingHandler { @@ -78,33 +81,33 @@ class NewRelicHandler extends AbstractProcessingHandler if ($transactionName = $this->getTransactionName($record['context'])) { $this->setNewRelicTransactionName($transactionName); - unset($record['context']['transaction_name']); + unset($record['formatted']['context']['transaction_name']); } if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) { newrelic_notice_error($record['message'], $record['context']['exception']); - unset($record['context']['exception']); + unset($record['formatted']['context']['exception']); } else { newrelic_notice_error($record['message']); } - foreach ($record['context'] as $key => $parameter) { + foreach ($record['formatted']['context'] as $key => $parameter) { if (is_array($parameter) && $this->explodeArrays) { foreach ($parameter as $paramKey => $paramValue) { - newrelic_add_custom_parameter('context_' . $key . '_' . $paramKey, $paramValue); + $this->setNewRelicParameter('context_' . $key . '_' . $paramKey, $paramValue); } } else { - newrelic_add_custom_parameter('context_' . $key, $parameter); + $this->setNewRelicParameter('context_' . $key, $parameter); } } - foreach ($record['extra'] as $key => $parameter) { + foreach ($record['formatted']['extra'] as $key => $parameter) { if (is_array($parameter) && $this->explodeArrays) { foreach ($parameter as $paramKey => $paramValue) { - newrelic_add_custom_parameter('extra_' . $key . '_' . $paramKey, $paramValue); + $this->setNewRelicParameter('extra_' . $key . '_' . $paramKey, $paramValue); } } else { - newrelic_add_custom_parameter('extra_' . $key, $parameter); + $this->setNewRelicParameter('extra_' . $key, $parameter); } } } @@ -165,10 +168,31 @@ class NewRelicHandler extends AbstractProcessingHandler /** * Overwrites the name of the current transaction * - * @param $transactionName + * @param string $transactionName */ protected function setNewRelicTransactionName($transactionName) { newrelic_name_transaction($transactionName); } + + /** + * @param string $key + * @param mixed $value + */ + protected function setNewRelicParameter($key, $value) + { + if (null === $value || is_scalar($value)) { + newrelic_add_custom_parameter($key, $value); + } else { + newrelic_add_custom_parameter($key, @json_encode($value)); + } + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new NormalizerFormatter(); + } } diff --git a/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php new file mode 100644 index 00000000..169bea0e --- /dev/null +++ b/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php @@ -0,0 +1,243 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Exception; +use Monolog\Formatter\LineFormatter; +use Monolog\Logger; +use PhpConsole\Connector; +use PhpConsole\Handler; +use PhpConsole\Helper; + +/** + * Monolog handler for Google Chrome extension "PHP Console" + * + * Display PHP error/debug log messages in Google Chrome console and notification popups, executes PHP code remotely + * + * Usage: + * 1. Install Google Chrome extension https://chrome.google.com/webstore/detail/php-console/nfhmhhlpfleoednkpnnnkolmclajemef + * 2. See overview https://github.com/barbushin/php-console#overview + * 3. Install PHP Console library https://github.com/barbushin/php-console#installation + * 4. Example (result will looks like http://i.hizliresim.com/vg3Pz4.png) + * + * $logger = new \Monolog\Logger('all', array(new \Monolog\Handler\PHPConsoleHandler())); + * \Monolog\ErrorHandler::register($logger); + * echo $undefinedVar; + * $logger->addDebug('SELECT * FROM users', array('db', 'time' => 0.012)); + * PC::debug($_SERVER); // PHP Console debugger for any type of vars + * + * @author Sergey Barbushin https://www.linkedin.com/in/barbushin + */ +class PHPConsoleHandler extends AbstractProcessingHandler +{ + private $options = array( + 'enabled' => true, // bool Is PHP Console server enabled + 'classesPartialsTraceIgnore' => array('Monolog\\'), // array Hide calls of classes started with... + 'debugTagsKeysInContext' => array(0, 'tag'), // bool Is PHP Console server enabled + 'useOwnErrorsHandler' => false, // bool Enable errors handling + 'useOwnExceptionsHandler' => false, // bool Enable exceptions handling + 'sourcesBasePath' => null, // string Base path of all project sources to strip in errors source paths + 'registerHelper' => true, // bool Register PhpConsole\Helper that allows short debug calls like PC::debug($var, 'ta.g.s') + 'serverEncoding' => null, // string|null Server internal encoding + 'headersLimit' => null, // int|null Set headers size limit for your web-server + 'password' => null, // string|null Protect PHP Console connection by password + 'enableSslOnlyMode' => false, // bool Force connection by SSL for clients with PHP Console installed + 'ipMasks' => array(), // array Set IP masks of clients that will be allowed to connect to PHP Console: array('192.168.*.*', '127.0.0.1') + 'enableEvalListener' => false, // bool Enable eval request to be handled by eval dispatcher(if enabled, 'password' option is also required) + 'dumperDetectCallbacks' => false, // bool Convert callback items in dumper vars to (callback SomeClass::someMethod) strings + 'dumperLevelLimit' => 5, // int Maximum dumped vars array or object nested dump level + 'dumperItemsCountLimit' => 100, // int Maximum dumped var same level array items or object properties number + 'dumperItemSizeLimit' => 5000, // int Maximum length of any string or dumped array item + 'dumperDumpSizeLimit' => 500000, // int Maximum approximate size of dumped vars result formatted in JSON + 'detectDumpTraceAndSource' => false, // bool Autodetect and append trace data to debug + 'dataStorage' => null, // PhpConsole\Storage|null Fixes problem with custom $_SESSION handler(see http://goo.gl/Ne8juJ) + ); + + /** @var Connector */ + private $connector; + + /** + * @param array $options See \Monolog\Handler\PHPConsoleHandler::$options for more details + * @param Connector|null $connector Instance of \PhpConsole\Connector class (optional) + * @param int $level + * @param bool $bubble + * @throws Exception + */ + public function __construct(array $options = array(), Connector $connector = null, $level = Logger::DEBUG, $bubble = true) + { + if (!class_exists('PhpConsole\Connector')) { + throw new Exception('PHP Console library not found. See https://github.com/barbushin/php-console#installation'); + } + parent::__construct($level, $bubble); + $this->options = $this->initOptions($options); + $this->connector = $this->initConnector($connector); + } + + private function initOptions(array $options) + { + $wrongOptions = array_diff(array_keys($options), array_keys($this->options)); + if ($wrongOptions) { + throw new Exception('Unknown options: ' . implode(', ', $wrongOptions)); + } + + return array_replace($this->options, $options); + } + + private function initConnector(Connector $connector = null) + { + if (!$connector) { + if ($this->options['dataStorage']) { + Connector::setPostponeStorage($this->options['dataStorage']); + } + $connector = Connector::getInstance(); + } + + if ($this->options['registerHelper'] && !Helper::isRegistered()) { + Helper::register(); + } + + if ($this->options['enabled'] && $connector->isActiveClient()) { + if ($this->options['useOwnErrorsHandler'] || $this->options['useOwnExceptionsHandler']) { + $handler = Handler::getInstance(); + $handler->setHandleErrors($this->options['useOwnErrorsHandler']); + $handler->setHandleExceptions($this->options['useOwnExceptionsHandler']); + $handler->start(); + } + if ($this->options['sourcesBasePath']) { + $connector->setSourcesBasePath($this->options['sourcesBasePath']); + } + if ($this->options['serverEncoding']) { + $connector->setServerEncoding($this->options['serverEncoding']); + } + if ($this->options['password']) { + $connector->setPassword($this->options['password']); + } + if ($this->options['enableSslOnlyMode']) { + $connector->enableSslOnlyMode(); + } + if ($this->options['ipMasks']) { + $connector->setAllowedIpMasks($this->options['ipMasks']); + } + if ($this->options['headersLimit']) { + $connector->setHeadersLimit($this->options['headersLimit']); + } + if ($this->options['detectDumpTraceAndSource']) { + $connector->getDebugDispatcher()->detectTraceAndSource = true; + } + $dumper = $connector->getDumper(); + $dumper->levelLimit = $this->options['dumperLevelLimit']; + $dumper->itemsCountLimit = $this->options['dumperItemsCountLimit']; + $dumper->itemSizeLimit = $this->options['dumperItemSizeLimit']; + $dumper->dumpSizeLimit = $this->options['dumperDumpSizeLimit']; + $dumper->detectCallbacks = $this->options['dumperDetectCallbacks']; + if ($this->options['enableEvalListener']) { + $connector->startEvalRequestsListener(); + } + } + + return $connector; + } + + public function getConnector() + { + return $this->connector; + } + + public function getOptions() + { + return $this->options; + } + + public function handle(array $record) + { + if ($this->options['enabled'] && $this->connector->isActiveClient()) { + return parent::handle($record); + } + + return !$this->bubble; + } + + /** + * Writes the record down to the log of the implementing handler + * + * @param array $record + * @return void + */ + protected function write(array $record) + { + if ($record['level'] < Logger::NOTICE) { + $this->handleDebugRecord($record); + } elseif (isset($record['context']['exception']) && $record['context']['exception'] instanceof Exception) { + $this->handleExceptionRecord($record); + } else { + $this->handleErrorRecord($record); + } + } + + private function handleDebugRecord(array $record) + { + $tags = $this->getRecordTags($record); + $message = $record['message']; + if ($record['context']) { + $message .= ' ' . json_encode($this->connector->getDumper()->dump(array_filter($record['context']))); + } + $this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']); + } + + private function handleExceptionRecord(array $record) + { + $this->connector->getErrorsDispatcher()->dispatchException($record['context']['exception']); + } + + private function handleErrorRecord(array $record) + { + $context = $record['context']; + + $this->connector->getErrorsDispatcher()->dispatchError( + isset($context['code']) ? $context['code'] : null, + isset($context['message']) ? $context['message'] : $record['message'], + isset($context['file']) ? $context['file'] : null, + isset($context['line']) ? $context['line'] : null, + $this->options['classesPartialsTraceIgnore'] + ); + } + + private function getRecordTags(array &$record) + { + $tags = null; + if (!empty($record['context'])) { + $context =& $record['context']; + foreach ($this->options['debugTagsKeysInContext'] as $key) { + if (!empty($context[$key])) { + $tags = $context[$key]; + if ($key === 0) { + array_shift($context); + } else { + unset($context[$key]); + } + break; + } + } + } + + return $tags ?: strtolower($record['level_name']); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new LineFormatter('%message%'); + } +} + diff --git a/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php index cd2fcfa3..9917b649 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php @@ -30,6 +30,7 @@ class PushoverHandler extends SocketHandler private $highPriorityLevel; private $emergencyLevel; + private $useFormattedMessage = false; /** * All parameters that can be sent to Pushover @@ -103,7 +104,10 @@ class PushoverHandler extends SocketHandler { // Pushover has a limit of 512 characters on title and message combined. $maxMessageLength = 512 - strlen($this->title); - $message = substr($record['message'], 0, $maxMessageLength); + + $message = ($this->useFormattedMessage) ? $record['formatted'] : $record['message']; + $message = substr($message, 0, $maxMessageLength); + $timestamp = $record['datetime']->getTimestamp(); $dataArray = array( @@ -169,4 +173,13 @@ class PushoverHandler extends SocketHandler { $this->emergencyLevel = $value; } + + /** + * Use the formatted message? + * @param boolean $value + */ + public function useFormattedMessage($value) + { + $this->useFormattedMessage = (boolean) $value; + } } diff --git a/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php index f5743cd6..7fedc16f 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php @@ -127,6 +127,7 @@ class RavenHandler extends AbstractProcessingHandler */ protected function write(array $record) { + $previousUserContext = false; $options = array(); $options['level'] = $this->logLevels[$record['level']]; $options['tags'] = array(); @@ -146,6 +147,11 @@ class RavenHandler extends AbstractProcessingHandler } if (!empty($record['context'])) { $options['extra']['context'] = $record['context']; + if (!empty($record['context']['user'])) { + $previousUserContext = $this->ravenClient->context->user; + $this->ravenClient->user_context($record['context']['user']); + unset($options['extra']['context']['user']); + } } if (!empty($record['extra'])) { $options['extra']['extra'] = $record['extra']; @@ -154,11 +160,14 @@ class RavenHandler extends AbstractProcessingHandler if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) { $options['extra']['message'] = $record['formatted']; $this->ravenClient->captureException($record['context']['exception'], $options); + } else { + $this->ravenClient->captureMessage($record['formatted'], array(), $options); + } - return; + if ($previousUserContext !== false) { + $this->ravenClient->user_context($previousUserContext); } - $this->ravenClient->captureMessage($record['formatted'], array(), $options); } /** diff --git a/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php index 3fc7f34b..ee8c2363 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php @@ -11,8 +11,8 @@ namespace Monolog\Handler; -use Monolog\Logger; use Monolog\Formatter\LineFormatter; +use Monolog\Logger; /** * Logs to a Redis key using rpush @@ -30,7 +30,12 @@ class RedisHandler extends AbstractProcessingHandler private $redisClient; private $redisKey; - # redis instance, key to use + /** + * @param \Predis\Client|\Redis $redis The redis instance + * @param string $key The key name to push records to + * @param integer $level The minimum logging level at which this handler will be triggered + * @param boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ public function __construct($redis, $key, $level = Logger::DEBUG, $bubble = true) { if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) { diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php index 487e26f6..9509ae37 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php @@ -11,7 +11,6 @@ namespace Monolog\Handler; - /** * Sampling handler * diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php index e3c8e11b..c7a1c7e9 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php @@ -53,16 +53,16 @@ class SlackHandler extends SocketHandler private $useAttachment; /** - * Whether the the message that is added to Slack as attachment is in a short style (or not) + * Whether the the context/extra messages added to Slack as attachments are in a short style * @var bool */ private $useShortAttachment; /** - * Whether the attachment should include extra data (or not) + * Whether the attachment should include context and extra data * @var bool */ - private $includeExtra; + private $includeContextAndExtra; /** * @var LineFormatter @@ -70,15 +70,17 @@ class SlackHandler extends SocketHandler private $lineFormatter; /** - * @param string $token Slack API token - * @param string $channel Slack channel (encoded ID or name) - * @param string $username Name of a bot - * @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise) - * @param string|null $iconEmoji The emoji name to use (or null) - * @param int $level The minimum logging level at which this handler will be triggered - * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @param string $token Slack API token + * @param string $channel Slack channel (encoded ID or name) + * @param string $username Name of a bot + * @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise) + * @param string|null $iconEmoji The emoji name to use (or null) + * @param int $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @param bool $useShortAttachment Whether the the context/extra messages added to Slack as attachments are in a short style + * @param bool $includeContextAndExtra Whether the attachment should include context and extra data */ - public function __construct($token, $channel, $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $level = Logger::CRITICAL, $bubble = true, $useShortAttachment = false, $includeExtra = false) + public function __construct($token, $channel, $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $level = Logger::CRITICAL, $bubble = true, $useShortAttachment = false, $includeContextAndExtra = false) { if (!extension_loaded('openssl')) { throw new MissingExtensionException('The OpenSSL PHP extension is required to use the SlackHandler'); @@ -92,8 +94,8 @@ class SlackHandler extends SocketHandler $this->iconEmoji = trim($iconEmoji, ':'); $this->useAttachment = $useAttachment; $this->useShortAttachment = $useShortAttachment; - $this->includeExtra = $includeExtra; - if ($this->includeExtra) { + $this->includeContextAndExtra = $includeContextAndExtra; + if ($this->includeContextAndExtra) { $this->lineFormatter = new LineFormatter; } } @@ -119,18 +121,31 @@ class SlackHandler extends SocketHandler */ private function buildContent($record) { + $dataArray = $this->prepareContentData($record); + + return http_build_query($dataArray); + } + + /** + * Prepares content data + * + * @param array $record + * @return array + */ + protected function prepareContentData($record) + { $dataArray = array( - 'token' => $this->token, - 'channel' => $this->channel, - 'username' => $this->username, - 'text' => '', + 'token' => $this->token, + 'channel' => $this->channel, + 'username' => $this->username, + 'text' => '', 'attachments' => array() ); if ($this->useAttachment) { $attachment = array( 'fallback' => $record['message'], - 'color' => $this->getAttachmentColor($record['level']) + 'color' => $this->getAttachmentColor($record['level']) ); if ($this->useShortAttachment) { @@ -156,19 +171,44 @@ class SlackHandler extends SocketHandler ); } - if ($this->includeExtra) { - $extra = ''; - foreach ($record['extra'] as $var => $val) { - $extra .= $var.': '.$this->lineFormatter->stringify($val)." | "; + if ($this->includeContextAndExtra) { + if (!empty($record['extra'])) { + if ($this->useShortAttachment) { + $attachment['fields'][] = array( + 'title' => "Extra", + 'value' => $this->stringify($record['extra']), + 'short' => $this->useShortAttachment + ); + } else { + // Add all extra fields as individual fields in attachment + foreach ($record['extra'] as $var => $val) { + $attachment['fields'][] = array( + 'title' => $var, + 'value' => $val, + 'short' => $this->useShortAttachment + ); + } + } } - $extra = rtrim($extra, " |"); - - $attachment['fields'][] = array( - 'title' => "Extra", - 'value' => $extra, - 'short' => false - ); + if (!empty($record['context'])) { + if ($this->useShortAttachment) { + $attachment['fields'][] = array( + 'title' => "Context", + 'value' => $this->stringify($record['context']), + 'short' => $this->useShortAttachment + ); + } else { + // Add all context fields as individual fields in attachment + foreach ($record['context'] as $var => $val) { + $attachment['fields'][] = array( + 'title' => $var, + 'value' => $val, + 'short' => $this->useShortAttachment + ); + } + } + } } $dataArray['attachments'] = json_encode(array($attachment)); @@ -179,8 +219,7 @@ class SlackHandler extends SocketHandler if ($this->iconEmoji) { $dataArray['icon_emoji'] = ":{$this->iconEmoji}:"; } - - return http_build_query($dataArray); + return $dataArray; } /** @@ -231,4 +270,23 @@ class SlackHandler extends SocketHandler return '#e3e4e6'; } } + + /** + * Stringifies an array of key/value pairs to be used in attachment fields + * + * @param array $fields + * @access protected + * @return string + */ + protected function stringify($fields) + { + $string = ''; + foreach ($fields as $var => $val) { + $string .= $var.': '.$this->lineFormatter->stringify($val)." | "; + } + + $string = rtrim($string, " |"); + + return $string; + } } diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php index af321db2..003a1a2a 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php @@ -21,7 +21,7 @@ use Monolog\Logger; class SwiftMailerHandler extends MailHandler { protected $mailer; - protected $message; + private $messageTemplate; /** * @param \Swift_Mailer $mailer The mailer to use @@ -32,14 +32,9 @@ class SwiftMailerHandler extends MailHandler public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, $bubble = true) { parent::__construct($level, $bubble); - $this->mailer = $mailer; - if (!$message instanceof \Swift_Message && is_callable($message)) { - $message = call_user_func($message); - } - if (!$message instanceof \Swift_Message) { - throw new \InvalidArgumentException('You must provide either a Swift_Message instance or a callable returning it'); - } - $this->message = $message; + + $this->mailer = $mailer; + $this->messageTemplate = $message; } /** @@ -47,10 +42,46 @@ class SwiftMailerHandler extends MailHandler */ protected function send($content, array $records) { - $message = clone $this->message; + $this->mailer->send($this->buildMessage($content, $records)); + } + + /** + * Creates instance of Swift_Message to be sent + * + * @param string $content formatted email body to be sent + * @param array $records Log records that formed the content + * @return \Swift_Message + */ + protected function buildMessage($content, array $records) + { + $message = null; + if ($this->messageTemplate instanceof \Swift_Message) { + $message = clone $this->messageTemplate; + } else if (is_callable($this->messageTemplate)) { + $message = call_user_func($this->messageTemplate, $content, $records); + } + + if (!$message instanceof \Swift_Message) { + throw new \InvalidArgumentException('Could not resolve message as instance of Swift_Message or a callable returning it'); + } + $message->setBody($content); $message->setDate(time()); - $this->mailer->send($message); + return $message; + } + + /** + * BC getter, to be removed in 2.0 + */ + public function __get($name) + { + if ($name === 'message') { + trigger_error('SwiftMailerHandler->message is deprecated, use ->buildMessage() instead to retrieve the message', E_USER_DEPRECATED); + + return $this->buildMessage(null, array()); + } + + throw new \InvalidArgumentException('Invalid property '.$name); } } diff --git a/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php index 085d9e17..80b7f283 100644 --- a/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php +++ b/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php @@ -129,6 +129,61 @@ class TestHandler extends AbstractProcessingHandler return false; } + public function hasEmergencyThatContains($message) + { + return $this->hasRecordThatContains($message, Logger::EMERGENCY); + } + + public function hasAlertThatContains($message) + { + return $this->hasRecordThatContains($message, Logger::ALERT); + } + + public function hasCriticalThatContains($message) + { + return $this->hasRecordThatContains($message, Logger::CRITICAL); + } + + public function hasErrorThatContains($message) + { + return $this->hasRecordThatContains($message, Logger::ERROR); + } + + public function hasWarningThatContains($message) + { + return $this->hasRecordThatContains($message, Logger::WARNING); + } + + public function hasNoticeThatContains($message) + { + return $this->hasRecordThatContains($message, Logger::NOTICE); + } + + public function hasInfoThatContains($message) + { + return $this->hasRecordThatContains($message, Logger::INFO); + } + + public function hasDebugThatContains($message) + { + return $this->hasRecordThatContains($message, Logger::DEBUG); + } + + public function hasRecordThatContains($message, $level) + { + if (!isset($this->recordsByLevel[$level])) { + return false; + } + + foreach ($this->recordsByLevel[$level] as $rec) { + if (strpos($rec['message'], $message) !== false) { + return true; + } + } + + return false; + } + /** * {@inheritdoc} */ diff --git a/vendor/monolog/monolog/src/Monolog/Logger.php b/vendor/monolog/monolog/src/Monolog/Logger.php index 4a38de7f..32e3dd92 100644 --- a/vendor/monolog/monolog/src/Monolog/Logger.php +++ b/vendor/monolog/monolog/src/Monolog/Logger.php @@ -152,10 +152,12 @@ class Logger implements LoggerInterface * Pushes a handler on to the stack. * * @param HandlerInterface $handler + * @return $this */ public function pushHandler(HandlerInterface $handler) { array_unshift($this->handlers, $handler); + return $this; } /** @@ -184,6 +186,7 @@ class Logger implements LoggerInterface * Adds a processor on to the stack. * * @param callable $callback + * @return $this */ public function pushProcessor($callback) { @@ -191,6 +194,7 @@ class Logger implements LoggerInterface throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given'); } array_unshift($this->processors, $callback); + return $this; } /** @@ -438,9 +442,7 @@ class Logger implements LoggerInterface */ public function log($level, $message, array $context = array()) { - if (is_string($level) && defined(__CLASS__.'::'.strtoupper($level))) { - $level = constant(__CLASS__.'::'.strtoupper($level)); - } + $level = static::toMonologLevel($level); return $this->addRecord($level, $message, $context); } @@ -612,4 +614,16 @@ class Logger implements LoggerInterface { return $this->addRecord(static::EMERGENCY, $message, $context); } + + /** + * Set the timezone to be used for the timestamp of log records. + * + * This is stored globally for all Logger instances + * + * @param \DateTimeZone $tz Timezone object + */ + public static function setTimezone(\DateTimeZone $tz) + { + self::$timezone = $tz; + } } diff --git a/vendor/monolog/monolog/src/Monolog/Registry.php b/vendor/monolog/monolog/src/Monolog/Registry.php index a3eba079..a33cb7c4 100644 --- a/vendor/monolog/monolog/src/Monolog/Registry.php +++ b/vendor/monolog/monolog/src/Monolog/Registry.php @@ -38,7 +38,7 @@ use InvalidArgumentException; class Registry { /** - * List of all loggers in the registry (ba named indexes) + * List of all loggers in the registry (by named indexes) * * @var Logger[] */ @@ -64,6 +64,22 @@ class Registry } /** + * Checks if such logging channel exists by name or instance + * + * @param string|Logger $logger Name or logger instance + */ + public static function hasLogger($logger) + { + if ($logger instanceof Logger) { + $index = array_search($logger, self::$loggers, true); + + return false !== $index; + } else { + return isset(self::$loggers[$logger]); + } + } + + /** * Removes instance from registry by name or instance * * @param string|Logger $logger Name or logger instance diff --git a/vendor/monolog/monolog/tests/Monolog/Formatter/GelfMessageFormatterTest.php b/vendor/monolog/monolog/tests/Monolog/Formatter/GelfMessageFormatterTest.php index 3f47a09a..6ac14854 100644 --- a/vendor/monolog/monolog/tests/Monolog/Formatter/GelfMessageFormatterTest.php +++ b/vendor/monolog/monolog/tests/Monolog/Formatter/GelfMessageFormatterTest.php @@ -82,6 +82,21 @@ class GelfMessageFormatterTest extends \PHPUnit_Framework_TestCase /** * @covers Monolog\Formatter\GelfMessageFormatter::format + * @expectedException InvalidArgumentException + */ + public function testFormatInvalidFails() + { + $formatter = new GelfMessageFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + ); + + $formatter->format($record); + } + + /** + * @covers Monolog\Formatter\GelfMessageFormatter::format */ public function testFormatWithContext() { diff --git a/vendor/monolog/monolog/tests/Monolog/Formatter/LineFormatterTest.php b/vendor/monolog/monolog/tests/Monolog/Formatter/LineFormatterTest.php index 89e1ca2e..c1b2e0ee 100644 --- a/vendor/monolog/monolog/tests/Monolog/Formatter/LineFormatterTest.php +++ b/vendor/monolog/monolog/tests/Monolog/Formatter/LineFormatterTest.php @@ -103,7 +103,7 @@ class LineFormatterTest extends \PHPUnit_Framework_TestCase 'message' => 'foobar', )); - $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: foobar [] {"foo":"[object] (Monolog\\\\Formatter\\\\TestFoo: {\\"foo\\":\\"foo\\"})","bar":"[object] (Monolog\\\\Formatter\\\\TestBar: {})","baz":[],"res":"[resource]"}'."\n", $message); + $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: foobar [] {"foo":"[object] (Monolog\\\\Formatter\\\\TestFoo: {\\"foo\\":\\"foo\\"})","bar":"[object] (Monolog\\\\Formatter\\\\TestBar: bar)","baz":[],"res":"[resource]"}'."\n", $message); } public function testDefFormatWithException() diff --git a/vendor/monolog/monolog/tests/Monolog/Formatter/NormalizerFormatterTest.php b/vendor/monolog/monolog/tests/Monolog/Formatter/NormalizerFormatterTest.php index 00bbb249..4ffeded0 100644 --- a/vendor/monolog/monolog/tests/Monolog/Formatter/NormalizerFormatterTest.php +++ b/vendor/monolog/monolog/tests/Monolog/Formatter/NormalizerFormatterTest.php @@ -28,6 +28,9 @@ class NormalizerFormatterTest extends \PHPUnit_Framework_TestCase 'context' => array( 'foo' => 'bar', 'baz' => 'qux', + 'inf' => INF, + '-inf' => -INF, + 'nan' => acos(4), ), )); @@ -38,13 +41,16 @@ class NormalizerFormatterTest extends \PHPUnit_Framework_TestCase 'datetime' => date('Y-m-d'), 'extra' => array( 'foo' => '[object] (Monolog\\Formatter\\TestFooNorm: {"foo":"foo"})', - 'bar' => '[object] (Monolog\\Formatter\\TestBarNorm: {})', + 'bar' => '[object] (Monolog\\Formatter\\TestBarNorm: bar)', 'baz' => array(), 'res' => '[resource]', ), 'context' => array( 'foo' => 'bar', 'baz' => 'qux', + 'inf' => 'INF', + '-inf' => '-INF', + 'nan' => 'NaN', ) ), $formatted); } @@ -184,7 +190,8 @@ class NormalizerFormatterTest extends \PHPUnit_Framework_TestCase // This will contain $resource and $wrappedResource as arguments in the trace item $resource = fopen('php://memory', 'rw+'); fwrite($resource, 'test_resource'); - $wrappedResource = new TestStreamFoo($resource); + $wrappedResource = new TestFooNorm; + $wrappedResource->foo = $resource; // Just do something stupid with a resource/wrapped resource as argument array_keys($wrappedResource); } catch (\Exception $e) { @@ -201,9 +208,9 @@ class NormalizerFormatterTest extends \PHPUnit_Framework_TestCase ); if (version_compare(PHP_VERSION, '5.5.0', '>=')) { - $pattern = '%"wrappedResource":"\[object\] \(Monolog\\\\\\\\Formatter\\\\\\\\TestStreamFoo: \)"%'; + $pattern = '%"wrappedResource":"\[object\] \(Monolog\\\\\\\\Formatter\\\\\\\\TestFooNorm: \)"%'; } else { - $pattern = '%\\\\"resource\\\\":null%'; + $pattern = '%\\\\"foo\\\\":null%'; } // Tests that the wrapped resource is ignored while encoding, only works for PHP <= 5.4 diff --git a/vendor/monolog/monolog/tests/Monolog/Functional/Handler/FirePHPHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Functional/Handler/FirePHPHandlerTest.php deleted file mode 100644 index 7e4e7eb5..00000000 --- a/vendor/monolog/monolog/tests/Monolog/Functional/Handler/FirePHPHandlerTest.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Monolog package. - * - * (c) Jordi Boggiano <j.boggiano@seld.be> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -spl_autoload_register(function ($class) { - $file = __DIR__.'/../../../../src/'.strtr($class, '\\', '/').'.php'; - if (file_exists($file)) { - require $file; - - return true; - } -}); - -use Monolog\Logger; -use Monolog\Handler\FirePHPHandler; -use Monolog\Handler\ChromePHPHandler; - -$logger = new Logger('firephp'); -$logger->pushHandler(new FirePHPHandler); -$logger->pushHandler(new ChromePHPHandler()); - -$logger->addDebug('Debug'); -$logger->addInfo('Info'); -$logger->addWarning('Warning'); -$logger->addError('Error'); diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/AmqpHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/AmqpHandlerTest.php index 074d50c6..a71d6251 100644 --- a/vendor/monolog/monolog/tests/Monolog/Handler/AmqpHandlerTest.php +++ b/vendor/monolog/monolog/tests/Monolog/Handler/AmqpHandlerTest.php @@ -14,7 +14,6 @@ namespace Monolog\Handler; use Monolog\TestCase; use Monolog\Logger; use PhpAmqpLib\Message\AMQPMessage; -use PhpAmqpLib\Channel\AMQPChannel; use PhpAmqpLib\Connection\AMQPConnection; /** diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/CouchDBHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/CouchDBHandlerTest.php index 78a1d15c..9fc4b388 100644 --- a/vendor/monolog/monolog/tests/Monolog/Handler/CouchDBHandlerTest.php +++ b/vendor/monolog/monolog/tests/Monolog/Handler/CouchDBHandlerTest.php @@ -20,16 +20,6 @@ class CouchDBHandlerTest extends TestCase { $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); - $expected = array( - 'message' => 'test', - 'context' => array('data' => '[object] (stdClass: {})', 'foo' => 34), - 'level' => Logger::WARNING, - 'level_name' => 'WARNING', - 'channel' => 'test', - 'datetime' => $record['datetime']->format('Y-m-d H:i:s'), - 'extra' => array(), - ); - $handler = new CouchDBHandler(); try { diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/FingersCrossedHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/FingersCrossedHandlerTest.php index a3d350d5..8e31e9b8 100644 --- a/vendor/monolog/monolog/tests/Monolog/Handler/FingersCrossedHandlerTest.php +++ b/vendor/monolog/monolog/tests/Monolog/Handler/FingersCrossedHandlerTest.php @@ -15,6 +15,7 @@ use Monolog\TestCase; use Monolog\Logger; use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy; use Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy; +use Psr\Log\LogLevel; class FingersCrossedHandlerTest extends TestCase { @@ -237,4 +238,18 @@ class FingersCrossedHandlerTest extends TestCase $this->assertFalse($test->hasDebugRecords()); $this->assertTrue($test->hasInfoRecords()); } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::close + */ + public function testPsrLevelPassthruOnClose() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, new ErrorLevelActivationStrategy(Logger::WARNING), 0, true, true, LogLevel::INFO); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $handler->close(); + $this->assertFalse($test->hasDebugRecords()); + $this->assertTrue($test->hasInfoRecords()); + } } diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerLegacyTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerLegacyTest.php index d60a6db3..9d007b13 100644 --- a/vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerLegacyTest.php +++ b/vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerLegacyTest.php @@ -23,6 +23,8 @@ class GelfHandlerLegacyTest extends TestCase if (!class_exists('Gelf\MessagePublisher') || !class_exists('Gelf\Message')) { $this->markTestSkipped("mlehner/gelf-php not installed"); } + + require_once __DIR__ . '/GelfMockMessagePublisher.php'; } /** @@ -43,7 +45,7 @@ class GelfHandlerLegacyTest extends TestCase protected function getMessagePublisher() { - return new MockMessagePublisher('localhost'); + return new GelfMockMessagePublisher('localhost'); } public function testDebug() diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/GelfMockMessagePublisher.php b/vendor/monolog/monolog/tests/Monolog/Handler/GelfMockMessagePublisher.php new file mode 100644 index 00000000..873d92fb --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/GelfMockMessagePublisher.php @@ -0,0 +1,25 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Gelf\MessagePublisher; +use Gelf\Message; + +class GelfMockMessagePublisher extends MessagePublisher +{ + public function publish(Message $message) + { + $this->lastMessage = $message; + } + + public $lastMessage = null; +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/HipChatHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/HipChatHandlerTest.php index d58386a1..ff773c98 100644 --- a/vendor/monolog/monolog/tests/Monolog/Handler/HipChatHandlerTest.php +++ b/vendor/monolog/monolog/tests/Monolog/Handler/HipChatHandlerTest.php @@ -35,12 +35,81 @@ class HipChatHandlerTest extends TestCase return $content; } + public function testWriteCustomHostHeader() + { + $this->createHandler('myToken', 'room1', 'Monolog', true, 'hipchat.foo.bar'); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/POST \/v1\/rooms\/message\?format=json&auth_token=.* HTTP\/1.1\\r\\nHost: hipchat.foo.bar\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); + + return $content; + } + + public function testWriteV2() { + $this->createHandler('myToken', 'room1', 'Monolog', false, 'hipchat.foo.bar', 'v2'); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/POST \/v2\/room\/room1\/notification\?auth_token=.* HTTP\/1.1\\r\\nHost: hipchat.foo.bar\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); + + return $content; + } + + public function testWriteV2Notify() { + $this->createHandler('myToken', 'room1', 'Monolog', true, 'hipchat.foo.bar', 'v2'); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/POST \/v2\/room\/room1\/notification\?auth_token=.* HTTP\/1.1\\r\\nHost: hipchat.foo.bar\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); + + return $content; + } + + public function testRoomSpaces() { + $this->createHandler('myToken', 'room name', 'Monolog', false, 'hipchat.foo.bar', 'v2'); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/POST \/v2\/room\/room%20name\/notification\?auth_token=.* HTTP\/1.1\\r\\nHost: hipchat.foo.bar\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); + + return $content; + } + /** * @depends testWriteHeader */ public function testWriteContent($content) { - $this->assertRegexp('/from=Monolog&room_id=room1¬ify=0&message=test1&message_format=text&color=red$/', $content); + $this->assertRegexp('/notify=0&message=test1&message_format=text&color=red&room_id=room1&from=Monolog$/', $content); + } + + /** + * @depends testWriteCustomHostHeader + */ + public function testWriteContentNotify($content) + { + $this->assertRegexp('/notify=1&message=test1&message_format=text&color=red&room_id=room1&from=Monolog$/', $content); + } + + /** + * @depends testWriteV2 + */ + public function testWriteContentV2($content) + { + $this->assertRegexp('/notify=false&message=test1&message_format=text&color=red$/', $content); + } + + /** + * @depends testWriteV2Notify + */ + public function testWriteContentV2Notify($content) + { + $this->assertRegexp('/notify=true&message=test1&message_format=text&color=red$/', $content); } public function testWriteWithComplexMessage() @@ -129,9 +198,9 @@ class HipChatHandlerTest extends TestCase ); } - private function createHandler($token = 'myToken', $room = 'room1', $name = 'Monolog', $notify = false) + private function createHandler($token = 'myToken', $room = 'room1', $name = 'Monolog', $notify = false, $host = 'api.hipchat.com', $version = 'v1') { - $constructorArgs = array($token, $room, $name, $notify, Logger::DEBUG); + $constructorArgs = array($token, $room, $name, $notify, Logger::DEBUG, true, true, 'text', $host, $version); $this->res = fopen('php://memory', 'a'); $this->handler = $this->getMock( '\Monolog\Handler\HipChatHandler', @@ -163,4 +232,9 @@ class HipChatHandlerTest extends TestCase { $hipChatHandler = new \Monolog\Handler\HipChatHandler('token', 'room', 'SixteenCharsHere'); } + + public function testCreateWithTooLongNameV2() { + // creating a handler with too long of a name but using the v2 api doesn't matter. + $hipChatHandler = new \Monolog\Handler\HipChatHandler('token', 'room', 'SixteenCharsHere', false, Logger::CRITICAL, true, true, 'test', 'api.hipchat.com', 'v2'); + } } diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/MockRavenClient.php b/vendor/monolog/monolog/tests/Monolog/Handler/MockRavenClient.php index fbaab9bc..a0833225 100644 --- a/vendor/monolog/monolog/tests/Monolog/Handler/MockRavenClient.php +++ b/vendor/monolog/monolog/tests/Monolog/Handler/MockRavenClient.php @@ -17,6 +17,7 @@ class MockRavenClient extends Raven_Client { public function capture($data, $stack, $vars = null) { + $data = array_merge($this->get_user_data(), $data); $this->lastData = $data; $this->lastStack = $stack; } diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/NewRelicHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/NewRelicHandlerTest.php index 22014908..4eda6155 100644 --- a/vendor/monolog/monolog/tests/Monolog/Handler/NewRelicHandlerTest.php +++ b/vendor/monolog/monolog/tests/Monolog/Handler/NewRelicHandlerTest.php @@ -136,7 +136,7 @@ class NewRelicHandlerTest extends TestCase $this->assertEquals(null, self::$transactionName); } - public function testTheTransactionNameCanBeInjectedFromtheConstructor() + public function testTheTransactionNameCanBeInjectedFromTheConstructor() { $handler = new StubNewRelicHandler(Logger::DEBUG, false, null, false, 'myTransaction'); $handler->handle($this->getRecord(Logger::ERROR, 'log message')); diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/PHPConsoleHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/PHPConsoleHandlerTest.php new file mode 100644 index 00000000..81684c5e --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/PHPConsoleHandlerTest.php @@ -0,0 +1,271 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Exception; +use Monolog\ErrorHandler; +use Monolog\Logger; +use Monolog\TestCase; +use PhpConsole\Connector; +use PhpConsole\Dispatcher\Debug as DebugDispatcher; +use PhpConsole\Dispatcher\Errors as ErrorDispatcher; +use PhpConsole\Handler; +use PHPUnit_Framework_MockObject_MockObject; + +/** + * @covers Monolog\Handler\PHPConsoleHandler + * @author Sergey Barbushin https://www.linkedin.com/in/barbushin + */ +class PHPConsoleHandlerTest extends TestCase +{ + + /** @var Connector|PHPUnit_Framework_MockObject_MockObject */ + protected $connector; + /** @var DebugDispatcher|PHPUnit_Framework_MockObject_MockObject */ + protected $debugDispatcher; + /** @var ErrorDispatcher|PHPUnit_Framework_MockObject_MockObject */ + protected $errorDispatcher; + + protected function setUp() + { + if (!class_exists('PhpConsole\Connector')) { + $this->markTestSkipped('PHP Console library not found. See https://github.com/barbushin/php-console#installation'); + } + $this->connector = $this->initConnectorMock(); + + $this->debugDispatcher = $this->initDebugDispatcherMock($this->connector); + $this->connector->setDebugDispatcher($this->debugDispatcher); + + $this->errorDispatcher = $this->initErrorDispatcherMock($this->connector); + $this->connector->setErrorsDispatcher($this->errorDispatcher); + } + + protected function initDebugDispatcherMock(Connector $connector) + { + return $this->getMockBuilder('PhpConsole\Dispatcher\Debug') + ->disableOriginalConstructor() + ->setMethods(array('dispatchDebug')) + ->setConstructorArgs(array($connector, $connector->getDumper())) + ->getMock(); + } + + protected function initErrorDispatcherMock(Connector $connector) + { + return $this->getMockBuilder('PhpConsole\Dispatcher\Errors') + ->disableOriginalConstructor() + ->setMethods(array('dispatchError', 'dispatchException')) + ->setConstructorArgs(array($connector, $connector->getDumper())) + ->getMock(); + } + + protected function initConnectorMock() + { + $connector = $this->getMockBuilder('PhpConsole\Connector') + ->disableOriginalConstructor() + ->setMethods(array( + 'sendMessage', + 'onShutDown', + 'isActiveClient', + 'setSourcesBasePath', + 'setServerEncoding', + 'setPassword', + 'enableSslOnlyMode', + 'setAllowedIpMasks', + 'setHeadersLimit', + 'startEvalRequestsListener', + )) + ->getMock(); + + $connector->expects($this->any()) + ->method('isActiveClient') + ->will($this->returnValue(true)); + + return $connector; + } + + protected function getHandlerDefaultOption($name) + { + $handler = new PHPConsoleHandler(array(), $this->connector); + $options = $handler->getOptions(); + + return $options[$name]; + } + + protected function initLogger($handlerOptions = array(), $level = Logger::DEBUG) + { + return new Logger('test', array( + new PHPConsoleHandler($handlerOptions, $this->connector, $level) + )); + } + + public function testInitWithDefaultConnector() + { + $handler = new PHPConsoleHandler(); + $this->assertEquals(spl_object_hash(Connector::getInstance()), spl_object_hash($handler->getConnector())); + } + + public function testInitWithCustomConnector() + { + $handler = new PHPConsoleHandler(array(), $this->connector); + $this->assertEquals(spl_object_hash($this->connector), spl_object_hash($handler->getConnector())); + } + + public function testDebug() + { + $this->debugDispatcher->expects($this->once())->method('dispatchDebug')->with($this->equalTo('test')); + $this->initLogger()->addDebug('test'); + } + + public function testDebugContextInMessage() + { + $message = 'test'; + $tag = 'tag'; + $context = array($tag, 'custom' => mt_rand()); + $expectedMessage = $message . ' ' . json_encode(array_slice($context, 1)); + $this->debugDispatcher->expects($this->once())->method('dispatchDebug')->with( + $this->equalTo($expectedMessage), + $this->equalTo($tag) + ); + $this->initLogger()->addDebug($message, $context); + } + + public function testDebugTags($tagsContextKeys = null) + { + $expectedTags = mt_rand(); + $logger = $this->initLogger($tagsContextKeys ? array('debugTagsKeysInContext' => $tagsContextKeys) : array()); + if (!$tagsContextKeys) { + $tagsContextKeys = $this->getHandlerDefaultOption('debugTagsKeysInContext'); + } + foreach ($tagsContextKeys as $key) { + $debugDispatcher = $this->initDebugDispatcherMock($this->connector); + $debugDispatcher->expects($this->once())->method('dispatchDebug')->with( + $this->anything(), + $this->equalTo($expectedTags) + ); + $this->connector->setDebugDispatcher($debugDispatcher); + $logger->addDebug('test', array($key => $expectedTags)); + } + } + + public function testError($classesPartialsTraceIgnore = null) + { + $code = E_USER_NOTICE; + $message = 'message'; + $file = __FILE__; + $line = __LINE__; + $this->errorDispatcher->expects($this->once())->method('dispatchError')->with( + $this->equalTo($code), + $this->equalTo($message), + $this->equalTo($file), + $this->equalTo($line), + $classesPartialsTraceIgnore ?: $this->equalTo($this->getHandlerDefaultOption('classesPartialsTraceIgnore')) + ); + $errorHandler = ErrorHandler::register($this->initLogger($classesPartialsTraceIgnore ? array('classesPartialsTraceIgnore' => $classesPartialsTraceIgnore) : array()), false); + $errorHandler->registerErrorHandler(array(), false, E_USER_WARNING); + $errorHandler->handleError($code, $message, $file, $line); + } + + public function testException() + { + $exception = new Exception(); + $this->errorDispatcher->expects($this->once())->method('dispatchException')->with( + $this->equalTo($exception) + ); + $errorHandler = ErrorHandler::register($this->initLogger(), false, false); + $errorHandler->registerExceptionHandler(null, false); + $errorHandler->handleException($exception); + } + + /** + * @expectedException Exception + */ + public function testWrongOptionsThrowsException() + { + new PHPConsoleHandler(array('xxx' => 1)); + } + + public function testOptionEnabled() + { + $this->debugDispatcher->expects($this->never())->method('dispatchDebug'); + $this->initLogger(array('enabled' => false))->addDebug('test'); + } + + public function testOptionClassesPartialsTraceIgnore() + { + $this->testError(array('Class', 'Namespace\\')); + } + + public function testOptionDebugTagsKeysInContext() + { + $this->testDebugTags(array('key1', 'key2')); + } + + public function testOptionUseOwnErrorsAndExceptionsHandler() + { + $this->initLogger(array('useOwnErrorsHandler' => true, 'useOwnExceptionsHandler' => true)); + $this->assertEquals(array(Handler::getInstance(), 'handleError'), set_error_handler(function () { + })); + $this->assertEquals(array(Handler::getInstance(), 'handleException'), set_exception_handler(function () { + })); + } + + public static function provideConnectorMethodsOptionsSets() + { + return array( + array('sourcesBasePath', 'setSourcesBasePath', __DIR__), + array('serverEncoding', 'setServerEncoding', 'cp1251'), + array('password', 'setPassword', '******'), + array('enableSslOnlyMode', 'enableSslOnlyMode', true, false), + array('ipMasks', 'setAllowedIpMasks', array('127.0.0.*')), + array('headersLimit', 'setHeadersLimit', 2500), + array('enableEvalListener', 'startEvalRequestsListener', true, false), + ); + } + + /** + * @dataProvider provideConnectorMethodsOptionsSets + */ + public function testOptionCallsConnectorMethod($option, $method, $value, $isArgument = true) + { + $expectCall = $this->connector->expects($this->once())->method($method); + if ($isArgument) { + $expectCall->with($value); + } + new PHPConsoleHandler(array($option => $value), $this->connector); + } + + public function testOptionDetectDumpTraceAndSource() + { + new PHPConsoleHandler(array('detectDumpTraceAndSource' => true), $this->connector); + $this->assertTrue($this->connector->getDebugDispatcher()->detectTraceAndSource); + } + + public static function provideDumperOptionsValues() + { + return array( + array('dumperLevelLimit', 'levelLimit', 1001), + array('dumperItemsCountLimit', 'itemsCountLimit', 1002), + array('dumperItemSizeLimit', 'itemSizeLimit', 1003), + array('dumperDumpSizeLimit', 'dumpSizeLimit', 1004), + array('dumperDetectCallbacks', 'detectCallbacks', true), + ); + } + + /** + * @dataProvider provideDumperOptionsValues + */ + public function testDumperOptions($option, $dumperProperty, $value) + { + new PHPConsoleHandler(array($option => $value), $this->connector); + $this->assertEquals($value, $this->connector->getDumper()->$dumperProperty); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/RavenHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/RavenHandlerTest.php index 8fe86961..9a9d1006 100644 --- a/vendor/monolog/monolog/tests/Monolog/Handler/RavenHandlerTest.php +++ b/vendor/monolog/monolog/tests/Monolog/Handler/RavenHandlerTest.php @@ -19,8 +19,8 @@ class RavenHandlerTest extends TestCase { public function setUp() { - if (!class_exists("Raven_Client")) { - $this->markTestSkipped("raven/raven not installed"); + if (!class_exists('Raven_Client')) { + $this->markTestSkipped('raven/raven not installed'); } require_once __DIR__ . '/MockRavenClient.php'; @@ -54,7 +54,7 @@ class RavenHandlerTest extends TestCase $ravenClient = $this->getRavenClient(); $handler = $this->getHandler($ravenClient); - $record = $this->getRecord(Logger::DEBUG, "A test debug message"); + $record = $this->getRecord(Logger::DEBUG, 'A test debug message'); $handler->handle($record); $this->assertEquals($ravenClient::DEBUG, $ravenClient->lastData['level']); @@ -66,7 +66,7 @@ class RavenHandlerTest extends TestCase $ravenClient = $this->getRavenClient(); $handler = $this->getHandler($ravenClient); - $record = $this->getRecord(Logger::WARNING, "A test warning message"); + $record = $this->getRecord(Logger::WARNING, 'A test warning message'); $handler->handle($record); $this->assertEquals($ravenClient::WARNING, $ravenClient->lastData['level']); @@ -79,12 +79,47 @@ class RavenHandlerTest extends TestCase $handler = $this->getHandler($ravenClient); $tags = array(1, 2, 'foo'); - $record = $this->getRecord(Logger::INFO, "test", array('tags' => $tags)); + $record = $this->getRecord(Logger::INFO, 'test', array('tags' => $tags)); $handler->handle($record); $this->assertEquals($tags, $ravenClient->lastData['tags']); } + public function testUserContext() + { + $ravenClient = $this->getRavenClient(); + $handler = $this->getHandler($ravenClient); + + $recordWithNoContext = $this->getRecord(Logger::INFO, 'test with default user context'); + // set user context 'externally' + + $user = array( + 'id' => '123', + 'email' => 'test@test.com' + ); + + $recordWithContext = $this->getRecord(Logger::INFO, 'test', array('user' => $user)); + + $ravenClient->user_context(array('id' => 'test_user_id')); + // handle context + $handler->handle($recordWithContext); + $this->assertEquals($user, $ravenClient->lastData['sentry.interfaces.User']); + + // check to see if its reset + $handler->handle($recordWithNoContext); + $this->assertInternalType('array', $ravenClient->context->user); + $this->assertSame('test_user_id', $ravenClient->context->user['id']); + + // handle with null context + $ravenClient->user_context(null); + $handler->handle($recordWithContext); + $this->assertEquals($user, $ravenClient->lastData['sentry.interfaces.User']); + + // check to see if its reset + $handler->handle($recordWithNoContext); + $this->assertNull($ravenClient->context->user); + } + public function testException() { $ravenClient = $this->getRavenClient(); diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/SwiftMailerHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/SwiftMailerHandlerTest.php new file mode 100644 index 00000000..ac885220 --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/Handler/SwiftMailerHandlerTest.php @@ -0,0 +1,65 @@ +<?php + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\TestCase; + +class SwiftMailerHandlerTest extends TestCase +{ + /** @var \Swift_Mailer|\PHPUnit_Framework_MockObject_MockObject */ + private $mailer; + + public function setUp() + { + $this->mailer = $this + ->getMockBuilder('Swift_Mailer') + ->disableOriginalConstructor() + ->getMock(); + } + + public function testMessageCreationIsLazyWhenUsingCallback() + { + $this->mailer->expects($this->never()) + ->method('send'); + + $callback = function () { + throw new \RuntimeException('Swift_Message creation callback should not have been called in this test'); + }; + $handler = new SwiftMailerHandler($this->mailer, $callback); + + $records = array( + $this->getRecord(Logger::DEBUG), + $this->getRecord(Logger::INFO), + ); + $handler->handleBatch($records); + } + + public function testMessageCanBeCustomizedGivenLoggedData() + { + // Wire Mailer to expect a specific Swift_Message with a customized Subject + $expectedMessage = new \Swift_Message(); + $this->mailer->expects($this->once()) + ->method('send') + ->with($this->callback(function ($value) use ($expectedMessage) { + return $value instanceof \Swift_Message + && $value->getSubject() === 'Emergency' + && $value === $expectedMessage; + })); + + // Callback dynamically changes subject based on number of logged records + $callback = function ($content, array $records) use ($expectedMessage) { + $subject = count($records) > 0 ? 'Emergency' : 'Normal'; + $expectedMessage->setSubject($subject); + + return $expectedMessage; + }; + $handler = new SwiftMailerHandler($this->mailer, $callback); + + // Logging 1 record makes this an Emergency + $records = array( + $this->getRecord(Logger::EMERGENCY), + ); + $handler->handleBatch($records); + } +} diff --git a/vendor/monolog/monolog/tests/Monolog/Handler/TestHandlerTest.php b/vendor/monolog/monolog/tests/Monolog/Handler/TestHandlerTest.php index 801d80a9..2a79fdc6 100644 --- a/vendor/monolog/monolog/tests/Monolog/Handler/TestHandlerTest.php +++ b/vendor/monolog/monolog/tests/Monolog/Handler/TestHandlerTest.php @@ -27,12 +27,14 @@ class TestHandlerTest extends TestCase $handler = new TestHandler; $record = $this->getRecord($level, 'test'.$method); $this->assertFalse($handler->{'has'.$method}($record)); + $this->assertFalse($handler->{'has'.$method.'ThatContains'}('test')); $this->assertFalse($handler->{'has'.$method.'Records'}()); $handler->handle($record); $this->assertFalse($handler->{'has'.$method}('bar')); $this->assertTrue($handler->{'has'.$method}($record)); $this->assertTrue($handler->{'has'.$method}('test'.$method)); + $this->assertTrue($handler->{'has'.$method.'ThatContains'}('test')); $this->assertTrue($handler->{'has'.$method.'Records'}()); $records = $handler->getRecords(); diff --git a/vendor/monolog/monolog/tests/Monolog/LoggerTest.php b/vendor/monolog/monolog/tests/Monolog/LoggerTest.php index 7a19c0b4..146b6f1b 100644 --- a/vendor/monolog/monolog/tests/Monolog/LoggerTest.php +++ b/vendor/monolog/monolog/tests/Monolog/LoggerTest.php @@ -34,6 +34,21 @@ class LoggerTest extends \PHPUnit_Framework_TestCase } /** + * @covers Monolog\Logger::toMonologLevel + */ + public function testConvertPSR3ToMonologLevel() + { + $this->assertEquals(Logger::toMonologLevel('debug'), 100); + $this->assertEquals(Logger::toMonologLevel('info'), 200); + $this->assertEquals(Logger::toMonologLevel('notice'), 250); + $this->assertEquals(Logger::toMonologLevel('warning'), 300); + $this->assertEquals(Logger::toMonologLevel('error'), 400); + $this->assertEquals(Logger::toMonologLevel('critical'), 500); + $this->assertEquals(Logger::toMonologLevel('alert'), 550); + $this->assertEquals(Logger::toMonologLevel('emergency'), 600); + } + + /** * @covers Monolog\Logger::getLevelName * @expectedException InvalidArgumentException */ @@ -406,4 +421,27 @@ class LoggerTest extends \PHPUnit_Framework_TestCase array('emerg', Logger::EMERGENCY), ); } + + /** + * @dataProvider setTimezoneProvider + * @covers Monolog\Logger::setTimezone + */ + public function testSetTimezone($tz) + { + Logger::setTimezone($tz); + $logger = new Logger('foo'); + $handler = new TestHandler; + $logger->pushHandler($handler); + $logger->info('test'); + list($record) = $handler->getRecords(); + $this->assertEquals($tz, $record['datetime']->getTimezone()); + } + + public function setTimezoneProvider() + { + return array_map( + function ($tz) { return array(new \DateTimeZone($tz)); }, + \DateTimeZone::listIdentifiers() + ); + } } diff --git a/vendor/monolog/monolog/tests/Monolog/RegistryTest.php b/vendor/monolog/monolog/tests/Monolog/RegistryTest.php new file mode 100644 index 00000000..29925f8a --- /dev/null +++ b/vendor/monolog/monolog/tests/Monolog/RegistryTest.php @@ -0,0 +1,63 @@ +<?php + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog; + + +class RegistryTest extends \PHPUnit_Framework_TestCase +{ + protected function setUp() + { + Registry::clear(); + } + + /** + * @dataProvider hasLoggerProvider + * @covers Monolog\Registry::hasLogger + */ + public function testHasLogger(array $loggersToAdd, array $loggersToCheck, array $expectedResult) + { + foreach ($loggersToAdd as $loggerToAdd) { + Registry::addLogger($loggerToAdd); + } + foreach ($loggersToCheck as $index => $loggerToCheck) { + $this->assertSame($expectedResult[$index], Registry::hasLogger($loggerToCheck)); + } + } + + public function hasLoggerProvider() + { + $logger1 = new Logger('test1'); + $logger2 = new Logger('test2'); + $logger3 = new Logger('test3'); + + return array( + // only instances + array( + array($logger1), + array($logger1, $logger2), + array(true, false), + ), + // only names + array( + array($logger1), + array('test1', 'test2'), + array(true, false), + ), + // mixed case + array( + array($logger1, $logger2), + array('test1', $logger2, 'test3', $logger3), + array(true, true, false, false), + ), + ); + } +} diff --git a/vendor/monolog/monolog/tests/bootstrap.php b/vendor/monolog/monolog/tests/bootstrap.php deleted file mode 100644 index b78740e2..00000000 --- a/vendor/monolog/monolog/tests/bootstrap.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -/* - * This file is part of the Monolog package. - * - * (c) Jordi Boggiano <j.boggiano@seld.be> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -$loader = require __DIR__ . "/../vendor/autoload.php"; -$loader->addPsr4('Monolog\\', __DIR__.'/Monolog'); - -date_default_timezone_set('UTC'); |