rpicms

A CMS for the Raspberry Pi
git clone git://archive.git.mtrnord.blog/RpicmsTeam/rpicms.git
Log | Files | Refs | README | LICENSE

commit dfce3d1075cad0e29f27e1aad78c631b2e470338
parent b284dee5a6b6033809cf701fff3db682c3250703
Author: MTRNord <mtrnord1@gmail.com>
Date:   Sun, 22 Feb 2015 19:50:22 +0100

fix autoload

Diffstat:
Acore/update/PHP-Auto-Update | 1+
Mcore/update/update/index.php | 2+-
Acore/update/update/vendor/autoload.php | 7+++++++
Acore/update/update/vendor/bin/semver | 2++
Acore/update/update/vendor/bin/update-versions | 2++
Acore/update/update/vendor/composer/ClassLoader.php | 413+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/composer/autoload_classmap.php | 14++++++++++++++
Acore/update/update/vendor/composer/autoload_namespaces.php | 13+++++++++++++
Acore/update/update/vendor/composer/autoload_psr4.php | 11+++++++++++
Acore/update/update/vendor/composer/autoload_real.php | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/composer/installed.json | 224+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/.gitignore | 7+++++++
Acore/update/update/vendor/desarrolla2/cache/.scrutinizer.yml | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/.travis.yml | 29+++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/LICENSE | 20++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/README.md | 199+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/build.xml | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/composer.json | 35+++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/docs/performance.md | 41+++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/phpunit.xml | 27+++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/AbstractAdapter.php | 148+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/AdapterInterface.php | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/Apc.php | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/File.php | 213+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/MemCache.php | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/Memcached.php | 128+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/Memory.php | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/Mongo.php | 171+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/MySQL.php | 173+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/NotCache.php | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/Redis.php | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Cache.php | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/CacheInterface.php | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/AdapterNotSetException.php | 18++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/ApcCacheException.php | 18++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/CacheException.php | 26++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/FileCacheException.php | 18++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/MemcacheException.php | 26++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/MemoryCacheException.php | 26++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/MongoCacheException.php | 26++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/MySQLCacheException.php | 25+++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/AbstractCacheTest.php | 148+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/ApcCacheTest.php | 40++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/FileTest.php | 41+++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/MemCacheTest.php | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/MemoryTest.php | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/MongoTest.php | 48++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/MySQLTest.php | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/NotCacheTest.php | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/RedisTest.php | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Test/CacheTest.php | 36++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/bootstrap.php | 15+++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/config.yml.dist | 13+++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/performance/Apc.php | 24++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/performance/File.php | 24++++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/performance/Mongo.php | 23+++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/performance/NoCache.php | 23+++++++++++++++++++++++
Acore/update/update/vendor/desarrolla2/cache/tests/performance/common.php | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/CHANGELOG.mdown | 202+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/LICENSE | 19+++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/README.mdown | 283+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/composer.json | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/doc/extending.md | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/doc/sockets.md | 37+++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/doc/usage.md | 162+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/phpunit.xml.dist | 15+++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/ErrorHandler.php | 208+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php | 36++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php | 159+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php | 47+++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php | 165+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php | 48++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php | 184+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php | 184+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php | 204+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php | 145+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php | 45+++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php | 128+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php | 28++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php | 34++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php | 150+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php | 195+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php | 300+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php | 21+++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php | 155+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php | 174+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php | 45+++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php | 172+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php | 181+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php | 153+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php | 234+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php | 284+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php | 46++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Logger.php | 615+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php | 40++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php | 40++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php | 31+++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php | 48++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php | 34++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php | 38++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/src/Monolog/Registry.php | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/ErrorHandlerTest.php | 31+++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/ChromePHPFormatterTest.php | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/ElasticaFormatterTest.php | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/FlowdockFormatterTest.php | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/GelfMessageFormatterTest.php | 189+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/JsonFormatterTest.php | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/LineFormatterTest.php | 208+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/LogglyFormatterTest.php | 40++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/LogstashFormatterTest.php | 289++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/MongoDBFormatterTest.php | 253+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/NormalizerFormatterTest.php | 247+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/ScalarFormatterTest.php | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/WildfireFormatterTest.php | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Functional/Handler/FirePHPHandlerTest.php | 32++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/AbstractHandlerTest.php | 115+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/AbstractProcessingHandlerTest.php | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/AmqpHandlerTest.php | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/BrowserConsoleHandlerTest.php | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/BufferHandlerTest.php | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/ChromePHPHandlerTest.php | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/CouchDBHandlerTest.php | 41+++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/DoctrineCouchDBHandlerTest.php | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/DynamoDbHandlerTest.php | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/ElasticSearchHandlerTest.php | 239+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/ErrorLogHandlerTest.php | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/FilterHandlerTest.php | 170+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/FingersCrossedHandlerTest.php | 240+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/FirePHPHandlerTest.php | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/Fixtures/.gitkeep | 0
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/FleepHookHandlerTest.php | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/FlowdockHandlerTest.php | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerLegacyTest.php | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerTest.php | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/GroupHandlerTest.php | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/HipChatHandlerTest.php | 166+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/LogEntriesHandlerTest.php | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/MailHandlerTest.php | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/MockRavenClient.php | 26++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/MongoDBHandlerTest.php | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/NativeMailerHandlerTest.php | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/NewRelicHandlerTest.php | 192+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/NullHandlerTest.php | 33+++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/PsrHandlerTest.php | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/PushoverHandlerTest.php | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/RavenHandlerTest.php | 150+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/RedisHandlerTest.php | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/RotatingFileHandlerTest.php | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/SamplingHandlerTest.php | 33+++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/SlackHandlerTest.php | 133+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/SocketHandlerTest.php | 282+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/StreamHandlerTest.php | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/SyslogHandlerTest.php | 44++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/SyslogUdpHandlerTest.php | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/TestHandlerTest.php | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/UdpSocketTest.php | 46++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/WhatFailureGroupHandlerTest.php | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Handler/ZendMonitorHandlerTest.php | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/LoggerTest.php | 409+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Processor/GitProcessorTest.php | 29+++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Processor/IntrospectionProcessorTest.php | 123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Processor/MemoryPeakUsageProcessorTest.php | 42++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Processor/MemoryUsageProcessorTest.php | 42++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Processor/ProcessIdProcessorTest.php | 30++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Processor/PsrLogMessageProcessorTest.php | 43+++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Processor/TagProcessorTest.php | 29+++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Processor/UidProcessorTest.php | 27+++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/Processor/WebProcessorTest.php | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/PsrLogCompatTest.php | 47+++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/Monolog/TestCase.php | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/monolog/monolog/tests/bootstrap.php | 15+++++++++++++++
Acore/update/update/vendor/psr/log/.gitignore | 1+
Acore/update/update/vendor/psr/log/LICENSE | 19+++++++++++++++++++
Acore/update/update/vendor/psr/log/Psr/Log/AbstractLogger.php | 120+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/psr/log/Psr/Log/InvalidArgumentException.php | 7+++++++
Acore/update/update/vendor/psr/log/Psr/Log/LogLevel.php | 18++++++++++++++++++
Acore/update/update/vendor/psr/log/Psr/Log/LoggerAwareInterface.php | 17+++++++++++++++++
Acore/update/update/vendor/psr/log/Psr/Log/LoggerAwareTrait.php | 22++++++++++++++++++++++
Acore/update/update/vendor/psr/log/Psr/Log/LoggerInterface.php | 114+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/psr/log/Psr/Log/LoggerTrait.php | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/psr/log/Psr/Log/NullLogger.php | 27+++++++++++++++++++++++++++
Acore/update/update/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/psr/log/README.md | 45+++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/psr/log/composer.json | 17+++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/.travis.yml | 6++++++
Acore/update/update/vendor/vierbergenlars/php-semver/README.md | 129+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/bin/semver | 128+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/bin/update-versions | 134+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/composer.json | 32++++++++++++++++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/definitions | 31+++++++++++++++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/license.md | 24++++++++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/JSArray.php | 205+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/Object.php | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/RegExp.php | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/String.php | 231+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/Util.php | 47+++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/SemVer/SemVerException.php | 19+++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/SemVer/expression.php | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php | 1114+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/SemVer/version.php | 263+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/tests/all_tests.php | 14++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/tests/base_test.php | 259+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/tests/regression_test.php | 18++++++++++++++++++
Acore/update/update/vendor/vierbergenlars/php-semver/tests/semver_test.php | 431+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mthemes/jumbotron/update.php | 12+++++++-----
248 files changed, 24433 insertions(+), 6 deletions(-)

diff --git a/core/update/PHP-Auto-Update b/core/update/PHP-Auto-Update @@ -0,0 +1 @@ +Subproject commit f47f46f4908770e6478fd5e47d5eb8c34ad9788e diff --git a/core/update/update/index.php b/core/update/update/index.php @@ -4,7 +4,7 @@ ####################### header("Cache-Control: no-cache, must-revalidate, no-store"); -require('update.php'); +require('vendor/autoload.php'); use \VisualAppeal\AutoUpdate; diff --git a/core/update/update/vendor/autoload.php b/core/update/update/vendor/autoload.php @@ -0,0 +1,7 @@ +<?php + +// autoload.php @generated by Composer + +require_once __DIR__ . '/composer' . '/autoload_real.php'; + +return ComposerAutoloaderInit28bcf3a34a1868d8d2296cf549ebcc02::getLoader(); diff --git a/core/update/update/vendor/bin/semver b/core/update/update/vendor/bin/semver @@ -0,0 +1 @@ +../vierbergenlars/php-semver/bin/semver +\ No newline at end of file diff --git a/core/update/update/vendor/bin/update-versions b/core/update/update/vendor/bin/update-versions @@ -0,0 +1 @@ +../vierbergenlars/php-semver/bin/update-versions +\ No newline at end of file diff --git a/core/update/update/vendor/composer/ClassLoader.php b/core/update/update/vendor/composer/ClassLoader.php @@ -0,0 +1,413 @@ +<?php + +/* + * This file is part of Composer. + * + * (c) Nils Adermann <naderman@naderman.de> + * 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 Composer\Autoload; + +/** + * ClassLoader implements a PSR-0 class loader + * + * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + + private $classMapAuthoritative = false; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-0 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 + if ('\\' == $class[0]) { + $class = substr($class, 1); + } + + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative) { + return false; + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if ($file === null && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if ($file === null) { + // Remember that this class does not exist. + return $this->classMap[$class] = false; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { + if (0 === strpos($class, $prefix)) { + foreach ($this->prefixDirsPsr4[$prefix] as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/core/update/update/vendor/composer/autoload_classmap.php b/core/update/update/vendor/composer/autoload_classmap.php @@ -0,0 +1,14 @@ +<?php + +// autoload_classmap.php @generated by Composer + +$vendorDir = dirname(dirname(__FILE__)); +$baseDir = dirname($vendorDir); + +return array( + 'vierbergenlars\\SemVer\\Internal\\Comparator' => $vendorDir . '/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php', + 'vierbergenlars\\SemVer\\Internal\\Exports' => $vendorDir . '/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php', + 'vierbergenlars\\SemVer\\Internal\\G' => $vendorDir . '/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php', + 'vierbergenlars\\SemVer\\Internal\\Range' => $vendorDir . '/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php', + 'vierbergenlars\\SemVer\\Internal\\SemVer' => $vendorDir . '/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php', +); diff --git a/core/update/update/vendor/composer/autoload_namespaces.php b/core/update/update/vendor/composer/autoload_namespaces.php @@ -0,0 +1,13 @@ +<?php + +// autoload_namespaces.php @generated by Composer + +$vendorDir = dirname(dirname(__FILE__)); +$baseDir = dirname($vendorDir); + +return array( + 'vierbergenlars\\SemVer\\' => array($vendorDir . '/vierbergenlars/php-semver/src'), + 'vierbergenlars\\LibJs\\' => array($vendorDir . '/vierbergenlars/php-semver/src'), + 'Psr\\Log\\' => array($vendorDir . '/psr/log'), + 'Desarrolla2\\Cache\\' => array($vendorDir . '/desarrolla2/cache/src'), +); diff --git a/core/update/update/vendor/composer/autoload_psr4.php b/core/update/update/vendor/composer/autoload_psr4.php @@ -0,0 +1,11 @@ +<?php + +// autoload_psr4.php @generated by Composer + +$vendorDir = dirname(dirname(__FILE__)); +$baseDir = dirname($vendorDir); + +return array( + 'VisualAppeal\\' => array($baseDir . '/src'), + 'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'), +); diff --git a/core/update/update/vendor/composer/autoload_real.php b/core/update/update/vendor/composer/autoload_real.php @@ -0,0 +1,50 @@ +<?php + +// autoload_real.php @generated by Composer + +class ComposerAutoloaderInit28bcf3a34a1868d8d2296cf549ebcc02 +{ + private static $loader; + + public static function loadClassLoader($class) + { + if ('Composer\Autoload\ClassLoader' === $class) { + require __DIR__ . '/ClassLoader.php'; + } + } + + public static function getLoader() + { + if (null !== self::$loader) { + return self::$loader; + } + + spl_autoload_register(array('ComposerAutoloaderInit28bcf3a34a1868d8d2296cf549ebcc02', 'loadClassLoader'), true, true); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(); + spl_autoload_unregister(array('ComposerAutoloaderInit28bcf3a34a1868d8d2296cf549ebcc02', 'loadClassLoader')); + + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + + $loader->register(true); + + return $loader; + } +} + +function composerRequire28bcf3a34a1868d8d2296cf549ebcc02($file) +{ + require $file; +} diff --git a/core/update/update/vendor/composer/installed.json b/core/update/update/vendor/composer/installed.json @@ -0,0 +1,224 @@ +[ + { + "name": "vierbergenlars/php-semver", + "version": "3.0.0", + "version_normalized": "3.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/vierbergenlars/php-semver.git", + "reference": "4dc35f3804f3b127ad557b8b2255c03204dec951" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vierbergenlars/php-semver/zipball/4dc35f3804f3b127ad557b8b2255c03204dec951", + "reference": "4dc35f3804f3b127ad557b8b2255c03204dec951", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "simpletest/simpletest": "1.1.*" + }, + "time": "2013-12-21 17:10:13", + "bin": [ + "bin/semver", + "bin/update-versions" + ], + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "vierbergenlars\\SemVer\\": "src/", + "vierbergenlars\\LibJs\\": "src/" + }, + "classmap": [ + "src/vierbergenlars/SemVer/internal.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Vierbergen", + "email": "vierbergenlars@gmail.com" + } + ], + "description": "The Semantic Versioner for PHP", + "keywords": [ + "semantic", + "semver", + "versioning" + ] + }, + { + "name": "desarrolla2/cache", + "version": "v1.8.0", + "version_normalized": "1.8.0.0", + "source": { + "type": "git", + "url": "https://github.com/desarrolla2/Cache.git", + "reference": "a4fe5e0015b497099613e9cf80f37e445de077a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/desarrolla2/Cache/zipball/a4fe5e0015b497099613e9cf80f37e445de077a2", + "reference": "a4fe5e0015b497099613e9cf80f37e445de077a2", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "predis/predis": "*", + "raulfraile/ladybug": "v0.7", + "symfony/yaml": "dev-master" + }, + "time": "2014-11-06 11:33:50", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "Desarrolla2\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel González", + "homepage": "http://desarrolla2.com/", + "role": "Developer" + } + ], + "description": "Provides an cache interface for several adapters (Apc, File, Mongo, Memcached, Mysql, ... )", + "homepage": "https://github.com/desarrolla2/Cache/blob/master/README.md", + "keywords": [ + "apc", + "cache", + "file", + "memcached", + "mongo", + "mysql", + "redis" + ] + }, + { + "name": "psr/log", + "version": "1.0.0", + "version_normalized": "1.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "shasum": "" + }, + "time": "2012-12-21 11:40:51", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "Psr\\Log\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ] + }, + { + "name": "monolog/monolog", + "version": "1.12.0", + "version_normalized": "1.12.0.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "1fbe8c2641f2b163addf49cc5e18f144bec6b19f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1fbe8c2641f2b163addf49cc5e18f144bec6b19f", + "reference": "1fbe8c2641f2b163addf49cc5e18f144bec6b19f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "psr/log": "~1.0" + }, + "provide": { + "psr/log-implementation": "1.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "~2.4, >2.4.8", + "doctrine/couchdb": "~1.0@dev", + "graylog2/gelf-php": "~1.0", + "phpunit/phpunit": "~4.0", + "raven/raven": "~0.5", + "ruflin/elastica": "0.90.*", + "videlalvaro/php-amqplib": "~2.4" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-mongo": "Allow sending log messages to a MongoDB server", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "raven/raven": "Allow sending log messages to a Sentry server", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "videlalvaro/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib" + }, + "time": "2014-12-29 21:29:35", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "http://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ] + } +] diff --git a/core/update/update/vendor/desarrolla2/cache/.gitignore b/core/update/update/vendor/desarrolla2/cache/.gitignore @@ -0,0 +1,7 @@ +/build +/composer.lock +/tests/config.yml +/vendor +/.idea +*~ +*.swp diff --git a/core/update/update/vendor/desarrolla2/cache/.scrutinizer.yml b/core/update/update/vendor/desarrolla2/cache/.scrutinizer.yml @@ -0,0 +1,84 @@ +before_commands: + - "composer install --prefer-source" + +tools: + # Code Coverage + php_code_coverage: + enabled: true + test_command: phpunit + filter: + excluded_paths: + - 'vendor/*' + - 'tests/*' + + + # Code Sniffer + php_code_sniffer: + enabled: true + command: phpcs + config: + standard: PSR2 + filter: + excluded_paths: + - 'vendor/*' + + + # Copy/Paste Detector + php_cpd: + enabled: true + command: phpcpd + excluded_dirs: + - 'vendor' + + + # PHP CS Fixer (http://http://cs.sensiolabs.org/). + php_cs_fixer: + enabled: true + command: php-cs-fixer + config: + level: psr2 + filter: + excluded_paths: + - 'vendor/*' + + + # Analyzes the size and structure of a PHP project. + php_loc: + enabled: true + command: phploc + excluded_dirs: + - vendor + + + # PHP Mess Detector (http://phpmd.org). + php_mess_detector: + enabled: true + command: phpmd + config: + rulesets: + - codesize + - unusedcode + - naming + - design + - controversial + filter: + excluded_paths: + - 'vendor/*' + + + # Analyzes the size and structure of a PHP project. + php_pdepend: + enabled: true + command: pdepend + excluded_dirs: + - vendor + + # Runs Scrutinizer's PHP Analyzer Tool + php_analyzer: + enabled: true + filter: + excluded_paths: + - 'vendor/*' + + # Security Advisory Checker + sensiolabs_security_checker: true +\ No newline at end of file diff --git a/core/update/update/vendor/desarrolla2/cache/.travis.yml b/core/update/update/vendor/desarrolla2/cache/.travis.yml @@ -0,0 +1,28 @@ +language: php + +php: + - 5.3 + - 5.4 + - 5.5 + - 5.6 + - hhvm + +services: + - mongodb + - redis-server + +notifications: + email: + - daniel.gonzalez@freelancemadrid.es + +before_script: + +# Create MySQL Database + - mysql -e 'CREATE DATABASE IF NOT EXISTS `cache`;' + - mysql -e 'USE `cache`; CREATE TABLE `cache` (`hash` varchar(255) NOT NULL, `value` text NOT NULL, `ttl` int(11) NOT NULL, PRIMARY KEY (`hash`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;' + +# Install dependencies + - composer install --prefer-source + +# Set Configuration + - cp tests/config.yml.dist tests/config.yml +\ No newline at end of file diff --git a/core/update/update/vendor/desarrolla2/cache/LICENSE b/core/update/update/vendor/desarrolla2/cache/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012-2013 Desarrolla2 - http://desarrolla2.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +\ No newline at end of file diff --git a/core/update/update/vendor/desarrolla2/cache/README.md b/core/update/update/vendor/desarrolla2/cache/README.md @@ -0,0 +1,199 @@ +# Cache + +A simple cache library. Implements different adapters that you can use and change +easily by a manager or similar. + +[![Build Status](https://secure.travis-ci.org/desarrolla2/Cache.png)](http://travis-ci.org/desarrolla2/Cache) [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/desarrolla2/Cache/badges/quality-score.png?s=940939c8d0bf2056188455594f4332a002a968c2)](https://scrutinizer-ci.com/g/desarrolla2/Cache/) [![Code Coverage](https://scrutinizer-ci.com/g/desarrolla2/Cache/badges/coverage.png?s=16037142f461dcfdfd6ad57561e231881252197b)](https://scrutinizer-ci.com/g/desarrolla2/Cache/) + +[![Latest Stable Version](https://poser.pugx.org/desarrolla2/cache/v/stable.png)](https://packagist.org/packages/desarrolla2/cache) [![Total Downloads](https://poser.pugx.org/desarrolla2/cache/downloads.png)](https://packagist.org/packages/desarrolla2/cache) + + + +## Installation + +### With Composer + +It is best installed it through [packagist](http://packagist.org/packages/desarrolla2/cache) +by including +`desarrolla2/cache` in your project composer.json require: + +``` json + "require": { + // ... + "desarrolla2/cache": "dev-master" + } +``` + +### Without Composer + +You can also download it from [Github] (https://github.com/desarrolla2/Cache), +but no autoloader is provided so you'll need to register it with your own PSR-0 +compatible autoloader. + +## Usage + + +``` php +<?php + +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\NotCache; + +$cache = new Cache(new NotCache()); + +$cache->set('key', 'myKeyValue', 3600); + +// later ... + +echo $cache->get('key'); + +``` + +## Adapters + +### NotCache + +Use it if you will not implement any cache adapter is an adapter that will serve +to fool the test environments. + +### File + +Use it if you will you have dont have other cache system available in your system +or if you like to do your code more portable. + +``` php +<?php + +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\File; + +$cacheDir = '/tmp'; +$adapter = new File($cacheDir); +$adapter->setOption('ttl', 3600); +$cache = new Cache($adapter); + +``` + +### Apc + +Use it if you will you have APC cache available in your system. + +``` php +<?php + +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\Apc; + +$adapter = new Apc(); +$adapter->setOption('ttl', 3600); +$cache = new Cache($adapter); + +``` + +### Memory + +This is the fastest cache type, since the elements are stored in memory. +Cache Memory such is very volatile and is removed when the process terminates. +Also it is not shared between different processes. + +Memory cache have a option "limit", that limit the max items in cache. + +``` php +<?php + +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\Memory; + +$adapter = new Memory(); +$adapter->setOption('ttl', 3600); +$adapter->setOption('limit', 200); +$cache = new Cache($adapter); + +``` + +### Mongo + +Use it if you will you have mongodb available in your system. + +``` php +<?php + +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\Mongo; + +$server = 'mongodb://localhost:27017'; +$adapter = new Mongo($server); +$adapter->setOption('ttl', 3600); +$cache = new Cache($adapter); + +``` + +### MySQL + +Use it if you will you have mysqlnd available in your system. + +``` php +<?php + +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\MySQL; + +$adapter = new Cache(new MySQL('localhost', 'user', 'pass', 'port')); +$adapter->setOption('ttl', 3600); +$cache = new Cache($adapter); + +``` + +### Redis + +Use it if you will you have redis available in your system. + +``` php +<?php + +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\Redis; + +$adapter = new Cache(new Redis()); +$adapter->setOption('ttl', 3600); +$cache = new Cache($adapter); + +``` + +### Memcache + +Use it if you will you have memcache available in your system. + +``` php +<?php + +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\MemCache; + +$adapter = new Cache(new MemCache()); +$adapter->setOption('ttl', 3600); +$cache = new Cache($adapter); + +``` + + + + +## Coming soon + +This library implements other adapters as soon as possible, feel free to send +new adapters if you think it appropriate. + +This can be a list of pending tasks. + +* Cleanning cache +* MemcachedAdapter +* Other Adapters + +## Contact + +You can contact with me on [@desarrolla2](https://twitter.com/desarrolla2). + +## Other + +* [API docs](http://cache.desarrolla2.com/api/namespaces/Desarrolla2.Cache.html) diff --git a/core/update/update/vendor/desarrolla2/cache/build.xml b/core/update/update/vendor/desarrolla2/cache/build.xml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<project name="Cache" default="build"> + + <target name="install" depends="composer" + description="Prepare for execution"/> + + <target name="build" depends="install, init" + description="Run all tests and build everything"/> + + <target name="metrics" depends="build, phpunit, phpdoc, pdepend, phpcs, phpmd" + description="Generate Metrics"/> + + <target name="clean" + description="Cleanup build artifacts"> + <delete dir="cache"/> + <delete dir="build"/> + </target> + + <target name="init" depends="clean" + description="Prepare for build"> + <mkdir dir="cache/htmlpurifier"/> + <mkdir dir="build/api"/> + <mkdir dir="build/coverage"/> + <mkdir dir="build/pdepend"/> + <mkdir dir="build/phpcs"/> + <mkdir dir="build/phpmd"/> + </target> + + <target name="composer" + description="Composer install"> + <exec executable="composer"> + <arg value="install"/> + </exec> + </target> + + <target name="phpdoc" + description="Generate API documentation using PHPDocumentor"> + <exec executable="phpdoc"> + <arg value="-d"/> + <arg value="src"/> + <arg value="-t"/> + <arg value="build/api/"/> + </exec> + </target> + + <target name="phpunit" + description="Run unit tests using PHPUnit"> + <exec executable="phpunit"> + <arg value="-c"/> + <arg value="phpunit.xml"/> + </exec> + </target> + + <target name="pdepend" + description="Generate software metrics charts using PHP_Depend"> + <exec executable="pdepend"> + <arg value="--jdepend-chart=build/pdepend/dependencies.svg"/> + <arg value="--overview-pyramid=build/pdepend/overview-pyramid.svg"/> + <arg value="src"/> + </exec> + </target> + + <target name="phpcs" + description="Generate coding standard metrics using PHPCS"> + <exec executable="phpcs"> + <arg value="--standard=PSR2"/> + <arg value="--report-full=build/phpcs/full.txt"/> + <arg value="--report-summary=build/phpcs/sumary.txt"/> + <arg value="src"/> + <arg value="tests"/> + </exec> + </target> + + <target name="phpmd" + description="Generate coding metrics for mess code using PHPMD"> + <exec executable="phpmd"> + <arg value="src"/> + <arg value="text"/> + <arg value="codesize,unusedcode,naming,design,controversial"/> + <arg value="--reportfile"/> + <arg value="build/phpmd/report.txt"/> + </exec> + + </target> +</project> +\ No newline at end of file diff --git a/core/update/update/vendor/desarrolla2/cache/composer.json b/core/update/update/vendor/desarrolla2/cache/composer.json @@ -0,0 +1,35 @@ +{ + "name": "desarrolla2/cache", + "description": "Provides an cache interface for several adapters (Apc, File, Mongo, Memcached, Mysql, ... )", + "keywords": ["cache", "apc", "file", "memcached", "mysql", "mongo", "redis"], + "type": "library", + "license": "MIT", + "homepage": "https://github.com/desarrolla2/Cache/blob/master/README.md", + "authors": [ + { + "name": "Daniel González", + "homepage": "http://desarrolla2.com/", + "role": "Developer" + } + ], + "support": { + "issues": "https://github.com/desarrolla2/Cache/issues" + }, + "require": + { + "php": ">=5.3.0" + }, + "require-dev": + { + "raulfraile/ladybug": "v0.7", + "symfony/yaml": "dev-master", + "predis/predis": "*" + }, + "autoload": + { + "psr-0": { + "Desarrolla2\\Cache\\": "src/" + } + }, + "minimum-stability": "dev" +} diff --git a/core/update/update/vendor/desarrolla2/cache/docs/performance.md b/core/update/update/vendor/desarrolla2/cache/docs/performance.md @@ -0,0 +1,40 @@ +# Performance test + +Here are my performance tests, you can view the results ordered from faster to slower. + +| Adapter | 10.000 set | 10.000 has | 10.000 get | +| :-------------- | -----------: | -----------: | ---------: | +| NoCache | 0.0637 | 0.0482 | 0.0488 | +| Apc | 0.0961 | 0.0556 | 0.0770 | +| File | 0.6881 | 0.3426 | 0.3107 | +| Mongo | 13.8144 | 30.0203 | 24.4214 | + + +## how i run the test? + +The test its the same for all Adapters and look like this. + +``` php + <?php + + $timer = new Timer(); + for ($i = 1; $i <= 10000; $i++) { + $cache->set(md5($i), md5($i), 3600); + } + $timer->mark('10.000 set'); + for ($i = 1; $i <= 10000; $i++) { + $cache->has(md5($i)); + } + $timer->mark('10.000 has'); + for ($i = 1; $i <= 10000; $i++) { + $cache->get(md5($i)); + } + $timer->mark('10.000 get'); + +``` + + if you want run the tests them execute. + +``` sh + php test/performance/AdapterName.php +``` +\ No newline at end of file diff --git a/core/update/update/vendor/desarrolla2/cache/phpunit.xml b/core/update/update/vendor/desarrolla2/cache/phpunit.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<phpunit bootstrap="./tests/bootstrap.php" colors="true"> + + <testsuites> + <testsuite name="Desarrolla2 Cache test suite"> + <directory suffix="Test.php">./tests</directory> + </testsuite> + </testsuites> + + <filter> + <whitelist> + <directory>./Test</directory> + </whitelist> + <blacklist> + <directory>/usr/share/pear/</directory> + <directory>./vendor</directory> + <directory>./build</directory> + </blacklist> + </filter> + + <logging> + <log type="coverage-text" target="php://stdout" showUncoveredFiles="false"/> + <log type="coverage-html" target="build/coverage" title="RSS Client" charset="UTF-8" yui="true" highlight="true" + lowUpperBound="35" highLowerBound="70"/> + </logging> +</phpunit> diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/AbstractAdapter.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/AbstractAdapter.php @@ -0,0 +1,148 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * Daniel González <daniel.gonzalez@freelancemadrid.es> + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + */ + +namespace Desarrolla2\Cache\Adapter; + +use Desarrolla2\Cache\Exception\CacheException; +use Desarrolla2\Cache\Adapter\AdapterInterface; + +/** + * + * Description of AbstractAdapter + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +abstract class AbstractAdapter implements AdapterInterface +{ + /** + * @var int + */ + protected $ttl = 3600; + + /** + * @var string + */ + protected $prefix = ''; + + /** + * @var bool + */ + protected $serialize = true; + + /** + * {@inheritdoc } + */ + public function setOption($key, $value) + { + switch ($key) { + case 'ttl': + $value = (int)$value; + if ($value < 1) { + throw new CacheException('ttl cant be lower than 1'); + } + $this->ttl = $value; + break; + case 'prefix': + $this->prefix = (string)$value; + break; + case 'serialize': + $this->serialize = (bool)$value; + break; + default: + throw new CacheException('option not valid ' . $key); + } + + return true; + } + + /** + * {@inheritdoc } + */ + public function clearCache() + { + throw new Exception('not ready yet'); + } + + /** + * {@inheritdoc } + */ + public function dropCache() + { + throw new Exception('not ready yet'); + } + + /** + * + * @param string $key + * @return string + */ + protected function getKey($key) + { + //return md5($key); + return $key; + } + + /** + * Builds the key according to the prefix and other options + * + * @param string key + * @return string + */ + protected function buildKey($key) + { + return $this->prefix . $key; + } + + + /** + * Packages the data to be stored by the internal caching driver + * according to the options on the adapter. + * + * @param mixed $data + * @return mixed + */ + protected function packData($data) + { + if ($this->serialize) { + return serialize($data); + } + + return $data; + } + + /** + * Unpackages the data retrieved by the internal caching driver + * according to the options on the adapter. This will be the inverse + * of packData IF the options are set correctly. + * + * @param mixed $data + * @return mixed + */ + protected function unpackData($data) + { + if ($this->serialize) { + return unserialize($data); + } + + return $data; + } + + protected function serialize($value) + { + return serialize($value); + } + + protected function unserialize($value) + { + return unserialize($value); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/AdapterInterface.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/AdapterInterface.php @@ -0,0 +1,71 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Description of AdapterInterface + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + * @file : AdapterInterface.php , UTF-8 + * @date : Sep 4, 2012 , 12:49:07 AM + */ + +namespace Desarrolla2\Cache\Adapter; + +/** + * Interface AdapterInterface + * + * @author Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +interface AdapterInterface +{ + /** + * Delete a value from the cache + * + * @param string $key + */ + public function delete($key); + + /** + * Retrieve the value corresponding to a provided key + * + * @param string $key + * @return mixed + */ + public function get($key); + + /** + * Retrieve the if value corresponding to a provided key exist + * + * @param string $key + * @return bool + */ + public function has($key); + + /** + * * Add a value to the cache under a unique key + * + * @param string $key + * @param mixed $value + * @param int $ttl + */ + public function set($key, $value, $ttl = null); + + /** + * Set option for Adapter + * + * @param string $key + * @param string $value + */ + public function setOption($key, $value); + + /** + * clean all expired records from cache + */ + public function clearCache(); + + /** + * clear all cache + */ + public function dropCache(); +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/Apc.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/Apc.php @@ -0,0 +1,113 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Description of Apc + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + */ + +namespace Desarrolla2\Cache\Adapter; + +use Desarrolla2\Cache\Adapter\AbstractAdapter; +use Desarrolla2\Cache\Exception\ApcCacheException; + +/** + * Class Apc + * + * @author Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +class Apc extends AbstractAdapter +{ + + /** + * Delete a value from the cache + * + * @param string $key + * @throws \Desarrolla2\Cache\Exception\ApcCacheException + */ + public function delete($key) + { + if ($this->has($key)) { + $tKey = $this->getKey($key); + if (!\apc_delete($tKey)) { + throw new ApcCacheException('Error deleting data with the key "' . $key . '" from the APC cache.'); + } + } + } + + /** + * {@inheritdoc } + */ + public function get($key) + { + if ($this->has($key)) { + $tKey = $this->getKey($key); + if (!$data = \apc_fetch($tKey)) { + throw new ApcCacheException('Error fetching data with the key "' . $key . '" from the APC cache.'); + } + + return $this->unserialize($data); + } + + return null; + } + + /** + * {@inheritdoc } + */ + public function has($key) + { + $tKey = $this->getKey($key); + if (function_exists("\apc_exists")) { + return (boolean)\apc_exists($tKey); + } else { + \apc_fetch($tKey, $result); + + return (boolean)$result; + } + } + + /** + * {@inheritdoc } + */ + public function set($key, $value, $ttl = null) + { + $tKey = $this->getKey($key); + $tValue = $this->serialize($value); + if (!$ttl) { + $ttl = $this->ttl; + } + if (!\apc_store($tKey, $tValue, $ttl)) { + throw new ApcCacheException('Error saving data with the key "' . $key . '" to the APC cache.'); + } + } + + /** + * {@inheritdoc } + */ + public function setOption($key, $value) + { + switch ($key) { + case 'ttl': + $value = (int)$value; + if ($value < 1) { + throw new ApcCacheException('ttl cant be lower than 1'); + } + $this->ttl = $value; + break; + default: + throw new ApcCacheException('option not valid ' . $key); + } + + return true; + } + + /** + * {@inheritdoc } + */ + public function dropCache() { + apc_clear_cache("user"); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/File.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/File.php @@ -0,0 +1,213 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Description of File + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + */ + +namespace Desarrolla2\Cache\Adapter; + +use Desarrolla2\Cache\Adapter\AbstractAdapter; +use Desarrolla2\Cache\Exception\FileCacheException; + +/** + * Class File + * + * @author Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +class File extends AbstractAdapter +{ + + const CACHE_FILE_PREFIX = '__'; + const CACHE_FILE_SUBFIX = '.php.cache'; + + /** + * @var string + */ + protected $cacheDir; + + public function __construct($cacheDir = null) + { + if (!$cacheDir) { + $cacheDir = realpath(sys_get_temp_dir()) . '/cache'; + } + $this->cacheDir = (string)$cacheDir; + if (!is_dir($this->cacheDir)) { + if (!mkdir($this->cacheDir, 0777, true)) { + throw new FileCacheException($this->cacheDir . ' is not writable'); + } + } + if (!is_writable($this->cacheDir)) { + throw new FileCacheException($this->cacheDir . ' is not writable'); + } + } + + /** + * Delete a value from the cache + * + * @param string $key + */ + public function delete($key) + { + $tKey = $this->getKey($key); + $cacheFile = $this->getCacheFile($tKey); + $this->deleteFile($cacheFile); + } + + /** + * {@inheritdoc } + */ + public function get($key) + { + if ($data = $this->getData($key)) { + return $data; + } + + return false; + } + + /** + * {@inheritdoc } + */ + public function has($key) + { + if ($this->getData($key)) { + return true; + } + + return false; + } + + /** + * {@inheritdoc } + */ + public function set($key, $value, $ttl = null) + { + $tKey = $this->getKey($key); + $cacheFile = $this->getCacheFile($tKey); + $tValue = $this->serialize($value); + if (!($ttl)) { + $ttl = $this->ttl; + } + $item = $this->serialize( + array( + 'value' => $tValue, + 'ttl' => (int)$ttl + time(), + ) + ); + if (!file_put_contents($cacheFile, $item)) { + throw new FileCacheException('Error saving data with the key "' . $key . '" to the cache file.'); + } + } + + /** + * {@inheritdoc } + */ + public function setOption($key, $value) + { + switch ($key) { + case 'ttl': + $value = (int)$value; + if ($value < 1) { + throw new FileCacheException('ttl cant be lower than 1'); + } + $this->ttl = $value; + break; + default: + throw new FileCacheException('option not valid ' . $key); + } + + return true; + } + + /** + * {@inheritdoc } + */ + public function clearCache() + { + throw new Exception('not ready yet'); + } + + /** + * {@inheritdoc } + */ + public function dropCache() + { + foreach (scandir($this->cacheDir) as $fileName) { + $cacheFile = $this->cacheDir . + DIRECTORY_SEPARATOR . + $fileName; + $this->deleteFile($cacheFile); + } + } + + /** + * Delete file + * + * @param type $cacheFile + * @return bool + */ + protected function deleteFile($cacheFile) + { + if (is_file($cacheFile)) { + return unlink($cacheFile); + } + + return false; + } + + /** + * Get the specified cache file + */ + protected function getCacheFile($fileName) + { + return $this->cacheDir . + DIRECTORY_SEPARATOR . + self::CACHE_FILE_PREFIX . + $fileName . + self::CACHE_FILE_SUBFIX; + } + + /** + * Get data value from file cache + * + * @param type $key + * @return mixed + * @throws FileCacheException + */ + protected function getData($key) + { + $tKey = $this->getKey($key); + $cacheFile = $this->getCacheFile($tKey); + if (!file_exists($cacheFile)) { + return; + } + if (!$data = unserialize(file_get_contents($cacheFile))) { + throw new FileCacheException( + 'Error with the key "' . $key . '" in cache file ' . $cacheFile + ); + } + if (!array_key_exists('value', $data)) { + throw new FileCacheException( + 'Error with the key "' . $key . '" in cache file ' . $cacheFile . ', value not exist' + ); + } + if (!array_key_exists('ttl', $data)) { + throw new FileCacheException( + 'Error with the key "' . $key . '" in cache file ' . $cacheFile . ', ttl not exist' + ); + } + if (time() > $data['ttl']) { + $this->delete($key); + + return false; + } + + return $this->unserialize($data['value']); + + return; + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/MemCache.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/MemCache.php @@ -0,0 +1,97 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * Daniel González <daniel.gonzalez@freelancemadrid.es> + * + */ + +namespace Desarrolla2\Cache\Adapter; + +use Desarrolla2\Cache\Adapter\AbstractAdapter; +use \Memcache as BaseMemCache; + +/** + * + * Description of Mencache + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +class MemCache extends AbstractAdapter +{ + /** + * + * @var \Memcache + */ + protected $server; + + public function __construct() + { + $this->server = new BaseMemcache(); + $this->server->addServer('localhost', 11211); + } + + /** + * + * @param string $host + * @param string $port + */ + public function addServer($host, $port) + { + $this->server->addServer($host, $port); + } + + /** + * Delete a value from the cache + * + * @param string $key + */ + public function delete($key) + { + $tKey = $this->getKey($key); + $this->server->delete($tKey); + } + + /** + * {@inheritdoc } + */ + public function get($key) + { + $tKey = $this->getKey($key); + $data = $this->server->get($tKey); + + return $this->unserialize($data); + } + + /** + * {@inheritdoc } + */ + public function has($key) + { + $tKey = $this->getKey($key); + if ($this->server->get($tKey)) { + return true; + } + + return false; + } + + /** + * {@inheritdoc } + */ + public function set($key, $value, $ttl = null) + { + $tKey = $this->getKey($key); + $tValue = $this->serialize($value); + if (!$ttl) { + $ttl = $this->ttl; + } + $this->server->set($tKey, $tValue, false, time() + $ttl); + } + + public function dropCache($delay = 0) { + $this->server->flush($delay); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/Memcached.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/Memcached.php @@ -0,0 +1,128 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * Daniel González <daniel.gonzalez@freelancemadrid.es> + * + */ + +namespace Desarrolla2\Cache\Adapter; + +use Desarrolla2\Cache\Adapter\AbstractAdapter; +use \Memcached as BaseMemcached; + +/** + * + * Simple Memcached Adapter + * + * @author : RJ Garcia <rj@bighead.net> + */ +class Memcached extends AbstractAdapter +{ + /** + * + * @var \Memcached + */ + public $adapter; + + /** + * Accept three types of inputs: a \Memcached instance already to use + * as the internal adapter, an array of servers which will be added to + * a memcached instance, or null, and we'll just build a default memcached + * instance + * + * @param mixed $data + * + */ + public function __construct($data = null, $options = []) + { + if ($data instanceof BaseMemcached) { + $this->adapter = $data; + } else { + $this->adapter = new BaseMemcached(); + } + + if (is_array($data)) { + /* if array, then the user supplied an array of servers */ + foreach ($data as $s) { + $this->adapter->addServer($s['host'], $s['port'], $s['weight']); + } + } + + $this->setOption($options); + } + + /** + * + * @param string $host + * @param int $port + * @param int $weight + * + */ + public function addServer($host, $port, $weight = 0) + { + $this->adapter->addServer($host, $port, $weight); + } + + /** + * Delete a value from the cache + * + * @param string $key + */ + public function delete($key) + { + $this->adapter->delete($this->buildKey($key)); + } + + /** + * {@inheritdoc } + */ + public function get($key) + { + return $this->unpackData( + $this->adapter->get( + $this->buildKey($key) + ) + ); + } + + /** + * {@inheritdoc } + */ + public function has($key) + { + /* It seems that the most efficient way to check has in memcached is + by using an append with an empty string. However, we need to make + sure that OPT_COMPRESSION is turned off because you can't append + if you compressing data */ + + /* store for later use */ + $cur_compression = $this->adapter->getOption(BaseMemcached::OPT_COMPRESSION); + + /* set compression off */ + $this->adapter->setOption(BaseMemcached::OPT_COMPRESSION, false); + + $res = $this->adapter->append( + $this->buildKey($key), + '' + ); + + $this->adapter->setOption(BaseMemcached::OPT_COMPRESSION, $cur_compression); + + return $res; + } + + /** + * {@inheritdoc } + */ + public function set($key, $value, $ttl = null) + { + $this->adapter->set( + $this->buildKey($key), + $this->packData($value), + $ttl ?: $this->ttl + ); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/Memory.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/Memory.php @@ -0,0 +1,117 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * Daniel González <daniel.gonzalez@freelancemadrid.es> + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + */ + +namespace Desarrolla2\Cache\Adapter; + +use Desarrolla2\Cache\Adapter\AbstractAdapter; + +/** + * + * Description of Memory + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +class Memory extends AbstractAdapter +{ + + /** + * + * @var int + */ + protected $limit = 100; + + /** + * + * @var array + */ + protected $cache = array(); + + /** + * Delete a value from the cache + * + * @param string $key + */ + public function delete($key) + { + $tKey = $this->getKey($key); + unset($this->cache[$tKey]); + } + + /** + * {@inheritdoc } + */ + public function get($key) + { + if ($this->has($key)) { + $tKey = $this->getKey($key); + + return $this->unserialize($this->cache[$tKey]['value']); + } + + return false; + } + + /** + * {@inheritdoc } + */ + public function has($key) + { + $tKey = $this->getKey($key); + if (isset($this->cache[$tKey])) { + $data = $this->cache[$tKey]; + if (time() < $data['ttl']) { + return true; + } else { + $this->delete($key); + } + } + + return false; + } + + /** + * {@inheritdoc } + */ + public function set($key, $value, $ttl = null) + { + while (count($this->cache) >= $this->limit) { + array_shift($this->cache); + } + $tKey = $this->getKey($key); + if (!$ttl) { + $ttl = $this->ttl; + } + $this->cache[$tKey] = array( + 'value' => serialize($value), + 'ttl' => $ttl + time(), + ); + } + + /** + * {@inheritdoc } + */ + public function setOption($key, $value) + { + switch ($key) { + case 'limit': + $value = (int) $value; + if ($value < 1) { + throw new MemoryCacheException('limit cant be lower than 1'); + } + $this->limit = $value; + + return true; + } + + return parent::setOption($key, $value); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/Mongo.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/Mongo.php @@ -0,0 +1,171 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * Daniel González <daniel.gonzalez@freelancemadrid.es> + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + */ + +namespace Desarrolla2\Cache\Adapter; + +use Desarrolla2\Cache\Adapter\AbstractAdapter; +use Desarrolla2\Cache\Exception\MongoCacheException; +use Mongo as MongoBase; + +/** + * + * Description of Mongo + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +class Mongo extends AbstractAdapter +{ + + /** + * @var \MongoDB + */ + protected $database; + + /** + * @var \Mongo + */ + protected $mongo; + + /** + * + * @param string $server + * @param array $options + * @param string $database + * @throws \Desarrolla2\Cache\Exception\MongoCacheException + */ + public function __construct( + $server = 'mongodb://localhost:27017', + $options = array('connect' => true), + $database = '__cache' + ) { + $this->mongo = new MongoBase($server, $options); + if (!$this->mongo) { + throw new MongoCacheException(' Mongo connection fails '); + } + $this->database = $this->mongo->selectDB($database); + } + + /** + * Delete a value from the cache + * + * @param string $key + */ + public function delete($key) + { + $tKey = $this->getKey($key); + $this->database->items->remove(array('key' => $tKey)); + } + + /** + * {@inheritdoc } + * + * @param string $key + */ + public function get($key) + { + if ($data = $this->getData($key)) { + return $data; + } + + return false; + } + + /** + * {@inheritdoc } + * + * @param string $key + * @return bool + */ + public function has($key) + { + if ($this->getData($key)) { + return true; + } + + return false; + } + + /** + * {@inheritdoc } + * + * @param string $key + * @param mixed $value + * @param null $ttl + */ + public function set($key, $value, $ttl = null) + { + $tKey = $this->getKey($key); + $tValue = $this->serialize($value); + if (!$ttl) { + $ttl = $this->ttl; + } + $item = array( + 'key' => $tKey, + 'value' => $tValue, + 'ttl' => (int)$ttl + time(), + ); + $this->delete($key); + $this->database->items->insert($item); + } + + /** + * {@inheritdoc } + * + * @param string $key + * @param string $value + * @return bool + * @throws \Desarrolla2\Cache\Exception\MongoCacheException + */ + public function setOption($key, $value) + { + switch ($key) { + case 'ttl': + $value = (int)$value; + if ($value < 1) { + throw new MongoCacheException('ttl cant be lower than 1'); + } + $this->ttl = $value; + break; + default: + throw new MongoCacheException('option not valid ' . $key); + } + + return true; + } + + /** + * Get data value from file cache + * + * @param string $key + * @param bool $delete + * @return mixed + */ + protected function getData($key, $delete = true) + { + $tKey = $this->getKey($key); + $data = $this->database->items->findOne(array('key' => $tKey)); + if (count($data)) { + $data = array_values($data); + if (time() > $data[3]) { + if ($delete) { + $this->delete($key); + } + + return false; + } + + return $this->unserialize($data[2]); + } + + return false; + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/MySQL.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/MySQL.php @@ -0,0 +1,173 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * Daniel González <daniel.gonzalez@freelancemadrid.es> + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + */ + +namespace Desarrolla2\Cache\Adapter; + +use Desarrolla2\Cache\Adapter\AdapterInterface; +use Desarrolla2\Cache\Adapter\AbstractAdapter; +use \mysqli; + +/** + * + * Description of MySQL + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +class MySQL extends AbstractAdapter implements AdapterInterface +{ + + /** + * + * @var \mysqli + */ + protected $mysql; + + public function __construct( + $host = 'localhost', + $user = 'root', + $password = '', + $database = 'cache', + $port = '3306' + ) { + $this->mysql = new mysqli($host, $user, $password, $database, $port); + } + + /** + * Destructor + */ + public function __destruct() + { + $this->mysql->close(); + } + + /** + * Delete a value from the cache + * + * @param string $key + */ + public function delete($key) + { + $tKey = $this->getKey($key); + $query = 'DELETE FROM cache WHERE hash = \'' . $tKey . '\';'; + + $this->query($query); + } + + /** + * {@inheritdoc } + */ + public function get($key) + { + $tKey = $this->getKey($key); + $query = 'SELECT value FROM cache WHERE hash = \'' . $tKey . '\'' . + ' AND ttl >= ' . time() . ';'; + $res = $this->fetchObject($query); + if ($res) { + return $this->unserialize($res->value); + } + + return false; + } + + /** + * {@inheritdoc } + */ + public function has($key) + { + $tKey = $this->getKey($key); + $query = 'SELECT COUNT(*) AS items FROM cache WHERE hash = ' . + '\'' . $tKey . '\' AND ' . + ' ttl >= ' . time() . ';'; + $res = $this->fetchObject($query); + if (!$res) { + return false; + } + if ($res->items == '0') { + return false; + } + + return true; + } + + /** + * {@inheritdoc } + */ + public function set($key, $value, $ttl = null) + { + $this->delete($key); + $tKey = $this->getKey($key); + $tValue = $this->escape( + $this->serialize($value) + ); + if (!($ttl)) { + $ttl = $this->ttl; + } + $tTtl = $ttl + time(); + $query = ' INSERT INTO cache (hash, value, ttl) VALUES (' . + '\'' . $tKey . '\', ' . + '\'' . $tValue . '\', ' . + '\'' . $tTtl . '\' );'; + $this->query($query); + } + + /** + * {@inheritdoc } + */ + protected function getKey($key) + { + $tKey = parent::getKey($key); + + return $this->escape($tKey); + } + + /** + * + * @param string $query + * @param int|string $mode + * @return mixed + */ + protected function fetchObject($query, $mode = MYSQLI_STORE_RESULT) + { + $res = $this->query($query, $mode); + if ($res) { + return $res->fetch_object(); + } + + return false; + } + + /** + * + * @param string $query + * @param int|string $mode + * @return mixed + */ + protected function query($query, $mode = MYSQLI_STORE_RESULT) + { + $res = $this->mysql->query($query, $mode); + if ($res) { + return $res; + } + + return false; + } + + /** + * + * @param string $key + * @return string + */ + private function escape($key) + { + return $this->mysql->real_escape_string($key); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/NotCache.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/NotCache.php @@ -0,0 +1,66 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Description of NoCache + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + * @file : NoCache.php , UTF-8 + * @date : Sep 4, 2012 , 1:00:01 AM + */ + +namespace Desarrolla2\Cache\Adapter; + +use Desarrolla2\Cache\Adapter\AbstractAdapter; + +/** + * Class NotCache + * + * @author Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +class NotCache extends AbstractAdapter +{ + + /** + * Delete a value from the cache + * + * @param string $key + */ + public function delete($key) + { + } + + /** + * {@inheritdoc } + */ + public function get($key) + { + return false; + } + + /** + * {@inheritdoc } + */ + public function has($key) + { + return false; + } + + /** + * {@inheritdoc } + */ + public function set($key, $value, $ttl = null) + { + return false; + } + + /** + * {@inheritdoc } + */ + public function setOption($key, $value) + { + return false; + } + +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/Redis.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Adapter/Redis.php @@ -0,0 +1,96 @@ +<?php +/** + * This file is part of the Cache project. + * + * Copyright (c) + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + */ + +namespace Desarrolla2\Cache\Adapter; + +use Desarrolla2\Cache\Adapter\AdapterInterface; +use Desarrolla2\Cache\Adapter\AbstractAdapter; +use Predis\Client; + + +/** + * Class Redis + * + * @author Daniel González <daniel.gonzalez@freelancemadrid.es> + */ + +class Redis extends AbstractAdapter +{ + + /** + * @var Client + */ + protected $client; + + function __construct() + { + $this->client = new Client(); + } + + function __destruct() + { + $this->client->disconnect(); + } + + /** + * Delete a value from the cache + * + * @param string $key + */ + public function delete($key) + { + $cmd = $this->client->createCommand('DEL'); + $cmd->setArguments(array($key)); + + $this->client->executeCommand($cmd); + } + + /** + * Retrieve the value corresponding to a provided key + * + * @param string $key + * @return mixed + */ + public function get($key) + { + return $this->client->get($key); + } + + /** + * Retrieve the if value corresponding to a provided key exist + * + * @param string $key + * @return bool + */ + public function has($key) + { + $cmd = $this->client->createCommand('EXISTS'); + $cmd->setArguments(array($key)); + + return $this->client->executeCommand($cmd); + } + + /** + * * Add a value to the cache under a unique key + * + * @param string $key + * @param mixed $value + * @param int $ttl + */ + public function set($key, $value, $ttl = null) + { + $this->client->set($key, $value); + if ($ttl) { + $cmd = $this->client->createCommand('EXPIRE'); + $cmd->setArguments(array($key, $ttl)); + $this->client->executeCommand($cmd); + } + } +} +\ No newline at end of file diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Cache.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Cache.php @@ -0,0 +1,135 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Description of Cache + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + * @file : Cache.php , UTF-8 + * @date : Sep 4, 2012 , 12:45:14 AM + */ + +namespace Desarrolla2\Cache; + +use Desarrolla2\Cache\CacheInterface; +use Desarrolla2\Cache\Exception\AdapterNotSetException; +use Desarrolla2\Cache\Adapter\AdapterInterface; + +/** + * Class Cache + * + * @author Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +class Cache implements CacheInterface +{ + const VERSION = 1.7; + + /** + * + * @var Adapter\AdapterInterface + */ + protected $adapter; + + /** + * @param AdapterInterface $adapter + */ + public function __construct(AdapterInterface $adapter = null) + { + if ($adapter) { + $this->setAdapter($adapter); + } + } + + /** + * {@inheritdoc } + * + * @param string $key + */ + public function delete($key) + { + $this->getAdapter()->delete($key); + } + + /** + * {@inheritdoc } + * + * @param string $key + */ + public function get($key) + { + return $this->getAdapter()->get($key); + } + + /** + * {@inheritdoc } + */ + public function getAdapter() + { + if (!$this->adapter) { + throw new AdapterNotSetException('Required Adapter'); + } + + return $this->adapter; + } + + /** + * {@inheritdoc } + * + * @param string $key + */ + public function has($key) + { + return $this->getAdapter()->has($key); + } + + /** + * {@inheritdoc } + * + * @param string $key + * @param mixed $value + * @param null $ttl + */ + public function set($key, $value, $ttl = null) + { + $this->getAdapter()->set($key, $value, $ttl); + } + + /** + * {@inheritdoc } + * + * @param Adapter\AdapterInterface $adapter + */ + public function setAdapter(AdapterInterface $adapter) + { + $this->adapter = $adapter; + } + + /** + * {@inheritdoc } + * + * @param string $key + * @param string $value + * @return mixed + */ + public function setOption($key, $value) + { + return $this->adapter->setOption($key, $value); + } + + /** + * {@inheritdoc } + */ + public function clearCache() + { + $this->adapter->clearCache(); + } + + /** + * {@inheritdoc } + */ + public function dropCache() + { + $this->adapter->dropCache(); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/CacheInterface.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/CacheInterface.php @@ -0,0 +1,84 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Description of CacheInterface + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + * @file : CacheInterface.php , UTF-8 + * @date : Sep 4, 2012 , 12:45:25 AM + */ + +namespace Desarrolla2\Cache; + +/** + * Interface CacheInterface + * + * @author Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +interface CacheInterface +{ + + /** + * Delete a value from the cache + * + * @param string $key + */ + public function delete($key); + + /** + * Retrieve the value corresponding to a provided key + * + * @param string $key + */ + public function get($key); + + /** + * + * @return \Desarrolla2\Cache\Adapter\AdapterInterface $adapter + * @throws Exception + */ + public function getAdapter(); + + /** + * Retrieve the if value corresponding to a provided key exist + * + * @param string $key + */ + public function has($key); + + /** + * * Add a value to the cache under a unique key + * + * @param string $key + * @param mixed $value + * @param int $ttl + */ + public function set($key, $value, $ttl = null); + + /** + * Set Adapter interface + * + * @param \Desarrolla2\Cache\Adapter\AdapterInterface $adapter + */ + public function setAdapter(\Desarrolla2\Cache\Adapter\AdapterInterface $adapter); + + /** + * Set option for Adapter + * + * @param string $key + * @param string $value + */ + public function setOption($key, $value); + + /** + * clean all expired records from cache + */ + public function clearCache(); + + /** + * clear all cache + */ + public function dropCache(); +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/AdapterNotSetException.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/AdapterNotSetException.php @@ -0,0 +1,18 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Description of AdapterNotSetException + * + * @author : Daniel González Cerviño <daniel.gonzalez@freelancemadrid.es> + * @file : AdapterNotSetException.php , UTF-8 + * @date : Sep 4, 2012 , 4:06:46 PM + */ + +namespace Desarrolla2\Cache\Exception; + +class AdapterNotSetException extends \Exception +{ + +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/ApcCacheException.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/ApcCacheException.php @@ -0,0 +1,18 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Description of ApcCacheException + * + * @author : Daniel González Cerviño <daniel.gonzalez@freelancemadrid.es> + * @file : ApcCacheException.php , UTF-8 + * @date : Sep 14, 2012 , 12:17:39 PM + */ + +namespace Desarrolla2\Cache\Exception; + +class ApcCacheException extends \Exception +{ + +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/CacheException.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/CacheException.php @@ -0,0 +1,26 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * Daniel González <daniel.gonzalez@freelancemadrid.es> + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + */ + +namespace Desarrolla2\Cache\Exception; + +/** + * + * Description of CacheException + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + * @file : CacheException.php , UTF-8 + * @date : Jun 30, 2013 , 4:04:09 PM + */ +class CacheException extends \Exception +{ + //put your code here +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/FileCacheException.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/FileCacheException.php @@ -0,0 +1,18 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Description of ApcCacheException + * + * @author : Daniel González Cerviño <daniel.gonzalez@freelancemadrid.es> + * @file : ApcCacheException.php , UTF-8 + * @date : Sep 14, 2012 , 12:17:39 PM + */ + +namespace Desarrolla2\Cache\Exception; + +class FileCacheException extends \Exception +{ + +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/MemcacheException.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/MemcacheException.php @@ -0,0 +1,26 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * Daniel González <daniel.gonzalez@freelancemadrid.es> + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + */ + +namespace Desarrolla2\Cache\Exception; + +/** + * + * Description of MemcachedException + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + * @file : MemcachedException.php , UTF-8 + * @date : Oct 24, 2012 , 12:10:58 AM + */ +class MemcacheException extends \Exception +{ + +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/MemoryCacheException.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/MemoryCacheException.php @@ -0,0 +1,26 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * Daniel González <daniel.gonzalez@freelancemadrid.es> + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + */ + +namespace Desarrolla2\Cache\Exception; + +/** + * + * Description of MemoryCacheException + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + * @file : MemoryCacheException.php , UTF-8 + * @date : Jun 30, 2013 , 4:01:55 PM + */ +class MemoryCacheException extends \Exception +{ + +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/MongoCacheException.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/MongoCacheException.php @@ -0,0 +1,26 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * Daniel González <daniel.gonzalez@freelancemadrid.es> + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + */ + +namespace Desarrolla2\Cache\Exception; + +/** + * + * Description of MongoCacheException + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + * @file : MongoCacheException.php , UTF-8 + * @date : Nov 25, 2012 , 1:54:07 AM + */ +class MongoCacheException extends \Exception +{ + //put your code here +} diff --git a/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/MySQLCacheException.php b/core/update/update/vendor/desarrolla2/cache/src/Desarrolla2/Cache/Exception/MySQLCacheException.php @@ -0,0 +1,25 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * Daniel González <daniel.gonzalez@freelancemadrid.es> + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + */ +namespace Desarrolla2\Cache\Exception; + +/** + * + * Description of MySQLCacheException + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + * @file : MySQLCacheException.php , UTF-8 + * @date : Oct 24, 2012 , 12:13:25 AM + */ +class MySQLCacheException extends \Exception +{ + //put your code here +} diff --git a/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/AbstractCacheTest.php b/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/AbstractCacheTest.php @@ -0,0 +1,148 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * Daniel González <daniel.gonzalez@freelancemadrid.es> + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + */ + +namespace Desarrolla2\Cache\Adapter\Test; + + +use Symfony\Component\Yaml\Yaml; + +/** + * + * Description of AbstracCacheTest + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +abstract class AbstractCacheTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @var \Desarrolla2\Cache\Cache + */ + protected $cache; + + /** + * @var array + */ + protected $config = array(); + + + public function setup() + { + $configurationFile = realpath(__DIR__ . '/../../../../') . '/config.yml'; + + if (!is_file($configurationFile)) { + throw new \Exception(' Configuration file not found in "' . $configurationFile . '" '); + } + $this->config = Yaml::parse( + file_get_contents( + $configurationFile + ) + ); + } + + /** + * @return array + */ + public function dataProvider() + { + return array( + array('key1', 'value', 1), + array('key2', 'value', 100), + array('key3', 'value', null), + ); + } + + /** + * @return array + */ + public function dataProviderForOptions() + { + return array( + array('ttl', 100), + ); + } + + /** + * + * @dataProvider dataProvider + * @param string $key + * @param string $value + * @param type $ttl + */ + public function testHash($key, $value, $ttl) + { + $this->assertNull($this->cache->delete($key)); + $this->assertFalse($this->cache->has($key)); + $this->assertNull($this->cache->set($key, $value, $ttl)); + $this->assertTrue($this->cache->has($key)); + } + + /** + * + * @dataProvider dataProvider + * @param string $key + * @param string $value + * @param int $ttl + */ + public function testGet($key, $value, $ttl) + { + $this->cache->set($key, $value, $ttl); + $this->assertEquals($value, $this->cache->get($key)); + } + + /** + * + * @dataProvider dataProvider + * @param string $key + * @param string $value + * @param int $ttl + */ + public function testDelete($key, $value, $ttl) + { + $this->cache->set($key, $value, $ttl); + $this->assertNull($this->cache->delete($key)); + $this->assertFalse($this->cache->has($key)); + } + + /** + * @dataProvider dataProviderForOptions + * @param string $key + * @param mixed $value + */ + public function testSetOption($key, $value) + { + $this->assertTrue($this->cache->setOption($key, $value)); + } + + /** + * @dataProvider dataProviderForOptionsException + * @param string $key + * @param mixed $value + * @param $expectedException + */ + public function testSetOptionException($key, $value, $expectedException) + { + $this->setExpectedException($expectedException); + $this->cache->setOption($key, $value); + } + + + public function testHasWithTtlExpired() + { + $key = 'key1'; + $value = 'value1'; + $ttl = 1; + $this->cache->set($key, $value, $ttl); + sleep($ttl + 1); + $this->assertFalse($this->cache->has($key)); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/ApcCacheTest.php b/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/ApcCacheTest.php @@ -0,0 +1,40 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Description of CacheTest + * + * @author : Daniel González Cerviño <daniel.gonzalez@freelancemadrid.es> + */ + +namespace Desarrolla2\Cache\Adapter\Test; + +use Desarrolla2\Cache\Adapter\Test\AbstractCacheTest; +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\Apc; + +class ApcCacheTest extends AbstractCacheTest +{ + public function setUp() + { + parent::setup(); + if (!extension_loaded('apc') || !ini_get('apc.enable_cli')) { + $this->markTestSkipped( + 'The APC extension is not available.' + ); + } + $this->cache = new Cache(new Apc()); + } + + /** + * @return array + */ + public function dataProviderForOptionsException() + { + return array( + array('ttl', 0, '\Desarrolla2\Cache\Exception\ApcCacheException'), + array('file', 100, '\Desarrolla2\Cache\Exception\ApcCacheException'), + ); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/FileTest.php b/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/FileTest.php @@ -0,0 +1,41 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Description of CacheTest + * + * @author : Daniel González Cerviño <daniel.gonzalez@freelancemadrid.es> + */ + +namespace Desarrolla2\Cache\Adapter\Test; + +use Desarrolla2\Cache\Adapter\Test\AbstractCacheTest; +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\File; + +/** + * Class FileTest + * + * @author Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +class FileTest extends AbstractCacheTest +{ + + public function setUp() + { + parent::setup(); + $this->cache = new Cache(new File($this->config['file']['dir'])); + } + + /** + * @return array + */ + public function dataProviderForOptionsException() + { + return array( + array('ttl', 0, '\Desarrolla2\Cache\Exception\FileCacheException'), + array('file', 100, '\Desarrolla2\Cache\Exception\FileCacheException'), + ); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/MemCacheTest.php b/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/MemCacheTest.php @@ -0,0 +1,51 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * Daniel González <daniel.gonzalez@freelancemadrid.es> + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + */ + +namespace Desarrolla2\Cache\Adapter\Test; + +use Desarrolla2\Cache\Adapter\Test\AbstractCacheTest; +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\Memcache; + +/** + * + * Description of MemoryTest + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + */ + +class MemCacheTest extends AbstractCacheTest +{ + public function setUp() + { + parent::setup(); + if (!extension_loaded('memcached')) { + $this->markTestSkipped( + 'The Memcache extension is not available.' + ); + } + $adapter = new MemCache(); + $adapter->addServer('localhost', 11211); + $this->cache = new Cache($adapter); + } + + /** + * @return array + */ + public function dataProviderForOptionsException() + { + return array( + array('ttl', 0, '\Desarrolla2\Cache\Exception\CacheException'), + array('file', 100, '\Desarrolla2\Cache\Exception\CacheException'), + ); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/MemoryTest.php b/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/MemoryTest.php @@ -0,0 +1,63 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * Daniel González <daniel.gonzalez@freelancemadrid.es> + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + */ + +namespace Desarrolla2\Cache\Adapter\Test; + +use Desarrolla2\Cache\Adapter\Test\AbstractCacheTest; +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\Memory; + +/** + * + * Description of MemoryTest + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +class MemoryTest extends AbstractCacheTest +{ + public function setUp() + { + $this->cache = new Cache(new Memory()); + } + + /** + * @return array + */ + public function dataProviderForOptions() + { + return array( + array('ttl', 100), + array('limit', 100), + ); + } + + /** + * @return array + */ + public function dataProviderForOptionsException() + { + return array( + array('ttl', 0, '\Desarrolla2\Cache\Exception\CacheException'), + array('file', 100, '\Desarrolla2\Cache\Exception\CacheException'), + ); + } + + public function testExceededLimit() + { + $limit = 1; + $this->cache->setOption('limit', $limit); + for ($i = 0; $i <= $limit; $i++) { + $this->cache->set($i, $i); + } + $this->assertFalse($this->cache->has($i)); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/MongoTest.php b/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/MongoTest.php @@ -0,0 +1,48 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * Daniel González <daniel.gonzalez@freelancemadrid.es> + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + */ + +namespace Desarrolla2\Cache\Adapter\Test; + +use Desarrolla2\Cache\Adapter\Test\AbstractCacheTest; +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\Mongo; + +/** + * + * Description of MongoTest + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +class MongoTest extends AbstractCacheTest +{ + public function setUp() + { + parent::setup(); + if (!class_exists('Mongo')) { + $this->markTestSkipped( + 'The Mongo extension is not available.' + ); + } + $this->cache = new Cache(new Mongo($this->config['mongo']['dns'])); + } + + /** + * @return array + */ + public function dataProviderForOptionsException() + { + return array( + array('ttl', 0, '\Desarrolla2\Cache\Exception\MongoCacheException'), + array('file', 100, '\Desarrolla2\Cache\Exception\MongoCacheException'), + ); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/MySQLTest.php b/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/MySQLTest.php @@ -0,0 +1,65 @@ +<?php + +/** + * This file is part of the Cache project. + * + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + */ + +namespace Desarrolla2\Cache\Adapter\Test; + +use Desarrolla2\Cache\Adapter\Test\AbstractCacheTest; +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\MySQL; + +/** + * + * Description of MemoryTest + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +class MySQLTest extends AbstractCacheTest +{ + + public function setUp() + { + parent::setup(); + if (!extension_loaded('mysqlnd')) { + $this->markTestSkipped( + 'The MySQLnd extension is not available.' + ); + } + $this->cache = new Cache( + new MySQL( + $this->config['mysql']['host'], + $this->config['mysql']['user'], + $this->config['mysql']['password'], + $this->config['mysql']['database'], + $this->config['mysql']['port'] + ) + ); + } + + /** + * @return array + */ + public function dataProviderForOptions() + { + return array( + array('ttl', 100), + ); + } + + /** + * @return array + */ + public function dataProviderForOptionsException() + { + return array( + array('ttl', 0, '\Desarrolla2\Cache\Exception\CacheException'), + array('file', 100, '\Desarrolla2\Cache\Exception\CacheException'), + ); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/NotCacheTest.php b/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/NotCacheTest.php @@ -0,0 +1,85 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Description of CacheTest + * + * @author : Daniel González Cerviño <daniel.gonzalez@freelancemadrid.es> + */ + +namespace Desarrolla2\Cache\Adapter\Test; + +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\NotCache; + +/** + * Class NotCacheTest + * + * @author Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +class NotCacheTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @var \Desarrolla2\Cache\Cache + */ + protected $cache; + + public function setUp() + { + $this->cache = new Cache(new NotCache()); + } + + /** + * @return array + */ + public function dataProvider() + { + return array( + array(), + ); + } + + /** + * @dataProvider dataProvider + */ + public function testHas() + { + $this->cache->set('key', 'value'); + $this->assertFalse($this->cache->has('key', 'value')); + } + + /** + * @dataProvider dataProvider + */ + public function testGet() + { + $this->cache->set('key', 'value'); + $this->assertFalse($this->cache->get('key')); + } + + /** + * @dataProvider dataProvider + */ + public function testSet() + { + $this->assertNull($this->cache->set('key', 'value')); + } + + /** + * @dataProvider dataProvider + */ + public function testDelete() + { + $this->assertNull($this->cache->delete('key')); + } + + /** + * @dataProvider dataProvider + */ + public function testSetOption() + { + $this->cache->setOption('ttl', 3600); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/RedisTest.php b/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Adapter/Test/RedisTest.php @@ -0,0 +1,54 @@ +<?php +/** + * This file is part of the Cache project. + * + * Copyright (c) + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + */ + +namespace Desarrolla2\Cache\Adapter\Test; + +use Desarrolla2\Cache\Adapter\Test\AbstractCacheTest; +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\Redis; + +/** + * Class RedisTest + * + * @author Daniel González <daniel.gonzalez@freelancemadrid.es> + */ + +class RedisTest extends AbstractCacheTest +{ + + public function setUp() + { + parent::setup(); + $this->cache = new Cache( + new Redis() + ); + } + + /** + * @return array + */ + public function dataProviderForOptions() + { + return array( + array('ttl', 100), + ); + } + + /** + * @return array + */ + public function dataProviderForOptionsException() + { + return array( + array('ttl', 0, '\Desarrolla2\Cache\Exception\CacheException'), + array('file', 100, '\Desarrolla2\Cache\Exception\CacheException'), + ); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Test/CacheTest.php b/core/update/update/vendor/desarrolla2/cache/tests/Desarrolla2/Cache/Test/CacheTest.php @@ -0,0 +1,36 @@ +<?php + +/** + * This file is part of the Cache project. + * + */ + +namespace Desarrolla2\Cache\Test; + +use Desarrolla2\Cache\Cache; + +/** + * Class CacheTest + * + * @author Daniel González <daniel.gonzalez@freelancemadrid.es> + */ +class CacheTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Desarrolla2\Cache\Cache + */ + protected $cache; + + public function setUp() + { + $this->cache = new Cache(); + } + + /** + * @expectedException \Desarrolla2\Cache\Exception\AdapterNotSetException + */ + public function testGetAdapterThrowsException() + { + $this->cache->getAdapter(); + } +} diff --git a/core/update/update/vendor/desarrolla2/cache/tests/bootstrap.php b/core/update/update/vendor/desarrolla2/cache/tests/bootstrap.php @@ -0,0 +1,14 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Description of auto load + * + * @author : Daniel González Cerviño <daniel.gonzalez@freelancemadrid.es> + * @file : autoload.php , UTF-8 + * @date : Sep 4, 2012 , 3:43:12 PM + */ + +$loader = require_once __DIR__ . '/../vendor/autoload.php'; +Ladybug\Loader::loadHelpers(); +\ No newline at end of file diff --git a/core/update/update/vendor/desarrolla2/cache/tests/config.yml.dist b/core/update/update/vendor/desarrolla2/cache/tests/config.yml.dist @@ -0,0 +1,13 @@ +file: + dir: '' +memcached: + host: '127.0.0.1' + port: '11211' +mongo: + dns: 'mongodb://localhost:27017' +mysql: + user: 'root' + password: '' + host: '127.0.0.1' + port: '3306' + database: 'cache' diff --git a/core/update/update/vendor/desarrolla2/cache/tests/performance/Apc.php b/core/update/update/vendor/desarrolla2/cache/tests/performance/Apc.php @@ -0,0 +1,24 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + * @file : Apc.php , UTF-8 + * @date : Nov 27, 2012 , 11:08:15 PM + * + */ + +require_once __DIR__ . '/../bootstrap.php'; + +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\Apc; + +$cache = new Cache(new Apc()); + +require_once __DIR__ . '/common.php'; diff --git a/core/update/update/vendor/desarrolla2/cache/tests/performance/File.php b/core/update/update/vendor/desarrolla2/cache/tests/performance/File.php @@ -0,0 +1,24 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + * @file : File.php , UTF-8 + * @date : Nov 27, 2012 , 10:53:29 PM + * + */ + +require_once __DIR__ . '/../bootstrap.php'; + +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\File; + +$cache = new Cache(new File('/tmp')); + +require_once __DIR__ . '/common.php'; diff --git a/core/update/update/vendor/desarrolla2/cache/tests/performance/Mongo.php b/core/update/update/vendor/desarrolla2/cache/tests/performance/Mongo.php @@ -0,0 +1,23 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + * @file : Mongo.php , UTF-8 + * @date : Nov 27, 2012 , 10:59:57 PM + * + */ +require_once __DIR__ . '/../bootstrap.php'; + +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\Mongo; + +$cache = new Cache(new Mongo('mongodb://localhost:27017')); + +require_once __DIR__ . '/common.php'; diff --git a/core/update/update/vendor/desarrolla2/cache/tests/performance/NoCache.php b/core/update/update/vendor/desarrolla2/cache/tests/performance/NoCache.php @@ -0,0 +1,23 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + * @file : NoCache.php , UTF-8 + * @date : Nov 27, 2012 , 10:42:49 PM + * + */ +require_once __DIR__ . '/../bootstrap.php'; + +use Desarrolla2\Cache\Cache; +use Desarrolla2\Cache\Adapter\NotCache; + +$cache = new Cache(new NotCache()); + +require_once __DIR__ . '/common.php'; diff --git a/core/update/update/vendor/desarrolla2/cache/tests/performance/common.php b/core/update/update/vendor/desarrolla2/cache/tests/performance/common.php @@ -0,0 +1,52 @@ +<?php + +/** + * This file is part of the Cache project. + * + * Copyright (c) + * + * This source file is subject to the MIT license that is bundled + * with this package in the file LICENSE. + * + * @author : Daniel González <daniel.gonzalez@freelancemadrid.es> + * @file : common.php , UTF-8 + * @date : Nov 27, 2012 , 10:56:05 PM + * + */ + +use Desarrolla2\Timer\Timer; + +//build test data outside of timing loop +$data=array(); +for ($i = 1; $i <= 10000; $i++) { + $data[$i]=md5($i); +} + +$timer = new Timer(); +for ($i = 1; $i <= 10000; $i++) { + $cache->set($data[$i], $data[$i], 3600); +} +$timer->mark('10.000 set'); +for ($i = 1; $i <= 10000; $i++) { + $cache->has($data[$i]); +} +$timer->mark('10.000 has'); +for ($i = 1; $i <= 10000; $i++) { + $cache->get($data[$i]); +} +$timer->mark('10.000 get'); +for ($i = 1; $i <= 10000; $i++) { + $cache->has($data[$i]); + $cache->get($data[$i]); +} +$timer->mark('10.000 has+get combos'); + +$benchmarks=$timer->get(); +foreach ($benchmarks as $benchmark) { + printf( + "%30s : duration %0.2fms memory %s\n", + $benchmark['text'], + $benchmark['from_previous']*1000, + $benchmark['memory'] + ); +} diff --git a/core/update/update/vendor/monolog/monolog/CHANGELOG.mdown b/core/update/update/vendor/monolog/monolog/CHANGELOG.mdown @@ -0,0 +1,202 @@ +### 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. + * Added PsrHandler to forward records to another PSR-3 logger + * Added SamplingHandler to wrap around a handler and include only every Nth record + * Added MongoDBFormatter to support better storage with MongoDBHandler (it must be enabled manually for now) + * Added exception codes in the output of most formatters + * Added LineFormatter::includeStacktraces to enable exception stack traces in logs (uses more than one line) + * Added $useShortAttachment to SlackHandler to minify attachment size and $includeExtra to append extra data + * Added $host to HipChatHandler for users of private instances + * Added $transactionName to NewRelicHandler and support for a transaction_name context value + * Fixed MandrillHandler to avoid outputing API call responses + * Fixed some non-standard behaviors in SyslogUdpHandler + +### 1.11.0 (2014-09-30) + + * Break: The NewRelicHandler extra and context data are now prefixed with extra_ and context_ to avoid clashes. Watch out if you have scripts reading those from the API and rely on names + * Added WhatFailureGroupHandler to suppress any exception coming from the wrapped handlers and avoid chain failures if a logging service fails + * Added MandrillHandler to send emails via the Mandrillapp.com API + * Added SlackHandler to log records to a Slack.com account + * Added FleepHookHandler to log records to a Fleep.io account + * Added LogglyHandler::addTag to allow adding tags to an existing handler + * Added $ignoreEmptyContextAndExtra to LineFormatter to avoid empty [] at the end + * Added $useLocking to StreamHandler and RotatingFileHandler to enable flock() while writing + * Added support for PhpAmqpLib in the AmqpHandler + * Added FingersCrossedHandler::clear and BufferHandler::clear to reset them between batches in long running jobs + * Added support for adding extra fields from $_SERVER in the WebProcessor + * Fixed support for non-string values in PrsLogMessageProcessor + * Fixed SwiftMailer messages being sent with the wrong date in long running scripts + * Fixed minor PHP 5.6 compatibility issues + * Fixed BufferHandler::close being called twice + +### 1.10.0 (2014-06-04) + + * Added Logger::getHandlers() and Logger::getProcessors() methods + * Added $passthruLevel argument to FingersCrossedHandler to let it always pass some records through even if the trigger level is not reached + * Added support for extra data in NewRelicHandler + * Added $expandNewlines flag to the ErrorLogHandler to create multiple log entries when a message has multiple lines + +### 1.9.1 (2014-04-24) + + * Fixed regression in RotatingFileHandler file permissions + * Fixed initialization of the BufferHandler to make sure it gets flushed after receiving records + * Fixed ChromePHPHandler and FirePHPHandler's activation strategies to be more conservative + +### 1.9.0 (2014-04-20) + + * Added LogEntriesHandler to send logs to a LogEntries account + * Added $filePermissions to tweak file mode on StreamHandler and RotatingFileHandler + * Added $useFormatting flag to MemoryProcessor to make it send raw data in bytes + * Added support for table formatting in FirePHPHandler via the table context key + * Added a TagProcessor to add tags to records, and support for tags in RavenHandler + * Added $appendNewline flag to the JsonFormatter to enable using it when logging to files + * Added sound support to the PushoverHandler + * Fixed multi-threading support in StreamHandler + * Fixed empty headers issue when ChromePHPHandler received no records + * Fixed default format of the ErrorLogHandler + +### 1.8.0 (2014-03-23) + + * Break: the LineFormatter now strips newlines by default because this was a bug, set $allowInlineLineBreaks to true if you need them + * Added BrowserConsoleHandler to send logs to any browser's console via console.log() injection in the output + * Added FilterHandler to filter records and only allow those of a given list of levels through to the wrapped handler + * Added FlowdockHandler to send logs to a Flowdock account + * Added RollbarHandler to send logs to a Rollbar account + * Added HtmlFormatter to send prettier log emails with colors for each log level + * Added GitProcessor to add the current branch/commit to extra record data + * Added a Monolog\Registry class to allow easier global access to pre-configured loggers + * Added support for the new official graylog2/gelf-php lib for GelfHandler, upgrade if you can by replacing the mlehner/gelf-php requirement + * Added support for HHVM + * Added support for Loggly batch uploads + * Added support for tweaking the content type and encoding in NativeMailerHandler + * Added $skipClassesPartials to tweak the ignored classes in the IntrospectionProcessor + * Fixed batch request support in GelfHandler + +### 1.7.0 (2013-11-14) + + * Added ElasticSearchHandler to send logs to an Elastic Search server + * Added DynamoDbHandler and ScalarFormatter to send logs to Amazon's Dynamo DB + * Added SyslogUdpHandler to send logs to a remote syslogd server + * Added LogglyHandler to send logs to a Loggly account + * Added $level to IntrospectionProcessor so it only adds backtraces when needed + * Added $version to LogstashFormatter to allow using the new v1 Logstash format + * Added $appName to NewRelicHandler + * Added configuration of Pushover notification retries/expiry + * Added $maxColumnWidth to NativeMailerHandler to change the 70 chars default + * Added chainability to most setters for all handlers + * Fixed RavenHandler batch processing so it takes the message from the record with highest priority + * Fixed HipChatHandler batch processing so it sends all messages at once + * Fixed issues with eAccelerator + * Fixed and improved many small things + +### 1.6.0 (2013-07-29) + + * Added HipChatHandler to send logs to a HipChat chat room + * Added ErrorLogHandler to send logs to PHP's error_log function + * Added NewRelicHandler to send logs to NewRelic's service + * Added Monolog\ErrorHandler helper class to register a Logger as exception/error/fatal handler + * Added ChannelLevelActivationStrategy for the FingersCrossedHandler to customize levels by channel + * Added stack traces output when normalizing exceptions (json output & co) + * Added Monolog\Logger::API constant (currently 1) + * Added support for ChromePHP's v4.0 extension + * Added support for message priorities in PushoverHandler, see $highPriorityLevel and $emergencyLevel + * Added support for sending messages to multiple users at once with the PushoverHandler + * Fixed RavenHandler's support for batch sending of messages (when behind a Buffer or FingersCrossedHandler) + * Fixed normalization of Traversables with very large data sets, only the first 1000 items are shown now + * Fixed issue in RotatingFileHandler when an open_basedir restriction is active + * Fixed minor issues in RavenHandler and bumped the API to Raven 0.5.0 + * Fixed SyslogHandler issue when many were used concurrently with different facilities + +### 1.5.0 (2013-04-23) + + * Added ProcessIdProcessor to inject the PID in log records + * Added UidProcessor to inject a unique identifier to all log records of one request/run + * Added support for previous exceptions in the LineFormatter exception serialization + * Added Monolog\Logger::getLevels() to get all available levels + * Fixed ChromePHPHandler so it avoids sending headers larger than Chrome can handle + +### 1.4.1 (2013-04-01) + + * Fixed exception formatting in the LineFormatter to be more minimalistic + * Fixed RavenHandler's handling of context/extra data, requires Raven client >0.1.0 + * Fixed log rotation in RotatingFileHandler to work with long running scripts spanning multiple days + * Fixed WebProcessor array access so it checks for data presence + * Fixed Buffer, Group and FingersCrossed handlers to make use of their processors + +### 1.4.0 (2013-02-13) + + * Added RedisHandler to log to Redis via the Predis library or the phpredis extension + * Added ZendMonitorHandler to log to the Zend Server monitor + * Added the possibility to pass arrays of handlers and processors directly in the Logger constructor + * Added `$useSSL` option to the PushoverHandler which is enabled by default + * Fixed ChromePHPHandler and FirePHPHandler issue when multiple instances are used simultaneously + * Fixed header injection capability in the NativeMailHandler + +### 1.3.1 (2013-01-11) + + * Fixed LogstashFormatter to be usable with stream handlers + * Fixed GelfMessageFormatter levels on Windows + +### 1.3.0 (2013-01-08) + + * Added PSR-3 compliance, the `Monolog\Logger` class is now an instance of `Psr\Log\LoggerInterface` + * Added PsrLogMessageProcessor that you can selectively enable for full PSR-3 compliance + * Added LogstashFormatter (combine with SocketHandler or StreamHandler to send logs to Logstash) + * Added PushoverHandler to send mobile notifications + * Added CouchDBHandler and DoctrineCouchDBHandler + * Added RavenHandler to send data to Sentry servers + * Added support for the new MongoClient class in MongoDBHandler + * Added microsecond precision to log records' timestamps + * Added `$flushOnOverflow` param to BufferHandler to flush by batches instead of losing + the oldest entries + * Fixed normalization of objects with cyclic references + +### 1.2.1 (2012-08-29) + + * Added new $logopts arg to SyslogHandler to provide custom openlog options + * Fixed fatal error in SyslogHandler + +### 1.2.0 (2012-08-18) + + * Added AmqpHandler (for use with AMQP servers) + * Added CubeHandler + * Added NativeMailerHandler::addHeader() to send custom headers in mails + * Added the possibility to specify more than one recipient in NativeMailerHandler + * Added the possibility to specify float timeouts in SocketHandler + * Added NOTICE and EMERGENCY levels to conform with RFC 5424 + * Fixed the log records to use the php default timezone instead of UTC + * Fixed BufferHandler not being flushed properly on PHP fatal errors + * Fixed normalization of exotic resource types + * Fixed the default format of the SyslogHandler to avoid duplicating datetimes in syslog + +### 1.1.0 (2012-04-23) + + * Added Monolog\Logger::isHandling() to check if a handler will + handle the given log level + * Added ChromePHPHandler + * Added MongoDBHandler + * Added GelfHandler (for use with Graylog2 servers) + * Added SocketHandler (for use with syslog-ng for example) + * Added NormalizerFormatter + * Added the possibility to change the activation strategy of the FingersCrossedHandler + * Added possibility to show microseconds in logs + * Added `server` and `referer` to WebProcessor output + +### 1.0.2 (2011-10-24) + + * Fixed bug in IE with large response headers and FirePHPHandler + +### 1.0.1 (2011-08-25) + + * Added MemoryPeakUsageProcessor and MemoryUsageProcessor + * Added Monolog\Logger::getName() to get a logger's channel name + +### 1.0.0 (2011-07-06) + + * Added IntrospectionProcessor to get info from where the logger was called + * Fixed WebProcessor in CLI + +### 1.0.0-RC1 (2011-07-01) + + * Initial release diff --git a/core/update/update/vendor/monolog/monolog/LICENSE b/core/update/update/vendor/monolog/monolog/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011-2014 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 +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/core/update/update/vendor/monolog/monolog/README.mdown b/core/update/update/vendor/monolog/monolog/README.mdown @@ -0,0 +1,283 @@ +Monolog - Logging for PHP 5.3+ [![Build Status](https://secure.travis-ci.org/Seldaek/monolog.png)](http://travis-ci.org/Seldaek/monolog) +============================== + +[![Total Downloads](https://poser.pugx.org/monolog/monolog/downloads.png)](https://packagist.org/packages/monolog/monolog) +[![Latest Stable Version](https://poser.pugx.org/monolog/monolog/v/stable.png)](https://packagist.org/packages/monolog/monolog) +[![Reference Status](https://www.versioneye.com/php/monolog:monolog/reference_badge.svg)](https://www.versioneye.com/php/monolog:monolog/references) + + +Monolog sends your logs to files, sockets, inboxes, databases and various +web services. See the complete list of handlers below. Special handlers +allow you to build advanced logging strategies. + +This library implements the [PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) +interface that you can type-hint against in your own libraries to keep +a maximum of interoperability. You can also use it in your applications to +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. + +Usage +----- + +Install the latest version with `composer require monolog/monolog` + +```php +<?php + +use Monolog\Logger; +use Monolog\Handler\StreamHandler; + +// create a log channel +$log = new Logger('name'); +$log->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING)); + +// add records to the log +$log->addWarning('Foo'); +$log->addError('Bar'); +``` + +Core Concepts +------------- + +Every `Logger` instance has a channel (name) and a stack of handlers. Whenever +you add a record to the logger, it traverses the handler stack. Each handler +decides whether it fully handled the record, and if so, the propagation of the +record ends there. + +This allows for flexible logging setups, for example having a `StreamHandler` at +the bottom of the stack that will log anything to disk, and on top of that add +a `MailHandler` that will send emails only when an error message is logged. +Handlers also have a `$bubble` property which defines whether they block the +record or not if they handled it. In this example, setting the `MailHandler`'s +`$bubble` argument to false means that records handled by the `MailHandler` will +not propagate to the `StreamHandler` anymore. + +You can create many `Logger`s, each defining a channel (e.g.: db, request, +router, ..) and each of them combining various handlers, which can be shared +or not. The channel is reflected in the logs and allows you to easily see or +filter records. + +Each Handler also has a Formatter, a default one with settings that make sense +will be created if you don't set one. The formatters normalize and format +incoming records so that they can be used by the handlers to output useful +information. + +Custom severity levels are not available. Only the eight +[RFC 5424](http://tools.ietf.org/html/rfc5424) levels (debug, info, notice, +warning, error, critical, alert, emergency) are present for basic filtering +purposes, but for sorting and other use cases that would require +flexibility, you should add Processors to the Logger that can add extra +information (tags, user ip, ..) to the records before they are handled. + +Log Levels +---------- + +Monolog supports the logging levels described by [RFC 5424](http://tools.ietf.org/html/rfc5424). + +- **DEBUG** (100): Detailed debug information. + +- **INFO** (200): Interesting events. Examples: User logs in, SQL logs. + +- **NOTICE** (250): Normal but significant events. + +- **WARNING** (300): Exceptional occurrences that are not errors. Examples: + Use of deprecated APIs, poor use of an API, undesirable things that are not + necessarily wrong. + +- **ERROR** (400): Runtime errors that do not require immediate action but + should typically be logged and monitored. + +- **CRITICAL** (500): Critical conditions. Example: Application component + unavailable, unexpected exception. + +- **ALERT** (550): Action must be taken immediately. Example: Entire website + down, database unavailable, etc. This should trigger the SMS alerts and wake + you up. + +- **EMERGENCY** (600): Emergency: system is unusable. + +Docs +==== + +**See the `doc` directory for more detailed documentation. +The following is only a list of all parts that come with Monolog.** + +Handlers +-------- + +### Log to files and syslog + +- _StreamHandler_: Logs records into any PHP stream, use this for log files. +- _RotatingFileHandler_: Logs records to a file and creates one logfile per day. + It will also delete files older than `$maxFiles`. You should use + [logrotate](http://linuxcommand.org/man_pages/logrotate8.html) for high profile + setups though, this is just meant as a quick and dirty solution. +- _SyslogHandler_: Logs records to the syslog. +- _ErrorLogHandler_: Logs records to PHP's + [`error_log()`](http://docs.php.net/manual/en/function.error-log.php) function. + +### Send alerts and emails + +- _NativeMailerHandler_: Sends emails using PHP's + [`mail()`](http://php.net/manual/en/function.mail.php) function. +- _SwiftMailerHandler_: Sends emails using a [`Swift_Mailer`](http://swiftmailer.org/) instance. +- _PushoverHandler_: Sends mobile notifications via the [Pushover](https://www.pushover.net/) API. +- _HipChatHandler_: Logs records to a [HipChat](http://hipchat.com) chat room using its API. +- _FlowdockHandler_: Logs records to a [Flowdock](https://www.flowdock.com/) account. +- _SlackHandler_: Logs records to a [Slack](https://www.slack.com/) account. +- _MandrillHandler_: Sends emails via the Mandrill API using a [`Swift_Message`](http://swiftmailer.org/) instance. +- _FleepHookHandler_: Logs records to a [Fleep](https://fleep.io/) conversation using Webhooks. + +### Log specific servers and networked logging + +- _SocketHandler_: Logs records to [sockets](http://php.net/fsockopen), use this + for UNIX and TCP sockets. See an [example](https://github.com/Seldaek/monolog/blob/master/doc/sockets.md). +- _AmqpHandler_: Logs records to an [amqp](http://www.amqp.org/) compatible + server. Requires the [php-amqp](http://pecl.php.net/package/amqp) extension (1.0+). +- _GelfHandler_: Logs records to a [Graylog2](http://www.graylog2.org) server. +- _CubeHandler_: Logs records to a [Cube](http://square.github.com/cube/) server. +- _RavenHandler_: Logs records to a [Sentry](http://getsentry.com/) server using + [raven](https://packagist.org/packages/raven/raven). +- _ZendMonitorHandler_: Logs records to the Zend Monitor present in Zend Server. +- _NewRelicHandler_: Logs records to a [NewRelic](http://newrelic.com/) application. +- _LogglyHandler_: Logs records to a [Loggly](http://www.loggly.com/) account. +- _RollbarHandler_: Logs records to a [Rollbar](https://rollbar.com/) account. +- _SyslogUdpHandler_: Logs records to a remote [Syslogd](http://www.rsyslog.com/) server. +- _LogEntriesHandler_: Logs records to a [LogEntries](http://logentries.com/) account. + +### Logging in development + +- _FirePHPHandler_: Handler for [FirePHP](http://www.firephp.org/), providing + inline `console` messages within [FireBug](http://getfirebug.com/). +- _ChromePHPHandler_: Handler for [ChromePHP](http://www.chromephp.com/), providing + 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. + +### Log to databases + +- _RedisHandler_: Logs records to a [redis](http://redis.io) server. +- _MongoDBHandler_: Handler to write records in MongoDB via a + [Mongo](http://pecl.php.net/package/mongo) extension connection. +- _CouchDBHandler_: Logs records to a CouchDB server. +- _DoctrineCouchDBHandler_: Logs records to a CouchDB server via the Doctrine CouchDB ODM. +- _ElasticSearchHandler_: Logs records to an Elastic Search server. +- _DynamoDbHandler_: Logs records to a DynamoDB table with the [AWS SDK](https://github.com/aws/aws-sdk-php). + +### Wrappers / Special Handlers + +- _FingersCrossedHandler_: A very interesting wrapper. It takes a logger as + parameter and will accumulate log records of all levels until a record + exceeds the defined severity level. At which point it delivers all records, + including those of lower severity, to the handler it wraps. This means that + until an error actually happens you will not see anything in your logs, but + when it happens you will have the full information, including debug and info + records. This provides you with all the information you need, but only when + you need it. +- _WhatFailureGroupHandler_: This handler extends the _GroupHandler_ ignoring + exceptions raised by each child handler. This allows you to ignore issues + where a remote tcp connection may have died but you do not want your entire + application to crash and may wish to continue to log to other handlers. +- _BufferHandler_: This handler will buffer all the log records it receives + until `close()` is called at which point it will call `handleBatch()` on the + handler it wraps with all the log messages at once. This is very useful to + send an email with all records at once for example instead of having one mail + for every log record. +- _GroupHandler_: This handler groups other handlers. Every record received is + sent to all the handlers it is configured with. +- _FilterHandler_: This handler only lets records of the given levels through + to the wrapped handler. +- _SamplingHandler_: Wraps around another handler and lets you sample records + if you only want to store some of them. +- _NullHandler_: Any record it can handle will be thrown away. This can be used + to put on top of an existing handler stack to disable it temporarily. +- _PsrHandler_: Can be used to forward log records to an existing PSR-3 logger +- _TestHandler_: Used for testing, it records everything that is sent to it and + has accessors to read out the information. + +Formatters +---------- + +- _LineFormatter_: Formats a log record into a one-line string. +- _HtmlFormatter_: Used to format log records into a human readable html table, mainly suitable for emails. +- _NormalizerFormatter_: Normalizes objects/resources down to strings so a record can easily be serialized/encoded. +- _ScalarFormatter_: Used to format log records into an associative array of scalar values. +- _JsonFormatter_: Encodes a log record into json. +- _WildfireFormatter_: Used to format log records into the Wildfire/FirePHP protocol, only useful for the FirePHPHandler. +- _ChromePHPFormatter_: Used to format log records into the ChromePHP format, only useful for the ChromePHPHandler. +- _GelfMessageFormatter_: Used to format log records into Gelf message instances, only useful for the GelfHandler. +- _LogstashFormatter_: Used to format log records into [logstash](http://logstash.net/) event json, useful for any handler listed under inputs [here](http://logstash.net/docs/latest). +- _ElasticaFormatter_: Used to format log records into an Elastica\Document object, only useful for the ElasticSearchHandler. +- _LogglyFormatter_: Used to format log records into Loggly messages, only useful for the LogglyHandler. +- _FlowdockFormatter_: Used to format log records into Flowdock messages, only useful for the FlowdockHandler. +- _MongoDBFormatter_: Converts \DateTime instances to \MongoDate and objects recursively to arrays, only useful with the MongoDBHandler. + +Processors +---------- + +- _IntrospectionProcessor_: Adds the line/file/class/method from which the log call originated. +- _WebProcessor_: Adds the current request URI, request method and client IP to a log record. +- _MemoryUsageProcessor_: Adds the current memory usage to a log record. +- _MemoryPeakUsageProcessor_: Adds the peak memory usage to a log record. +- _ProcessIdProcessor_: Adds the process id to a log record. +- _UidProcessor_: Adds a unique identifier to a log record. +- _GitProcessor_: Adds the current git branch and commit to a log record. +- _TagProcessor_: Adds an array of predefined tags to a log record. + +Utilities +--------- + +- _Registry_: The `Monolog\Registry` class lets you configure global loggers that you + can then statically access from anywhere. It is not really a best practice but can + help in some older codebases or for ease of use. +- _ErrorHandler_: The `Monolog\ErrorHandler` class allows you to easily register + a Logger instance as an exception handler, error handler or fatal error handler. +- _ErrorLevelActivationStrategy_: Activates a FingersCrossedHandler when a certain log + level is reached. +- _ChannelLevelActivationStrategy_: Activates a FingersCrossedHandler when a certain + log level is reached, depending on which channel received the log record. + +About +===== + +Requirements +------------ + +- Monolog works with PHP 5.3 or above, and is also tested to work with HHVM. + +Submitting bugs and feature requests +------------------------------------ + +Bugs and feature request are tracked on [GitHub](https://github.com/Seldaek/monolog/issues) + +Frameworks Integration +---------------------- + +- Frameworks and libraries using [PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) + 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. +- [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. + +Author +------ + +Jordi Boggiano - <j.boggiano@seld.be> - <http://twitter.com/seldaek><br /> +See also the list of [contributors](https://github.com/Seldaek/monolog/contributors) which participated in this project. + +License +------- + +Monolog is licensed under the MIT License - see the `LICENSE` file for details + +Acknowledgements +---------------- + +This library is heavily inspired by Python's [Logbook](http://packages.python.org/Logbook/) +library, although most concepts have been adjusted to fit to the PHP world. diff --git a/core/update/update/vendor/monolog/monolog/composer.json b/core/update/update/vendor/monolog/monolog/composer.json @@ -0,0 +1,50 @@ +{ + "name": "monolog/monolog", + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "keywords": ["log", "logging", "psr-3"], + "homepage": "http://github.com/Seldaek/monolog", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "require": { + "php": ">=5.3.0", + "psr/log": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0", + "graylog2/gelf-php": "~1.0", + "raven/raven": "~0.5", + "ruflin/elastica": "0.90.*", + "doctrine/couchdb": "~1.0@dev", + "aws/aws-sdk-php": "~2.4, >2.4.8", + "videlalvaro/php-amqplib": "~2.4" + }, + "suggest": { + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "raven/raven": "Allow sending log messages to a Sentry server", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "videlalvaro/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "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" + }, + "autoload": { + "psr-4": {"Monolog\\": "src/Monolog"} + }, + "provide": { + "psr/log-implementation": "1.0.0" + }, + "extra": { + "branch-alias": { + "dev-master": "1.12.x-dev" + } + } +} diff --git a/core/update/update/vendor/monolog/monolog/doc/extending.md b/core/update/update/vendor/monolog/monolog/doc/extending.md @@ -0,0 +1,76 @@ +Extending Monolog +================= + +Monolog is fully extensible, allowing you to adapt your logger to your needs. + +Writing your own handler +------------------------ + +Monolog provides many built-in handlers. But if the one you need does not +exist, you can write it and use it in your logger. The only requirement is +to implement `Monolog\Handler\HandlerInterface`. + +Let's write a PDOHandler to log records to a database. We will extend the +abstract class provided by Monolog to keep things DRY. + +```php +<?php + +use Monolog\Logger; +use Monolog\Handler\AbstractProcessingHandler; + +class PDOHandler extends AbstractProcessingHandler +{ + private $initialized = false; + private $pdo; + private $statement; + + public function __construct(PDO $pdo, $level = Logger::DEBUG, $bubble = true) + { + $this->pdo = $pdo; + parent::__construct($level, $bubble); + } + + protected function write(array $record) + { + if (!$this->initialized) { + $this->initialize(); + } + + $this->statement->execute(array( + 'channel' => $record['channel'], + 'level' => $record['level'], + 'message' => $record['formatted'], + 'time' => $record['datetime']->format('U'), + )); + } + + private function initialize() + { + $this->pdo->exec( + 'CREATE TABLE IF NOT EXISTS monolog ' + .'(channel VARCHAR(255), level INTEGER, message LONGTEXT, time INTEGER UNSIGNED)' + ); + $this->statement = $this->pdo->prepare( + 'INSERT INTO monolog (channel, level, message, time) VALUES (:channel, :level, :message, :time)' + ); + + $this->initialized = true; + } +} +``` + +You can now use this handler in your logger: + +```php +<?php + +$logger->pushHandler(new PDOHandler(new PDO('sqlite:logs.sqlite'))); + +// You can now use your logger +$logger->addInfo('My logger is now ready'); +``` + +The `Monolog\Handler\AbstractProcessingHandler` class provides most of the +logic needed for the handler, including the use of processors and the formatting +of the record (which is why we use ``$record['formatted']`` instead of ``$record['message']``). diff --git a/core/update/update/vendor/monolog/monolog/doc/sockets.md b/core/update/update/vendor/monolog/monolog/doc/sockets.md @@ -0,0 +1,37 @@ +Sockets Handler +=============== + +This handler allows you to write your logs to sockets using [fsockopen](http://php.net/fsockopen) +or [pfsockopen](http://php.net/pfsockopen). + +Persistent sockets are mainly useful in web environments where you gain some performance not closing/opening +the connections between requests. + +Basic Example +------------- + +```php +<?php + +use Monolog\Logger; +use Monolog\Handler\SocketHandler; + +// Create the logger +$logger = new Logger('my_logger'); + +// Create the handler +$handler = new SocketHandler('unix:///var/log/httpd_app_log.socket'); +$handler->setPersistent(true); + +// Now add the handler +$logger->pushHandler($handler, Logger::DEBUG); + +// You can now use your logger +$logger->addInfo('My logger is now ready'); + +``` + +In this example, using syslog-ng, you should see the log on the log server: + + cweb1 [2012-02-26 00:12:03] my_logger.INFO: My logger is now ready [] [] + diff --git a/core/update/update/vendor/monolog/monolog/doc/usage.md b/core/update/update/vendor/monolog/monolog/doc/usage.md @@ -0,0 +1,162 @@ +Using Monolog +============= + +Installation +------------ + +Monolog is available on Packagist ([monolog/monolog](http://packagist.org/packages/monolog/monolog)) +and as such installable via [Composer](http://getcomposer.org/). + +```bash +php composer.phar require monolog/monolog +``` + +If you do not use Composer, you can grab the code from GitHub, and use any +PSR-0 compatible autoloader (e.g. the [Symfony2 ClassLoader component](https://github.com/symfony/ClassLoader)) +to load Monolog classes. + +Configuring a logger +-------------------- + +Here is a basic setup to log to a file and to firephp on the DEBUG level: + +```php +<?php + +use Monolog\Logger; +use Monolog\Handler\StreamHandler; +use Monolog\Handler\FirePHPHandler; + +// Create the logger +$logger = new Logger('my_logger'); +// Now add some handlers +$logger->pushHandler(new StreamHandler(__DIR__.'/my_app.log', Logger::DEBUG)); +$logger->pushHandler(new FirePHPHandler()); + +// You can now use your logger +$logger->addInfo('My logger is now ready'); +``` + +Let's explain it. The first step is to create the logger instance which will +be used in your code. The argument is a channel name, which is useful when +you use several loggers (see below for more details about it). + +The logger itself does not know how to handle a record. It delegates it to +some handlers. The code above registers two handlers in the stack to allow +handling records in two different ways. + +Note that the FirePHPHandler is called first as it is added on top of the +stack. This allows you to temporarily add a logger with bubbling disabled if +you want to override other configured loggers. + +Adding extra data in the records +-------------------------------- + +Monolog provides two different ways to add extra informations along the simple +textual message. + +### Using the logging context + +The first way is the context, allowing to pass an array of data along the +record: + +```php +<?php + +$logger->addInfo('Adding a new user', array('username' => 'Seldaek')); +``` + +Simple handlers (like the StreamHandler for instance) will simply format +the array to a string but richer handlers can take advantage of the context +(FirePHP is able to display arrays in pretty way for instance). + +### Using processors + +The second way is to add extra data for all records by using a processor. +Processors can be any callable. They will get the record as parameter and +must return it after having eventually changed the `extra` part of it. Let's +write a processor adding some dummy data in the record: + +```php +<?php + +$logger->pushProcessor(function ($record) { + $record['extra']['dummy'] = 'Hello world!'; + + return $record; +}); +``` + +Monolog provides some built-in processors that can be used in your project. +Look at the [README file](https://github.com/Seldaek/monolog/blob/master/README.mdown) for the list. + +> Tip: processors can also be registered on a specific handler instead of + the logger to apply only for this handler. + +Leveraging channels +------------------- + +Channels are a great way to identify to which part of the application a record +is related. This is useful in big applications (and is leveraged by +MonologBundle in Symfony2). + +Picture two loggers sharing a handler that writes to a single log file. +Channels would allow you to identify the logger that issued every record. +You can easily grep through the log files filtering this or that channel. + +```php +<?php + +use Monolog\Logger; +use Monolog\Handler\StreamHandler; +use Monolog\Handler\FirePHPHandler; + +// Create some handlers +$stream = new StreamHandler(__DIR__.'/my_app.log', Logger::DEBUG); +$firephp = new FirePHPHandler(); + +// Create the main logger of the app +$logger = new Logger('my_logger'); +$logger->pushHandler($stream); +$logger->pushHandler($firephp); + +// Create a logger for the security-related stuff with a different channel +$securityLogger = new Logger('security'); +$securityLogger->pushHandler($stream); +$securityLogger->pushHandler($firephp); +``` + +Customizing log format +---------------------- + +In Monolog it's easy to customize the format of the logs written into files, +sockets, mails, databases and other handlers. Most of the handlers use the + +```php +$record['formatted'] +``` + +value to be automatically put into the log device. This value depends on the +formatter settings. You can choose between predefined formatter classes or +write your own (e.g. a multiline text file for human-readable output). + +To configure a predefined formatter class, just set it as the handler's field: + +```php +// the default date format is "Y-m-d H:i:s" +$dateFormat = "Y n j, g:i a"; +// the default output format is "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n" +$output = "%datetime% > %level_name% > %message% %context% %extra%\n"; +// finally, create a formatter +$formatter = new LineFormatter($output, $dateFormat); + +// Create a handler +$stream = new StreamHandler(__DIR__.'/my_app.log', Logger::DEBUG); +$stream->setFormatter($formatter); +// bind it to a logger object +$securityLogger = new Logger('security'); +$securityLogger->pushHandler($stream); +``` + +You may also reuse the same formatter between multiple handlers and share those +handlers between multiple loggers. diff --git a/core/update/update/vendor/monolog/monolog/phpunit.xml.dist b/core/update/update/vendor/monolog/monolog/phpunit.xml.dist @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<phpunit bootstrap="tests/bootstrap.php" colors="true"> + <testsuites> + <testsuite name="Monolog Test Suite"> + <directory>tests/Monolog/</directory> + </testsuite> + </testsuites> + + <filter> + <whitelist> + <directory suffix=".php">src/Monolog/</directory> + </whitelist> + </filter> +</phpunit> diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/ErrorHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/ErrorHandler.php @@ -0,0 +1,208 @@ +<?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; + +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; + +/** + * Monolog error handler + * + * A facility to enable logging of runtime errors, exceptions and fatal errors. + * + * Quick setup: <code>ErrorHandler::register($logger);</code> + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class ErrorHandler +{ + private $logger; + + private $previousExceptionHandler; + private $uncaughtExceptionLevel; + + private $previousErrorHandler; + private $errorLevelMap; + + private $fatalLevel; + private $reservedMemory; + private static $fatalErrors = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR); + + public function __construct(LoggerInterface $logger) + { + $this->logger = $logger; + } + + /** + * Registers a new ErrorHandler for a given Logger + * + * By default it will handle errors, exceptions and fatal errors + * + * @param LoggerInterface $logger + * @param array|false $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling + * @param int|false $exceptionLevel a LogLevel::* constant, or false to disable exception handling + * @param int|false $fatalLevel a LogLevel::* constant, or false to disable fatal error handling + * @return ErrorHandler + */ + public static function register(LoggerInterface $logger, $errorLevelMap = array(), $exceptionLevel = null, $fatalLevel = null) + { + $handler = new static($logger); + if ($errorLevelMap !== false) { + $handler->registerErrorHandler($errorLevelMap); + } + if ($exceptionLevel !== false) { + $handler->registerExceptionHandler($exceptionLevel); + } + if ($fatalLevel !== false) { + $handler->registerFatalHandler($fatalLevel); + } + + return $handler; + } + + public function registerExceptionHandler($level = null, $callPrevious = true) + { + $prev = set_exception_handler(array($this, 'handleException')); + $this->uncaughtExceptionLevel = $level; + if ($callPrevious && $prev) { + $this->previousExceptionHandler = $prev; + } + } + + public function registerErrorHandler(array $levelMap = array(), $callPrevious = true, $errorTypes = -1) + { + $prev = set_error_handler(array($this, 'handleError'), $errorTypes); + $this->errorLevelMap = array_replace($this->defaultErrorLevelMap(), $levelMap); + if ($callPrevious) { + $this->previousErrorHandler = $prev ?: true; + } + } + + public function registerFatalHandler($level = null, $reservedMemorySize = 20) + { + register_shutdown_function(array($this, 'handleFatalError')); + + $this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize); + $this->fatalLevel = $level; + } + + protected function defaultErrorLevelMap() + { + return array( + E_ERROR => LogLevel::CRITICAL, + E_WARNING => LogLevel::WARNING, + E_PARSE => LogLevel::ALERT, + E_NOTICE => LogLevel::NOTICE, + E_CORE_ERROR => LogLevel::CRITICAL, + E_CORE_WARNING => LogLevel::WARNING, + E_COMPILE_ERROR => LogLevel::ALERT, + E_COMPILE_WARNING => LogLevel::WARNING, + E_USER_ERROR => LogLevel::ERROR, + E_USER_WARNING => LogLevel::WARNING, + E_USER_NOTICE => LogLevel::NOTICE, + E_STRICT => LogLevel::NOTICE, + E_RECOVERABLE_ERROR => LogLevel::ERROR, + E_DEPRECATED => LogLevel::NOTICE, + E_USER_DEPRECATED => LogLevel::NOTICE, + ); + } + + /** + * @private + */ + public function handleException(\Exception $e) + { + $this->logger->log( + $this->uncaughtExceptionLevel === null ? LogLevel::ERROR : $this->uncaughtExceptionLevel, + sprintf('Uncaught Exception %s: "%s" at %s line %s', get_class($e), $e->getMessage(), $e->getFile(), $e->getLine()), + array('exception' => $e) + ); + + if ($this->previousExceptionHandler) { + call_user_func($this->previousExceptionHandler, $e); + } + } + + /** + * @private + */ + public function handleError($code, $message, $file = '', $line = 0, $context = array()) + { + if (!(error_reporting() & $code)) { + return; + } + + $level = isset($this->errorLevelMap[$code]) ? $this->errorLevelMap[$code] : LogLevel::CRITICAL; + $this->logger->log($level, self::codeToString($code).': '.$message, array('code' => $code, 'message' => $message, 'file' => $file, 'line' => $line)); + + if ($this->previousErrorHandler === true) { + return false; + } elseif ($this->previousErrorHandler) { + return call_user_func($this->previousErrorHandler, $code, $message, $file, $line, $context); + } + } + + /** + * @private + */ + public function handleFatalError() + { + $this->reservedMemory = null; + + $lastError = error_get_last(); + if ($lastError && in_array($lastError['type'], self::$fatalErrors)) { + $this->logger->log( + $this->fatalLevel === null ? LogLevel::ALERT : $this->fatalLevel, + 'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'], + array('code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line']) + ); + } + } + + private static function codeToString($code) + { + switch ($code) { + case E_ERROR: + return 'E_ERROR'; + case E_WARNING: + return 'E_WARNING'; + case E_PARSE: + return 'E_PARSE'; + case E_NOTICE: + return 'E_NOTICE'; + case E_CORE_ERROR: + return 'E_CORE_ERROR'; + case E_CORE_WARNING: + return 'E_CORE_WARNING'; + case E_COMPILE_ERROR: + return 'E_COMPILE_ERROR'; + case E_COMPILE_WARNING: + return 'E_COMPILE_WARNING'; + case E_USER_ERROR: + return 'E_USER_ERROR'; + case E_USER_WARNING: + return 'E_USER_WARNING'; + case E_USER_NOTICE: + return 'E_USER_NOTICE'; + case E_STRICT: + return 'E_STRICT'; + case E_RECOVERABLE_ERROR: + return 'E_RECOVERABLE_ERROR'; + case E_DEPRECATED: + return 'E_DEPRECATED'; + case E_USER_DEPRECATED: + return 'E_USER_DEPRECATED'; + } + + return 'Unknown PHP error'; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php @@ -0,0 +1,79 @@ +<?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\Formatter; + +use Monolog\Logger; + +/** + * Formats a log message according to the ChromePHP array format + * + * @author Christophe Coevoet <stof@notk.org> + */ +class ChromePHPFormatter implements FormatterInterface +{ + /** + * Translates Monolog log levels to Wildfire levels. + */ + private $logLevels = array( + Logger::DEBUG => 'log', + Logger::INFO => 'info', + Logger::NOTICE => 'info', + Logger::WARNING => 'warn', + Logger::ERROR => 'error', + Logger::CRITICAL => 'error', + Logger::ALERT => 'error', + Logger::EMERGENCY => 'error', + ); + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + // Retrieve the line and file if set and remove them from the formatted extra + $backtrace = 'unknown'; + if (isset($record['extra']['file']) && isset($record['extra']['line'])) { + $backtrace = $record['extra']['file'].' : '.$record['extra']['line']; + unset($record['extra']['file']); + unset($record['extra']['line']); + } + + $message = array('message' => $record['message']); + if ($record['context']) { + $message['context'] = $record['context']; + } + if ($record['extra']) { + $message['extra'] = $record['extra']; + } + if (count($message) === 1) { + $message = reset($message); + } + + return array( + $record['channel'], + $message, + $backtrace, + $this->logLevels[$record['level']], + ); + } + + public function formatBatch(array $records) + { + $formatted = array(); + + foreach ($records as $record) { + $formatted[] = $this->format($record); + } + + return $formatted; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php @@ -0,0 +1,87 @@ +<?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\Formatter; + +use Elastica\Document; + +/** + * Format a log message into an Elastica Document + * + * @author Jelle Vink <jelle.vink@gmail.com> + */ +class ElasticaFormatter extends NormalizerFormatter +{ + /** + * @var string Elastic search index name + */ + protected $index; + + /** + * @var string Elastic search document type + */ + protected $type; + + /** + * @param string $index Elastic Search index name + * @param string $type Elastic Search document type + */ + public function __construct($index, $type) + { + parent::__construct(\DateTime::ISO8601); + $this->index = $index; + $this->type = $type; + } + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + $record = parent::format($record); + + return $this->getDocument($record); + } + + /** + * Getter index + * @return string + */ + public function getIndex() + { + return $this->index; + } + + /** + * Getter type + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * Convert a log message into an Elastica Document + * + * @param array $record Log message + * @return Document + */ + protected function getDocument($record) + { + $document = new Document(); + $document->setData($record); + $document->setType($this->type); + $document->setIndex($this->index); + + return $document; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php @@ -0,0 +1,104 @@ +<?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\Formatter; + +/** + * formats the record to be used in the FlowdockHandler + * + * @author Dominik Liebler <liebler.dominik@gmail.com> + */ +class FlowdockFormatter implements FormatterInterface +{ + /** + * @var string + */ + private $source; + + /** + * @var string + */ + private $sourceEmail; + + /** + * @param string $source + * @param string $sourceEmail + */ + public function __construct($source, $sourceEmail) + { + $this->source = $source; + $this->sourceEmail = $sourceEmail; + } + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + $tags = array( + '#logs', + '#' . strtolower($record['level_name']), + '#' . $record['channel'], + ); + + foreach ($record['extra'] as $value) { + $tags[] = '#' . $value; + } + + $subject = sprintf( + 'in %s: %s - %s', + $this->source, + $record['level_name'], + $this->getShortMessage($record['message']) + ); + + $record['flowdock'] = array( + 'source' => $this->source, + 'from_address' => $this->sourceEmail, + 'subject' => $subject, + 'content' => $record['message'], + 'tags' => $tags, + 'project' => $this->source, + ); + + return $record; + } + + /** + * {@inheritdoc} + */ + public function formatBatch(array $records) + { + $formatted = array(); + + foreach ($records as $record) { + $formatted[] = $this->format($record); + } + + return $formatted; + } + + /** + * @param string $message + * + * @return string + */ + public function getShortMessage($message) + { + $maxLength = 45; + + if (strlen($message) > $maxLength) { + $message = substr($message, 0, $maxLength - 4) . ' ...'; + } + + return $message; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php @@ -0,0 +1,36 @@ +<?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\Formatter; + +/** + * Interface for formatters + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +interface FormatterInterface +{ + /** + * Formats a log record. + * + * @param array $record A record to format + * @return mixed The formatted record + */ + public function format(array $record); + + /** + * Formats a set of log records. + * + * @param array $records A set of records to format + * @return mixed The formatted set of records + */ + public function formatBatch(array $records); +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php @@ -0,0 +1,101 @@ +<?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\Formatter; + +use Monolog\Logger; +use Gelf\Message; + +/** + * Serializes a log message to GELF + * @see http://www.graylog2.org/about/gelf + * + * @author Matt Lehner <mlehner@gmail.com> + */ +class GelfMessageFormatter extends NormalizerFormatter +{ + /** + * @var string the name of the system for the Gelf log message + */ + protected $systemName; + + /** + * @var string a prefix for 'extra' fields from the Monolog record (optional) + */ + protected $extraPrefix; + + /** + * @var string a prefix for 'context' fields from the Monolog record (optional) + */ + protected $contextPrefix; + + /** + * Translates Monolog log levels to Graylog2 log priorities. + */ + private $logLevels = array( + Logger::DEBUG => 7, + Logger::INFO => 6, + Logger::NOTICE => 5, + Logger::WARNING => 4, + Logger::ERROR => 3, + Logger::CRITICAL => 2, + Logger::ALERT => 1, + Logger::EMERGENCY => 0, + ); + + public function __construct($systemName = null, $extraPrefix = null, $contextPrefix = 'ctxt_') + { + parent::__construct('U.u'); + + $this->systemName = $systemName ?: gethostname(); + + $this->extraPrefix = $extraPrefix; + $this->contextPrefix = $contextPrefix; + } + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + $record = parent::format($record); + $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']); + + foreach ($record['extra'] as $key => $val) { + $message->setAdditional($this->extraPrefix . $key, is_scalar($val) ? $val : $this->toJson($val)); + } + + foreach ($record['context'] as $key => $val) { + $message->setAdditional($this->contextPrefix . $key, is_scalar($val) ? $val : $this->toJson($val)); + } + + if (null === $message->getFile() && isset($record['context']['exception']['file'])) { + if (preg_match("/^(.+):([0-9]+)$/", $record['context']['exception']['file'], $matches)) { + $message->setFile($matches[1]); + $message->setLine($matches[2]); + } + } + + return $message; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php @@ -0,0 +1,140 @@ +<?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\Formatter; + +use Monolog\Logger; + +/** + * Formats incoming records into an HTML table + * + * This is especially useful for html email logging + * + * @author Tiago Brito <tlfbrito@gmail.com> + */ +class HtmlFormatter extends NormalizerFormatter +{ + /** + * Translates Monolog log levels to html color priorities. + */ + private $logLevels = array( + Logger::DEBUG => '#cccccc', + Logger::INFO => '#468847', + Logger::NOTICE => '#3a87ad', + Logger::WARNING => '#c09853', + Logger::ERROR => '#f0ad4e', + Logger::CRITICAL => '#FF7708', + Logger::ALERT => '#C12A19', + Logger::EMERGENCY => '#000000', + ); + + /** + * @param string $dateFormat The format of the timestamp: one supported by DateTime::format + */ + public function __construct($dateFormat = null) + { + parent::__construct($dateFormat); + } + + /** + * Creates an HTML table row + * + * @param string $th Row header content + * @param string $td Row standard cell content + * @param bool $escapeTd false if td content must not be html escaped + * @return string + */ + private function addRow($th, $td = ' ', $escapeTd = true) + { + $th = htmlspecialchars($th, ENT_NOQUOTES, 'UTF-8'); + if ($escapeTd) { + $td = '<pre>'.htmlspecialchars($td, ENT_NOQUOTES, 'UTF-8').'</pre>'; + } + + return "<tr style=\"padding: 4px;spacing: 0;text-align: left;\">\n<th style=\"background: #cccccc\" width=\"100px\">$th:</th>\n<td style=\"padding: 4px;spacing: 0;text-align: left;background: #eeeeee\">".$td."</td>\n</tr>"; + } + + /** + * Create a HTML h1 tag + * + * @param string $title Text to be in the h1 + * @param integer $level Error level + * @return string + */ + private function addTitle($title, $level) + { + $title = htmlspecialchars($title, ENT_NOQUOTES, 'UTF-8'); + + return '<h1 style="background: '.$this->logLevels[$level].';color: #ffffff;padding: 5px;" class="monolog-output">'.$title.'</h1>'; + } + /** + * Formats a log record. + * + * @param array $record A record to format + * @return mixed The formatted record + */ + public function format(array $record) + { + $output = $this->addTitle($record['level_name'], $record['level']); + $output .= '<table cellspacing="1" width="100%" class="monolog-output">'; + + $output .= $this->addRow('Message', (string) $record['message']); + $output .= $this->addRow('Time', $record['datetime']->format($this->dateFormat)); + $output .= $this->addRow('Channel', $record['channel']); + if ($record['context']) { + $embeddedTable = '<table cellspacing="1" width="100%">'; + foreach ($record['context'] as $key => $value) { + $embeddedTable .= $this->addRow($key, $this->convertToString($value)); + } + $embeddedTable .= '</table>'; + $output .= $this->addRow('Context', $embeddedTable, false); + } + if ($record['extra']) { + $embeddedTable = '<table cellspacing="1" width="100%">'; + foreach ($record['extra'] as $key => $value) { + $embeddedTable .= $this->addRow($key, $this->convertToString($value)); + } + $embeddedTable .= '</table>'; + $output .= $this->addRow('Extra', $embeddedTable, false); + } + + return $output.'</table>'; + } + + /** + * Formats a set of log records. + * + * @param array $records A set of records to format + * @return mixed The formatted set of records + */ + public function formatBatch(array $records) + { + $message = ''; + foreach ($records as $record) { + $message .= $this->format($record); + } + + return $message; + } + + protected function convertToString($data) + { + if (null === $data || is_scalar($data)) { + return (string) $data; + } + + $data = $this->normalize($data); + if (version_compare(PHP_VERSION, '5.4.0', '>=')) { + return json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } + + return str_replace('\\/', '/', json_encode($data)); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php @@ -0,0 +1,116 @@ +<?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\Formatter; + +/** + * Encodes whatever record data is passed to it as json + * + * This can be useful to log to databases or remote APIs + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class JsonFormatter implements FormatterInterface +{ + const BATCH_MODE_JSON = 1; + const BATCH_MODE_NEWLINES = 2; + + protected $batchMode; + protected $appendNewline; + + /** + * @param int $batchMode + */ + public function __construct($batchMode = self::BATCH_MODE_JSON, $appendNewline = true) + { + $this->batchMode = $batchMode; + $this->appendNewline = $appendNewline; + } + + /** + * 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 + * are available. + * + * @return int + */ + public function getBatchMode() + { + return $this->batchMode; + } + + /** + * True if newlines are appended to every formatted record + * + * @return bool + */ + public function isAppendingNewlines() + { + return $this->appendNewline; + } + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + return json_encode($record) . ($this->appendNewline ? "\n" : ''); + } + + /** + * {@inheritdoc} + */ + public function formatBatch(array $records) + { + switch ($this->batchMode) { + case static::BATCH_MODE_NEWLINES: + return $this->formatBatchNewlines($records); + + case static::BATCH_MODE_JSON: + default: + return $this->formatBatchJson($records); + } + } + + /** + * Return a JSON-encoded array of records. + * + * @param array $records + * @return string + */ + protected function formatBatchJson(array $records) + { + return json_encode($records); + } + + /** + * Use new lines to separate records instead of a + * JSON-encoded array. + * + * @param array $records + * @return string + */ + protected function formatBatchNewlines(array $records) + { + $instance = $this; + + $oldNewline = $this->appendNewline; + $this->appendNewline = false; + array_walk($records, function (&$value, $key) use ($instance) { + $value = $instance->format($value); + }); + $this->appendNewline = $oldNewline; + + return implode("\n", $records); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php @@ -0,0 +1,159 @@ +<?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\Formatter; + +use Exception; + +/** + * Formats incoming records into a one-line string + * + * This is especially useful for logging to files + * + * @author Jordi Boggiano <j.boggiano@seld.be> + * @author Christophe Coevoet <stof@notk.org> + */ +class LineFormatter extends NormalizerFormatter +{ + const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"; + + protected $format; + protected $allowInlineLineBreaks; + protected $ignoreEmptyContextAndExtra; + protected $includeStacktraces; + + /** + * @param string $format The format of the message + * @param string $dateFormat The format of the timestamp: one supported by DateTime::format + * @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries + * @param bool $ignoreEmptyContextAndExtra + */ + public function __construct($format = null, $dateFormat = null, $allowInlineLineBreaks = false, $ignoreEmptyContextAndExtra = false) + { + $this->format = $format ?: static::SIMPLE_FORMAT; + $this->allowInlineLineBreaks = $allowInlineLineBreaks; + $this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra; + parent::__construct($dateFormat); + } + + public function includeStacktraces($include = true) + { + $this->includeStacktraces = $include; + if ($this->includeStacktraces) { + $this->allowInlineLineBreaks = true; + } + } + + public function allowInlineLineBreaks($allow = true) + { + $this->allowInlineLineBreaks = $allow; + } + + public function ignoreEmptyContextAndExtra($ignore = true) + { + $this->ignoreEmptyContextAndExtra = $ignore; + } + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + $vars = parent::format($record); + + $output = $this->format; + + foreach ($vars['extra'] as $var => $val) { + if (false !== strpos($output, '%extra.'.$var.'%')) { + $output = str_replace('%extra.'.$var.'%', $this->stringify($val), $output); + unset($vars['extra'][$var]); + } + } + + if ($this->ignoreEmptyContextAndExtra) { + if (empty($vars['context'])) { + unset($vars['context']); + $output = str_replace('%context%', '', $output); + } + + if (empty($vars['extra'])) { + unset($vars['extra']); + $output = str_replace('%extra%', '', $output); + } + } + + foreach ($vars as $var => $val) { + if (false !== strpos($output, '%'.$var.'%')) { + $output = str_replace('%'.$var.'%', $this->stringify($val), $output); + } + } + + return $output; + } + + public function formatBatch(array $records) + { + $message = ''; + foreach ($records as $record) { + $message .= $this->format($record); + } + + return $message; + } + + public function stringify($value) + { + return $this->replaceNewlines($this->convertToString($value)); + } + + protected function normalizeException(Exception $e) + { + $previousText = ''; + if ($previous = $e->getPrevious()) { + do { + $previousText .= ', '.get_class($previous).'(code: '.$previous->getCode().'): '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine(); + } while ($previous = $previous->getPrevious()); + } + + $str = '[object] ('.get_class($e).'(code: '.$e->getCode().'): '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine().$previousText.')'; + if ($this->includeStacktraces) { + $str .= "\n[stacktrace]\n".$e->getTraceAsString(); + } + + return $str; + } + + protected function convertToString($data) + { + if (null === $data || is_bool($data)) { + return var_export($data, true); + } + + if (is_scalar($data)) { + return (string) $data; + } + + if (version_compare(PHP_VERSION, '5.4.0', '>=')) { + return $this->toJson($data, true); + } + + return str_replace('\\/', '/', @json_encode($data)); + } + + protected function replaceNewlines($str) + { + if ($this->allowInlineLineBreaks) { + return $str; + } + + return strtr($str, array("\r\n" => ' ', "\r" => ' ', "\n" => ' ')); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php @@ -0,0 +1,47 @@ +<?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\Formatter; + +/** + * Encodes message information into JSON in a format compatible with Loggly. + * + * @author Adam Pancutt <adam@pancutt.com> + */ +class LogglyFormatter extends JsonFormatter +{ + /** + * Overrides the default batch mode to new lines for compatibility with the + * Loggly bulk API. + * + * @param integer $batchMode + */ + public function __construct($batchMode = self::BATCH_MODE_NEWLINES, $appendNewline = false) + { + parent::__construct($batchMode, $appendNewline); + } + + /** + * Appends the 'timestamp' parameter for indexing by Loggly. + * + * @see https://www.loggly.com/docs/automated-parsing/#json + * @see \Monolog\Formatter\JsonFormatter::format() + */ + public function format(array $record) + { + if (isset($record["datetime"]) && ($record["datetime"] instanceof \DateTime)) { + $record["timestamp"] = $record["datetime"]->format("Y-m-d\TH:i:s.uO"); + // TODO 2.0 unset the 'datetime' parameter, retained for BC + } + + return parent::format($record); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php @@ -0,0 +1,165 @@ +<?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\Formatter; + +/** + * Serializes a log message to Logstash Event Format + * + * @see http://logstash.net/ + * @see https://github.com/logstash/logstash/blob/master/lib/logstash/event.rb + * + * @author Tim Mower <timothy.mower@gmail.com> + */ +class LogstashFormatter extends NormalizerFormatter +{ + const V0 = 0; + const V1 = 1; + + /** + * @var string the name of the system for the Logstash log message, used to fill the @source field + */ + protected $systemName; + + /** + * @var string an application name for the Logstash log message, used to fill the @type field + */ + protected $applicationName; + + /** + * @var string a prefix for 'extra' fields from the Monolog record (optional) + */ + protected $extraPrefix; + + /** + * @var string a prefix for 'context' fields from the Monolog record (optional) + */ + protected $contextPrefix; + + /** + * @var integer logstash format version to use + */ + protected $version; + + /** + * @param string $applicationName the application that sends the data, used as the "type" field of logstash + * @param string $systemName the system/machine name, used as the "source" field of logstash, defaults to the hostname of the machine + * @param string $extraPrefix prefix for extra keys inside logstash "fields" + * @param string $contextPrefix prefix for context keys inside logstash "fields", defaults to ctxt_ + */ + public function __construct($applicationName, $systemName = null, $extraPrefix = null, $contextPrefix = 'ctxt_', $version = self::V0) + { + // logstash requires a ISO 8601 format date with optional millisecond precision. + parent::__construct('Y-m-d\TH:i:s.uP'); + + $this->systemName = $systemName ?: gethostname(); + $this->applicationName = $applicationName; + $this->extraPrefix = $extraPrefix; + $this->contextPrefix = $contextPrefix; + $this->version = $version; + } + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + $record = parent::format($record); + + if ($this->version === self::V1) { + $message = $this->formatV1($record); + } else { + $message = $this->formatV0($record); + } + + return $this->toJson($message) . "\n"; + } + + protected function formatV0(array $record) + { + if (empty($record['datetime'])) { + $record['datetime'] = gmdate('c'); + } + $message = array( + '@timestamp' => $record['datetime'], + '@source' => $this->systemName, + '@fields' => array() + ); + if (isset($record['message'])) { + $message['@message'] = $record['message']; + } + if (isset($record['channel'])) { + $message['@tags'] = array($record['channel']); + $message['@fields']['channel'] = $record['channel']; + } + if (isset($record['level'])) { + $message['@fields']['level'] = $record['level']; + } + if ($this->applicationName) { + $message['@type'] = $this->applicationName; + } + if (isset($record['extra']['server'])) { + $message['@source_host'] = $record['extra']['server']; + } + if (isset($record['extra']['url'])) { + $message['@source_path'] = $record['extra']['url']; + } + if (!empty($record['extra'])) { + foreach ($record['extra'] as $key => $val) { + $message['@fields'][$this->extraPrefix . $key] = $val; + } + } + if (!empty($record['context'])) { + foreach ($record['context'] as $key => $val) { + $message['@fields'][$this->contextPrefix . $key] = $val; + } + } + + return $message; + } + + protected function formatV1(array $record) + { + if (empty($record['datetime'])) { + $record['datetime'] = gmdate('c'); + } + $message = array( + '@timestamp' => $record['datetime'], + '@version' => 1, + 'host' => $this->systemName, + ); + if (isset($record['message'])) { + $message['message'] = $record['message']; + } + if (isset($record['channel'])) { + $message['type'] = $record['channel']; + $message['channel'] = $record['channel']; + } + if (isset($record['level_name'])) { + $message['level'] = $record['level_name']; + } + if ($this->applicationName) { + $message['type'] = $this->applicationName; + } + if (!empty($record['extra'])) { + foreach ($record['extra'] as $key => $val) { + $message[$this->extraPrefix . $key] = $val; + } + } + if (!empty($record['context'])) { + foreach ($record['context'] as $key => $val) { + $message[$this->contextPrefix . $key] = $val; + } + } + + return $message; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php @@ -0,0 +1,105 @@ +<?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\Formatter; + +/** + * Formats a record for use with the MongoDBHandler. + * + * @author Florian Plattner <me@florianplattner.de> + */ +class MongoDBFormatter implements FormatterInterface +{ + private $exceptionTraceAsString; + private $maxNestingLevel; + + /** + * @param int $maxNestingLevel 0 means infinite nesting, the $record itself is level 1, $record['context'] is 2 + * @param bool $exceptionTraceAsString set to false to log exception traces as a sub documents instead of strings + */ + public function __construct($maxNestingLevel = 3, $exceptionTraceAsString = true) + { + $this->maxNestingLevel = max($maxNestingLevel, 0); + $this->exceptionTraceAsString = (bool) $exceptionTraceAsString; + } + + /** + * {@inheritDoc} + */ + public function format(array $record) + { + return $this->formatArray($record); + } + + /** + * {@inheritDoc} + */ + public function formatBatch(array $records) + { + foreach ($records as $key => $record) { + $records[$key] = $this->format($record); + } + + return $records; + } + + protected function formatArray(array $record, $nestingLevel = 0) + { + if ($this->maxNestingLevel == 0 || $nestingLevel <= $this->maxNestingLevel) { + foreach ($record as $name => $value) { + if ($value instanceof \DateTime) { + $record[$name] = $this->formatDate($value, $nestingLevel + 1); + } elseif ($value instanceof \Exception) { + $record[$name] = $this->formatException($value, $nestingLevel + 1); + } elseif (is_array($value)) { + $record[$name] = $this->formatArray($value, $nestingLevel + 1); + } elseif (is_object($value)) { + $record[$name] = $this->formatObject($value, $nestingLevel + 1); + } + } + } else { + $record = '[...]'; + } + + return $record; + } + + protected function formatObject($value, $nestingLevel) + { + $objectVars = get_object_vars($value); + $objectVars['class'] = get_class($value); + + return $this->formatArray($objectVars, $nestingLevel); + } + + protected function formatException(\Exception $exception, $nestingLevel) + { + $formattedException = array( + 'class' => get_class($exception), + 'message' => $exception->getMessage(), + 'code' => $exception->getCode(), + 'file' => $exception->getFile() . ':' . $exception->getLine(), + ); + + if ($this->exceptionTraceAsString === true) { + $formattedException['trace'] = $exception->getTraceAsString(); + } else { + $formattedException['trace'] = $exception->getTrace(); + } + + return $this->formatArray($formattedException, $nestingLevel); + } + + protected function formatDate(\DateTime $value, $nestingLevel) + { + return new \MongoDate($value->getTimestamp()); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php @@ -0,0 +1,141 @@ +<?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\Formatter; + +use Exception; + +/** + * Normalizes incoming records to remove objects/resources so it's easier to dump to various targets + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class NormalizerFormatter implements FormatterInterface +{ + const SIMPLE_DATE = "Y-m-d H:i:s"; + + protected $dateFormat; + + /** + * @param string $dateFormat The format of the timestamp: one supported by DateTime::format + */ + public function __construct($dateFormat = null) + { + $this->dateFormat = $dateFormat ?: static::SIMPLE_DATE; + if (!function_exists('json_encode')) { + throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s NormalizerFormatter'); + } + } + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + return $this->normalize($record); + } + + /** + * {@inheritdoc} + */ + public function formatBatch(array $records) + { + foreach ($records as $key => $record) { + $records[$key] = $this->format($record); + } + + return $records; + } + + protected function normalize($data) + { + if (null === $data || is_scalar($data)) { + return $data; + } + + if (is_array($data) || $data instanceof \Traversable) { + $normalized = array(); + + $count = 1; + foreach ($data as $key => $value) { + if ($count++ >= 1000) { + $normalized['...'] = 'Over 1000 items, aborting normalization'; + break; + } + $normalized[$key] = $this->normalize($value); + } + + return $normalized; + } + + if ($data instanceof \DateTime) { + return $data->format($this->dateFormat); + } + + if (is_object($data)) { + if ($data instanceof Exception) { + return $this->normalizeException($data); + } + + return sprintf("[object] (%s: %s)", get_class($data), $this->toJson($data, true)); + } + + if (is_resource($data)) { + return '[resource]'; + } + + return '[unknown('.gettype($data).')]'; + } + + protected function normalizeException(Exception $e) + { + $data = array( + 'class' => get_class($e), + 'message' => $e->getMessage(), + 'code' => $e->getCode(), + 'file' => $e->getFile().':'.$e->getLine(), + ); + + $trace = $e->getTrace(); + foreach ($trace as $frame) { + if (isset($frame['file'])) { + $data['trace'][] = $frame['file'].':'.$frame['line']; + } else { + // We should again normalize the frames, because it might contain invalid items + $data['trace'][] = $this->toJson($this->normalize($frame), true); + } + } + + if ($previous = $e->getPrevious()) { + $data['previous'] = $this->normalizeException($previous); + } + + return $data; + } + + protected function toJson($data, $ignoreErrors = false) + { + // suppress json_encode errors since it's twitchy with some inputs + if ($ignoreErrors) { + if (version_compare(PHP_VERSION, '5.4.0', '>=')) { + return @json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } + + return @json_encode($data); + } + + if (version_compare(PHP_VERSION, '5.4.0', '>=')) { + return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } + + return json_encode($data); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php @@ -0,0 +1,48 @@ +<?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\Formatter; + +/** + * Formats data into an associative array of scalar values. + * Objects and arrays will be JSON encoded. + * + * @author Andrew Lawson <adlawson@gmail.com> + */ +class ScalarFormatter extends NormalizerFormatter +{ + /** + * {@inheritdoc} + */ + public function format(array $record) + { + foreach ($record as $key => $value) { + $record[$key] = $this->normalizeValue($value); + } + + return $record; + } + + /** + * @param mixed $value + * @return mixed + */ + protected function normalizeValue($value) + { + $normalized = $this->normalize($value); + + if (is_array($normalized) || is_object($normalized)) { + return $this->toJson($normalized, true); + } + + return $normalized; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php @@ -0,0 +1,113 @@ +<?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\Formatter; + +use Monolog\Logger; + +/** + * Serializes a log message according to Wildfire's header requirements + * + * @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com> + * @author Christophe Coevoet <stof@notk.org> + * @author Kirill chEbba Chebunin <iam@chebba.org> + */ +class WildfireFormatter extends NormalizerFormatter +{ + const TABLE = 'table'; + + /** + * Translates Monolog log levels to Wildfire levels. + */ + private $logLevels = array( + Logger::DEBUG => 'LOG', + Logger::INFO => 'INFO', + Logger::NOTICE => 'INFO', + Logger::WARNING => 'WARN', + Logger::ERROR => 'ERROR', + Logger::CRITICAL => 'ERROR', + Logger::ALERT => 'ERROR', + Logger::EMERGENCY => 'ERROR', + ); + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + // Retrieve the line and file if set and remove them from the formatted extra + $file = $line = ''; + if (isset($record['extra']['file'])) { + $file = $record['extra']['file']; + unset($record['extra']['file']); + } + if (isset($record['extra']['line'])) { + $line = $record['extra']['line']; + unset($record['extra']['line']); + } + + $record = $this->normalize($record); + $message = array('message' => $record['message']); + $handleError = false; + if ($record['context']) { + $message['context'] = $record['context']; + $handleError = true; + } + if ($record['extra']) { + $message['extra'] = $record['extra']; + $handleError = true; + } + if (count($message) === 1) { + $message = reset($message); + } + + if (isset($record['context'][self::TABLE])) { + $type = 'TABLE'; + $label = $record['channel'] .': '. $record['message']; + $message = $record['context'][self::TABLE]; + } else { + $type = $this->logLevels[$record['level']]; + $label = $record['channel']; + } + + // Create JSON object describing the appearance of the message in the console + $json = $this->toJson(array( + array( + 'Type' => $type, + 'File' => $file, + 'Line' => $line, + 'Label' => $label, + ), + $message, + ), $handleError); + + // The message itself is a serialization of the above JSON object + it's length + return sprintf( + '%s|%s|', + strlen($json), + $json + ); + } + + public function formatBatch(array $records) + { + throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter'); + } + + protected function normalize($data) + { + if (is_object($data) && !$data instanceof \DateTime) { + return $data; + } + + return parent::normalize($data); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php @@ -0,0 +1,184 @@ +<?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 Monolog\Logger; +use Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\LineFormatter; + +/** + * Base Handler class providing the Handler structure + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +abstract class AbstractHandler implements HandlerInterface +{ + protected $level = Logger::DEBUG; + protected $bubble = true; + + /** + * @var FormatterInterface + */ + protected $formatter; + protected $processors = array(); + + /** + * @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($level = Logger::DEBUG, $bubble = true) + { + $this->setLevel($level); + $this->bubble = $bubble; + } + + /** + * {@inheritdoc} + */ + public function isHandling(array $record) + { + return $record['level'] >= $this->level; + } + + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + foreach ($records as $record) { + $this->handle($record); + } + } + + /** + * Closes the handler. + * + * This will be called automatically when the object is destroyed + */ + public function close() + { + } + + /** + * {@inheritdoc} + */ + public function pushProcessor($callback) + { + if (!is_callable($callback)) { + 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; + } + + /** + * {@inheritdoc} + */ + public function popProcessor() + { + if (!$this->processors) { + throw new \LogicException('You tried to pop from an empty processor stack.'); + } + + return array_shift($this->processors); + } + + /** + * {@inheritdoc} + */ + public function setFormatter(FormatterInterface $formatter) + { + $this->formatter = $formatter; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getFormatter() + { + if (!$this->formatter) { + $this->formatter = $this->getDefaultFormatter(); + } + + return $this->formatter; + } + + /** + * Sets minimum logging level at which this handler will be triggered. + * + * @param integer $level + * @return self + */ + public function setLevel($level) + { + $this->level = Logger::toMonologLevel($level); + + return $this; + } + + /** + * Gets minimum logging level at which this handler will be triggered. + * + * @return integer + */ + public function getLevel() + { + return $this->level; + } + + /** + * Sets the bubbling behavior. + * + * @param Boolean $bubble true means that this handler allows bubbling. + * false means that bubbling is not permitted. + * @return self + */ + public function setBubble($bubble) + { + $this->bubble = $bubble; + + return $this; + } + + /** + * Gets the bubbling behavior. + * + * @return Boolean true means that this handler allows bubbling. + * false means that bubbling is not permitted. + */ + public function getBubble() + { + return $this->bubble; + } + + public function __destruct() + { + try { + $this->close(); + } catch (\Exception $e) { + // do nothing + } + } + + /** + * Gets the default formatter. + * + * @return FormatterInterface + */ + protected function getDefaultFormatter() + { + return new LineFormatter(); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php @@ -0,0 +1,66 @@ +<?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; + +/** + * Base Handler class providing the Handler structure + * + * Classes extending it should (in most cases) only implement write($record) + * + * @author Jordi Boggiano <j.boggiano@seld.be> + * @author Christophe Coevoet <stof@notk.org> + */ +abstract class AbstractProcessingHandler extends AbstractHandler +{ + /** + * {@inheritdoc} + */ + public function handle(array $record) + { + if (!$this->isHandling($record)) { + return false; + } + + $record = $this->processRecord($record); + + $record['formatted'] = $this->getFormatter()->format($record); + + $this->write($record); + + return false === $this->bubble; + } + + /** + * Writes the record down to the log of the implementing handler + * + * @param array $record + * @return void + */ + abstract protected function write(array $record); + + /** + * Processes a record. + * + * @param array $record + * @return array + */ + protected function processRecord(array $record) + { + if ($this->processors) { + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + } + + return $record; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php @@ -0,0 +1,92 @@ +<?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 Monolog\Logger; +use Monolog\Formatter\LineFormatter; + +/** + * Common syslog functionality + */ +abstract class AbstractSyslogHandler extends AbstractProcessingHandler +{ + protected $facility; + + /** + * Translates Monolog log levels to syslog log priorities. + */ + protected $logLevels = array( + Logger::DEBUG => LOG_DEBUG, + Logger::INFO => LOG_INFO, + Logger::NOTICE => LOG_NOTICE, + Logger::WARNING => LOG_WARNING, + Logger::ERROR => LOG_ERR, + Logger::CRITICAL => LOG_CRIT, + Logger::ALERT => LOG_ALERT, + Logger::EMERGENCY => LOG_EMERG, + ); + + /** + * List of valid log facility names. + */ + protected $facilities = array( + 'auth' => LOG_AUTH, + 'authpriv' => LOG_AUTHPRIV, + 'cron' => LOG_CRON, + 'daemon' => LOG_DAEMON, + 'kern' => LOG_KERN, + 'lpr' => LOG_LPR, + 'mail' => LOG_MAIL, + 'news' => LOG_NEWS, + 'syslog' => LOG_SYSLOG, + 'user' => LOG_USER, + 'uucp' => LOG_UUCP, + ); + + /** + * @param mixed $facility + * @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($facility = LOG_USER, $level = Logger::DEBUG, $bubble = true) + { + parent::__construct($level, $bubble); + + if (!defined('PHP_WINDOWS_VERSION_BUILD')) { + $this->facilities['local0'] = LOG_LOCAL0; + $this->facilities['local1'] = LOG_LOCAL1; + $this->facilities['local2'] = LOG_LOCAL2; + $this->facilities['local3'] = LOG_LOCAL3; + $this->facilities['local4'] = LOG_LOCAL4; + $this->facilities['local5'] = LOG_LOCAL5; + $this->facilities['local6'] = LOG_LOCAL6; + $this->facilities['local7'] = LOG_LOCAL7; + } + + // convert textual description of facility to syslog constant + if (array_key_exists(strtolower($facility), $this->facilities)) { + $facility = $this->facilities[strtolower($facility)]; + } elseif (!in_array($facility, array_values($this->facilities), true)) { + throw new \UnexpectedValueException('Unknown facility value "'.$facility.'" given'); + } + + $this->facility = $facility; + } + + /** + * {@inheritdoc} + */ + protected function getDefaultFormatter() + { + return new LineFormatter('%channel%.%level_name%: %message% %context% %extra%'); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php @@ -0,0 +1,98 @@ +<?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 Monolog\Logger; +use Monolog\Formatter\JsonFormatter; +use PhpAmqpLib\Message\AMQPMessage; +use PhpAmqpLib\Channel\AMQPChannel; +use AMQPExchange; + +class AmqpHandler extends AbstractProcessingHandler +{ + /** + * @var AMQPExchange|AMQPChannel $exchange + */ + protected $exchange; + + /** + * @var string + */ + protected $exchangeName; + + /** + * @param AMQPExchange|AMQPChannel $exchange AMQPExchange (php AMQP ext) or PHP AMQP lib channel, ready for use + * @param string $exchangeName + * @param int $level + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct($exchange, $exchangeName = 'log', $level = Logger::DEBUG, $bubble = true) + { + if ($exchange instanceof AMQPExchange) { + $exchange->setName($exchangeName); + } elseif ($exchange instanceof AMQPChannel) { + $this->exchangeName = $exchangeName; + } else { + throw new \InvalidArgumentException('PhpAmqpLib\Channel\AMQPChannel or AMQPExchange instance required'); + } + $this->exchange = $exchange; + + parent::__construct($level, $bubble); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record) + { + $data = $record["formatted"]; + + $routingKey = sprintf( + '%s.%s', + // TODO 2.0 remove substr call + substr($record['level_name'], 0, 4), + $record['channel'] + ); + + if ($this->exchange instanceof AMQPExchange) { + $this->exchange->publish( + $data, + strtolower($routingKey), + 0, + array( + 'delivery_mode' => 2, + 'Content-type' => 'application/json' + ) + ); + } else { + $this->exchange->basic_publish( + new AMQPMessage( + (string) $data, + array( + 'delivery_mode' => 2, + 'content_type' => 'application/json' + ) + ), + $this->exchangeName, + strtolower($routingKey) + ); + } + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php @@ -0,0 +1,184 @@ +<?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 Monolog\Formatter\LineFormatter; + +/** + * Handler sending logs to browser's javascript console with no browser extension required + * + * @author Olivier Poitrey <rs@dailymotion.com> + */ +class BrowserConsoleHandler extends AbstractProcessingHandler +{ + protected static $initialized = false; + protected static $records = array(); + + /** + * {@inheritDoc} + * + * Formatted output may contain some formatting markers to be transfered to `console.log` using the %c format. + * + * Example of formatted string: + * + * You can do [[blue text]]{color: blue} or [[green background]]{background-color: green; color: white} + * + */ + protected function getDefaultFormatter() + { + return new LineFormatter('[[%channel%]]{macro: autolabel} [[%level_name%]]{font-weight: bold} %message%'); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record) + { + // Accumulate records + self::$records[] = $record; + + // Register shutdown handler if not already done + if (PHP_SAPI !== 'cli' && !self::$initialized) { + self::$initialized = true; + register_shutdown_function(array('Monolog\Handler\BrowserConsoleHandler', 'send')); + } + } + + /** + * Convert records to javascript console commands and send it to the browser. + * This method is automatically called on PHP shutdown if output is HTML. + */ + public static function send() + { + // Check content type + foreach (headers_list() as $header) { + if (stripos($header, 'content-type:') === 0) { + if (stripos($header, 'text/html') === false) { + // This handler only works with HTML outputs + return; + } + break; + } + } + + if (count(self::$records)) { + echo '<script>' . self::generateScript() . '</script>'; + self::reset(); + } + } + + /** + * Forget all logged records + */ + public static function reset() + { + self::$records = array(); + } + + private static function generateScript() + { + $script = array(); + foreach (self::$records as $record) { + $context = self::dump('Context', $record['context']); + $extra = self::dump('Extra', $record['extra']); + + if (empty($context) && empty($extra)) { + $script[] = self::call_array('log', self::handleStyles($record['formatted'])); + } else { + $script = array_merge($script, + array(self::call_array('groupCollapsed', self::handleStyles($record['formatted']))), + $context, + $extra, + array(self::call('groupEnd')) + ); + } + } + + return "(function (c) {if (c && c.groupCollapsed) {\n" . implode("\n", $script) . "\n}})(console);"; + } + + private static function handleStyles($formatted) + { + $args = array(self::quote('font-weight: normal')); + $format = '%c' . $formatted; + preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); + + foreach (array_reverse($matches) as $match) { + $args[] = self::quote(self::handleCustomStyles($match[2][0], $match[1][0])); + $args[] = '"font-weight: normal"'; + + $pos = $match[0][1]; + $format = substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . substr($format, $pos + strlen($match[0][0])); + } + + array_unshift($args, self::quote($format)); + + return $args; + } + + private static function handleCustomStyles($style, $string) + { + static $colors = array('blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey'); + static $labels = array(); + + return preg_replace_callback('/macro\s*:(.*?)(?:;|$)/', function ($m) use ($string, &$colors, &$labels) { + if (trim($m[1]) === 'autolabel') { + // Format the string as a label with consistent auto assigned background color + if (!isset($labels[$string])) { + $labels[$string] = $colors[count($labels) % count($colors)]; + } + $color = $labels[$string]; + + return "background-color: $color; color: white; border-radius: 3px; padding: 0 2px 0 2px"; + } + + return $m[1]; + }, $style); + } + + private static function dump($title, array $dict) + { + $script = array(); + $dict = array_filter($dict); + if (empty($dict)) { + return $script; + } + $script[] = self::call('log', self::quote('%c%s'), self::quote('font-weight: bold'), self::quote($title)); + foreach ($dict as $key => $value) { + $value = json_encode($value); + if (empty($value)) { + $value = self::quote(''); + } + $script[] = self::call('log', self::quote('%s: %o'), self::quote($key), $value); + } + + return $script; + } + + private static function quote($arg) + { + return '"' . addcslashes($arg, "\"\n") . '"'; + } + + private static function call() + { + $args = func_get_args(); + $method = array_shift($args); + + return self::call_array($method, $args); + } + + private static function call_array($method, array $args) + { + return 'c.' . $method . '(' . implode(', ', $args) . ');'; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php @@ -0,0 +1,117 @@ +<?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 Monolog\Logger; + +/** + * Buffers all records until closing the handler and then pass them as batch. + * + * This is useful for a MailHandler to send only one mail per request instead of + * sending one per log message. + * + * @author Christophe Coevoet <stof@notk.org> + */ +class BufferHandler extends AbstractHandler +{ + protected $handler; + protected $bufferSize = 0; + protected $bufferLimit; + protected $flushOnOverflow; + protected $buffer = array(); + protected $initialized = false; + + /** + * @param HandlerInterface $handler Handler. + * @param integer $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. + * @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 Boolean $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded + */ + public function __construct(HandlerInterface $handler, $bufferLimit = 0, $level = Logger::DEBUG, $bubble = true, $flushOnOverflow = false) + { + parent::__construct($level, $bubble); + $this->handler = $handler; + $this->bufferLimit = (int) $bufferLimit; + $this->flushOnOverflow = $flushOnOverflow; + } + + /** + * {@inheritdoc} + */ + public function handle(array $record) + { + if ($record['level'] < $this->level) { + return false; + } + + if (!$this->initialized) { + // __destructor() doesn't get called on Fatal errors + register_shutdown_function(array($this, 'close')); + $this->initialized = true; + } + + if ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) { + if ($this->flushOnOverflow) { + $this->flush(); + } else { + array_shift($this->buffer); + $this->bufferSize--; + } + } + + if ($this->processors) { + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + } + + $this->buffer[] = $record; + $this->bufferSize++; + + return false === $this->bubble; + } + + public function flush() + { + if ($this->bufferSize === 0) { + return; + } + + $this->handler->handleBatch($this->buffer); + $this->clear(); + } + + public function __destruct() + { + // suppress the parent behavior since we already have register_shutdown_function() + // to call close(), and the reference contained there will prevent this from being + // GC'd until the end of the request + } + + /** + * {@inheritdoc} + */ + public function close() + { + $this->flush(); + } + + /** + * Clears the buffer without flushing any messages down to the wrapped handler. + */ + public function clear() + { + $this->bufferSize = 0; + $this->buffer = array(); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php @@ -0,0 +1,204 @@ +<?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 Monolog\Formatter\ChromePHPFormatter; +use Monolog\Logger; + +/** + * Handler sending logs to the ChromePHP extension (http://www.chromephp.com/) + * + * @author Christophe Coevoet <stof@notk.org> + */ +class ChromePHPHandler extends AbstractProcessingHandler +{ + /** + * Version of the extension + */ + const VERSION = '4.0'; + + /** + * Header name + */ + const HEADER_NAME = 'X-ChromeLogger-Data'; + + protected static $initialized = false; + + /** + * Tracks whether we sent too much data + * + * Chrome limits the headers to 256KB, so when we sent 240KB we stop sending + * + * @var Boolean + */ + protected static $overflowed = false; + + protected static $json = array( + 'version' => self::VERSION, + 'columns' => array('label', 'log', 'backtrace', 'type'), + 'rows' => array(), + ); + + protected static $sendHeaders = true; + + /** + * @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($level = Logger::DEBUG, $bubble = true) + { + parent::__construct($level, $bubble); + if (!function_exists('json_encode')) { + throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s ChromePHPHandler'); + } + } + + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + $messages = array(); + + foreach ($records as $record) { + if ($record['level'] < $this->level) { + continue; + } + $messages[] = $this->processRecord($record); + } + + if (!empty($messages)) { + $messages = $this->getFormatter()->formatBatch($messages); + self::$json['rows'] = array_merge(self::$json['rows'], $messages); + $this->send(); + } + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new ChromePHPFormatter(); + } + + /** + * Creates & sends header for a record + * + * @see sendHeader() + * @see send() + * @param array $record + */ + protected function write(array $record) + { + self::$json['rows'][] = $record['formatted']; + + $this->send(); + } + + /** + * Sends the log header + * + * @see sendHeader() + */ + protected function send() + { + if (self::$overflowed || !self::$sendHeaders) { + return; + } + + if (!self::$initialized) { + self::$initialized = true; + + self::$sendHeaders = $this->headersAccepted(); + if (!self::$sendHeaders) { + return; + } + + self::$json['request_uri'] = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''; + } + + $json = @json_encode(self::$json); + $data = base64_encode(utf8_encode($json)); + if (strlen($data) > 240*1024) { + self::$overflowed = true; + + $record = array( + 'message' => 'Incomplete logs, chrome header size limit reached', + 'context' => array(), + 'level' => Logger::WARNING, + 'level_name' => Logger::getLevelName(Logger::WARNING), + 'channel' => 'monolog', + 'datetime' => new \DateTime(), + 'extra' => array(), + ); + self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record); + $json = @json_encode(self::$json); + $data = base64_encode(utf8_encode($json)); + } + + if (trim($data) !== '') { + $this->sendHeader(self::HEADER_NAME, $data); + } + } + + /** + * Send header string to the client + * + * @param string $header + * @param string $content + */ + protected function sendHeader($header, $content) + { + if (!headers_sent() && self::$sendHeaders) { + header(sprintf('%s: %s', $header, $content)); + } + } + + /** + * Verifies if the headers are accepted by the current user agent + * + * @return Boolean + */ + protected function headersAccepted() + { + if (empty($_SERVER['HTTP_USER_AGENT'])) { + return false; + } + + return preg_match('{\bChrome/\d+[\.\d+]*\b}', $_SERVER['HTTP_USER_AGENT']); + } + + /** + * BC getter for the sendHeaders property that has been made static + */ + public function __get($property) + { + if ('sendHeaders' !== $property) { + throw new \InvalidArgumentException('Undefined property '.$property); + } + + return static::$sendHeaders; + } + + /** + * BC setter for the sendHeaders property that has been made static + */ + public function __set($property, $value) + { + if ('sendHeaders' !== $property) { + throw new \InvalidArgumentException('Undefined property '.$property); + } + + static::$sendHeaders = $value; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php @@ -0,0 +1,72 @@ +<?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 Monolog\Formatter\JsonFormatter; +use Monolog\Logger; + +/** + * CouchDB handler + * + * @author Markus Bachmann <markus.bachmann@bachi.biz> + */ +class CouchDBHandler extends AbstractProcessingHandler +{ + private $options; + + public function __construct(array $options = array(), $level = Logger::DEBUG, $bubble = true) + { + $this->options = array_merge(array( + 'host' => 'localhost', + 'port' => 5984, + 'dbname' => 'logger', + 'username' => null, + 'password' => null, + ), $options); + + parent::__construct($level, $bubble); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record) + { + $basicAuth = null; + if ($this->options['username']) { + $basicAuth = sprintf('%s:%s@', $this->options['username'], $this->options['password']); + } + + $url = 'http://'.$basicAuth.$this->options['host'].':'.$this->options['port'].'/'.$this->options['dbname']; + $context = stream_context_create(array( + 'http' => array( + 'method' => 'POST', + 'content' => $record['formatted'], + 'ignore_errors' => true, + 'max_redirects' => 0, + 'header' => 'Content-type: application/json', + ) + )); + + if (false === @file_get_contents($url, null, $context)) { + throw new \RuntimeException(sprintf('Could not connect to %s', $url)); + } + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php @@ -0,0 +1,145 @@ +<?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 Monolog\Logger; + +/** + * Logs to Cube. + * + * @link http://square.github.com/cube/ + * @author Wan Chen <kami@kamisama.me> + */ +class CubeHandler extends AbstractProcessingHandler +{ + private $udpConnection = null; + private $httpConnection = null; + private $scheme = null; + private $host = null; + private $port = null; + private $acceptedSchemes = array('http', 'udp'); + + /** + * Create a Cube handler + * + * @throws UnexpectedValueException when given url is not a valid url. + * A valid url must consists of three parts : protocol://host:port + * Only valid protocol used by Cube are http and udp + */ + public function __construct($url, $level = Logger::DEBUG, $bubble = true) + { + $urlInfos = parse_url($url); + + if (!isset($urlInfos['scheme']) || !isset($urlInfos['host']) || !isset($urlInfos['port'])) { + throw new \UnexpectedValueException('URL "'.$url.'" is not valid'); + } + + if (!in_array($urlInfos['scheme'], $this->acceptedSchemes)) { + throw new \UnexpectedValueException( + 'Invalid protocol (' . $urlInfos['scheme'] . ').' + . ' Valid options are ' . implode(', ', $this->acceptedSchemes)); + } + + $this->scheme = $urlInfos['scheme']; + $this->host = $urlInfos['host']; + $this->port = $urlInfos['port']; + + parent::__construct($level, $bubble); + } + + /** + * Establish a connection to an UDP socket + * + * @throws LogicException when unable to connect to the socket + */ + protected function connectUdp() + { + if (!extension_loaded('sockets')) { + throw new MissingExtensionException('The sockets extension is required to use udp URLs with the CubeHandler'); + } + + $this->udpConnection = socket_create(AF_INET, SOCK_DGRAM, 0); + if (!$this->udpConnection) { + throw new \LogicException('Unable to create a socket'); + } + + if (!socket_connect($this->udpConnection, $this->host, $this->port)) { + throw new \LogicException('Unable to connect to the socket at ' . $this->host . ':' . $this->port); + } + } + + /** + * Establish a connection to a http server + */ + protected function connectHttp() + { + if (!extension_loaded('curl')) { + throw new \LogicException('The curl extension is needed to use http URLs with the CubeHandler'); + } + + $this->httpConnection = curl_init('http://'.$this->host.':'.$this->port.'/1.0/event/put'); + + if (!$this->httpConnection) { + throw new \LogicException('Unable to connect to ' . $this->host . ':' . $this->port); + } + + curl_setopt($this->httpConnection, CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($this->httpConnection, CURLOPT_RETURNTRANSFER, true); + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + $date = $record['datetime']; + + $data = array('time' => $date->format('Y-m-d\TH:i:s.uO')); + unset($record['datetime']); + + if (isset($record['context']['type'])) { + $data['type'] = $record['context']['type']; + unset($record['context']['type']); + } else { + $data['type'] = $record['channel']; + } + + $data['data'] = $record['context']; + $data['data']['level'] = $record['level']; + + $this->{'write'.$this->scheme}(json_encode($data)); + } + + private function writeUdp($data) + { + if (!$this->udpConnection) { + $this->connectUdp(); + } + + socket_send($this->udpConnection, $data, strlen($data), 0); + } + + private function writeHttp($data) + { + if (!$this->httpConnection) { + $this->connectHttp(); + } + + curl_setopt($this->httpConnection, CURLOPT_POSTFIELDS, '['.$data.']'); + curl_setopt($this->httpConnection, CURLOPT_HTTPHEADER, array( + 'Content-Type: application/json', + 'Content-Length: ' . strlen('['.$data.']')) + ); + + return curl_exec($this->httpConnection); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php @@ -0,0 +1,45 @@ +<?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 Monolog\Logger; +use Monolog\Formatter\NormalizerFormatter; +use Doctrine\CouchDB\CouchDBClient; + +/** + * CouchDB handler for Doctrine CouchDB ODM + * + * @author Markus Bachmann <markus.bachmann@bachi.biz> + */ +class DoctrineCouchDBHandler extends AbstractProcessingHandler +{ + private $client; + + public function __construct(CouchDBClient $client, $level = Logger::DEBUG, $bubble = true) + { + $this->client = $client; + parent::__construct($level, $bubble); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record) + { + $this->client->postDocument($record['formatted']); + } + + protected function getDefaultFormatter() + { + return new NormalizerFormatter; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php @@ -0,0 +1,89 @@ +<?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 Aws\Common\Aws; +use Aws\DynamoDb\DynamoDbClient; +use Monolog\Formatter\ScalarFormatter; +use Monolog\Logger; + +/** + * Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/) + * + * @link https://github.com/aws/aws-sdk-php/ + * @author Andrew Lawson <adlawson@gmail.com> + */ +class DynamoDbHandler extends AbstractProcessingHandler +{ + const DATE_FORMAT = 'Y-m-d\TH:i:s.uO'; + + /** + * @var DynamoDbClient + */ + protected $client; + + /** + * @var string + */ + protected $table; + + /** + * @param DynamoDbClient $client + * @param string $table + * @param integer $level + * @param boolean $bubble + */ + public function __construct(DynamoDbClient $client, $table, $level = Logger::DEBUG, $bubble = true) + { + if (!defined('Aws\Common\Aws::VERSION') || version_compare('3.0', Aws::VERSION, '<=')) { + throw new \RuntimeException('The DynamoDbHandler is only known to work with the AWS SDK 2.x releases'); + } + + $this->client = $client; + $this->table = $table; + + parent::__construct($level, $bubble); + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + $filtered = $this->filterEmptyFields($record['formatted']); + $formatted = $this->client->formatAttributes($filtered); + + $this->client->putItem(array( + 'TableName' => $this->table, + 'Item' => $formatted + )); + } + + /** + * @param array $record + * @return array + */ + protected function filterEmptyFields(array $record) + { + return array_filter($record, function ($value) { + return !empty($value) || false === $value || 0 === $value; + }); + } + + /** + * {@inheritdoc} + */ + protected function getDefaultFormatter() + { + return new ScalarFormatter(self::DATE_FORMAT); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php @@ -0,0 +1,128 @@ +<?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 Monolog\Formatter\FormatterInterface; +use Monolog\Formatter\ElasticaFormatter; +use Monolog\Logger; +use Elastica\Client; +use Elastica\Exception\ExceptionInterface; + +/** + * Elastic Search handler + * + * Usage example: + * + * $client = new \Elastica\Client(); + * $options = array( + * 'index' => 'elastic_index_name', + * 'type' => 'elastic_doc_type', + * ); + * $handler = new ElasticSearchHandler($client, $options); + * $log = new Logger('application'); + * $log->pushHandler($handler); + * + * @author Jelle Vink <jelle.vink@gmail.com> + */ +class ElasticSearchHandler extends AbstractProcessingHandler +{ + /** + * @var Client + */ + protected $client; + + /** + * @var array Handler config options + */ + protected $options = array(); + + /** + * @param Client $client Elastica Client object + * @param array $options Handler configuration + * @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(Client $client, array $options = array(), $level = Logger::DEBUG, $bubble = true) + { + parent::__construct($level, $bubble); + $this->client = $client; + $this->options = array_merge( + array( + 'index' => 'monolog', // Elastic index name + 'type' => 'record', // Elastic document type + 'ignore_error' => false, // Suppress Elastica exceptions + ), + $options + ); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record) + { + $this->bulkSend(array($record['formatted'])); + } + + /** + * {@inheritdoc} + */ + public function setFormatter(FormatterInterface $formatter) + { + if ($formatter instanceof ElasticaFormatter) { + return parent::setFormatter($formatter); + } + throw new \InvalidArgumentException('ElasticSearchHandler is only compatible with ElasticaFormatter'); + } + + /** + * Getter options + * @return array + */ + public function getOptions() + { + return $this->options; + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new ElasticaFormatter($this->options['index'], $this->options['type']); + } + + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + $documents = $this->getFormatter()->formatBatch($records); + $this->bulkSend($documents); + } + + /** + * Use Elasticsearch bulk API to send list of documents + * @param array $documents + * @throws \RuntimeException + */ + protected function bulkSend(array $documents) + { + try { + $this->client->addDocuments($documents); + } catch (ExceptionInterface $e) { + if (!$this->options['ignore_error']) { + throw new \RuntimeException("Error sending messages to Elasticsearch", 0, $e); + } + } + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php @@ -0,0 +1,82 @@ +<?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 Monolog\Formatter\LineFormatter; +use Monolog\Logger; + +/** + * Stores to PHP error_log() handler. + * + * @author Elan Ruusamäe <glen@delfi.ee> + */ +class ErrorLogHandler extends AbstractProcessingHandler +{ + const OPERATING_SYSTEM = 0; + const SAPI = 4; + + protected $messageType; + protected $expandNewlines; + + /** + * @param integer $messageType Says where the error should go. + * @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 Boolean $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries + */ + public function __construct($messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, $bubble = true, $expandNewlines = false) + { + parent::__construct($level, $bubble); + + if (false === in_array($messageType, self::getAvailableTypes())) { + $message = sprintf('The given message type "%s" is not supported', print_r($messageType, true)); + throw new \InvalidArgumentException($message); + } + + $this->messageType = $messageType; + $this->expandNewlines = $expandNewlines; + } + + /** + * @return array With all available types + */ + public static function getAvailableTypes() + { + return array( + self::OPERATING_SYSTEM, + self::SAPI, + ); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new LineFormatter('[%datetime%] %channel%.%level_name%: %message% %context% %extra%'); + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + if ($this->expandNewlines) { + $lines = preg_split('{[\r\n]+}', (string) $record['formatted']); + foreach ($lines as $line) { + error_log($line, $this->messageType); + } + } else { + error_log((string) $record['formatted'], $this->messageType); + } + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php @@ -0,0 +1,140 @@ +<?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 Monolog\Logger; + +/** + * Simple handler wrapper that filters records based on a list of levels + * + * It can be configured with an exact list of levels to allow, or a min/max level. + * + * @author Hennadiy Verkh + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class FilterHandler extends AbstractHandler +{ + /** + * Handler or factory callable($record, $this) + * + * @var callable|\Monolog\Handler\HandlerInterface + */ + protected $handler; + + /** + * Minimum level for logs that are passes to handler + * + * @var int[] + */ + protected $acceptedLevels; + + /** + * Whether the messages that are handled can bubble up the stack or not + * + * @var Boolean + */ + protected $bubble; + + /** + * @param callable|HandlerInterface $handler Handler or factory callable($record, $this). + * @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided + * @param int $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct($handler, $minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY, $bubble = true) + { + $this->handler = $handler; + $this->bubble = $bubble; + $this->setAcceptedLevels($minLevelOrList, $maxLevel); + + 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"); + } + } + + /** + * @return array + */ + public function getAcceptedLevels() + { + return array_flip($this->acceptedLevels); + } + + /** + * @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided + * @param int $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array + */ + public function setAcceptedLevels($minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY) + { + if (is_array($minLevelOrList)) { + $acceptedLevels = array_map('Monolog\Logger::toMonologLevel', $minLevelOrList); + } else { + $minLevelOrList = Logger::toMonologLevel($minLevelOrList); + $maxLevel = Logger::toMonologLevel($maxLevel); + $acceptedLevels = array_values(array_filter(Logger::getLevels(), function ($level) use ($minLevelOrList, $maxLevel) { + return $level >= $minLevelOrList && $level <= $maxLevel; + })); + } + $this->acceptedLevels = array_flip($acceptedLevels); + } + + /** + * {@inheritdoc} + */ + public function isHandling(array $record) + { + return isset($this->acceptedLevels[$record['level']]); + } + + /** + * {@inheritdoc} + */ + public function handle(array $record) + { + if (!$this->isHandling($record)) { + return false; + } + + // The same logic as in FingersCrossedHandler + if (!$this->handler instanceof HandlerInterface) { + $this->handler = call_user_func($this->handler, $record, $this); + if (!$this->handler instanceof HandlerInterface) { + throw new \RuntimeException("The factory callable should return a HandlerInterface"); + } + } + + if ($this->processors) { + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + } + + $this->handler->handle($record); + + return false === $this->bubble; + } + + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + $filtered = array(); + foreach ($records as $record) { + if ($this->isHandling($record)) { + $filtered[] = $record; + } + } + + $this->handler->handleBatch($filtered); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php @@ -0,0 +1,28 @@ +<?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\FingersCrossed; + +/** + * Interface for activation strategies for the FingersCrossedHandler. + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +interface ActivationStrategyInterface +{ + /** + * Returns whether the given record activates the handler. + * + * @param array $record + * @return Boolean + */ + public function isHandlerActivated(array $record); +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php @@ -0,0 +1,59 @@ +<?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\FingersCrossed; + +use Monolog\Logger; + +/** + * Channel and Error level based monolog activation strategy. Allows to trigger activation + * based on level per channel. e.g. trigger activation on level 'ERROR' by default, except + * for records of the 'sql' channel; those should trigger activation on level 'WARN'. + * + * Example: + * + * <code> + * $activationStrategy = new ChannelLevelActivationStrategy( + * Logger::CRITICAL, + * array( + * 'request' => Logger::ALERT, + * 'sensitive' => Logger::ERROR, + * ) + * ); + * $handler = new FingersCrossedHandler(new StreamHandler('php://stderr'), $activationStrategy); + * </code> + * + * @author Mike Meessen <netmikey@gmail.com> + */ +class ChannelLevelActivationStrategy implements ActivationStrategyInterface +{ + private $defaultActionLevel; + private $channelToActionLevel; + + /** + * @param int $defaultActionLevel The default action level to be used if the record's category doesn't match any + * @param array $channelToActionLevel An array that maps channel names to action levels. + */ + public function __construct($defaultActionLevel, $channelToActionLevel = array()) + { + $this->defaultActionLevel = Logger::toMonologLevel($defaultActionLevel); + $this->channelToActionLevel = array_map('Monolog\Logger::toMonologLevel', $channelToActionLevel); + } + + public function isHandlerActivated(array $record) + { + if (isset($this->channelToActionLevel[$record['channel']])) { + return $record['level'] >= $this->channelToActionLevel[$record['channel']]; + } + + return $record['level'] >= $this->defaultActionLevel; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php @@ -0,0 +1,34 @@ +<?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\FingersCrossed; + +use Monolog\Logger; + +/** + * Error level based activation strategy. + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +class ErrorLevelActivationStrategy implements ActivationStrategyInterface +{ + private $actionLevel; + + public function __construct($actionLevel) + { + $this->actionLevel = Logger::toMonologLevel($actionLevel); + } + + public function isHandlerActivated(array $record) + { + return $record['level'] >= $this->actionLevel; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php @@ -0,0 +1,150 @@ +<?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 Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy; +use Monolog\Handler\FingersCrossed\ActivationStrategyInterface; +use Monolog\Logger; + +/** + * Buffers all records until a certain level is reached + * + * The advantage of this approach is that you don't get any clutter in your log files. + * Only requests which actually trigger an error (or whatever your actionLevel is) will be + * in the logs, but they will contain all records, not only those above the level threshold. + * + * You can find the various activation strategies in the + * Monolog\Handler\FingersCrossed\ namespace. + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class FingersCrossedHandler extends AbstractHandler +{ + protected $handler; + protected $activationStrategy; + protected $buffering = true; + protected $bufferSize; + protected $buffer = array(); + protected $stopBuffering; + protected $passthruLevel; + + /** + * @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler). + * @param int|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action + * @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param Boolean $stopBuffering Whether the handler should stop buffering after being triggered (default true) + * @param int $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered + */ + public function __construct($handler, $activationStrategy = null, $bufferSize = 0, $bubble = true, $stopBuffering = true, $passthruLevel = null) + { + if (null === $activationStrategy) { + $activationStrategy = new ErrorLevelActivationStrategy(Logger::WARNING); + } + + // convert simple int activationStrategy to an object + if (!$activationStrategy instanceof ActivationStrategyInterface) { + $activationStrategy = new ErrorLevelActivationStrategy($activationStrategy); + } + + $this->handler = $handler; + $this->activationStrategy = $activationStrategy; + $this->bufferSize = $bufferSize; + $this->bubble = $bubble; + $this->stopBuffering = $stopBuffering; + $this->passthruLevel = $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"); + } + } + + /** + * {@inheritdoc} + */ + public function isHandling(array $record) + { + return true; + } + + /** + * {@inheritdoc} + */ + public function handle(array $record) + { + if ($this->processors) { + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + } + + if ($this->buffering) { + $this->buffer[] = $record; + if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) { + array_shift($this->buffer); + } + if ($this->activationStrategy->isHandlerActivated($record)) { + if ($this->stopBuffering) { + $this->buffering = false; + } + if (!$this->handler instanceof HandlerInterface) { + $this->handler = call_user_func($this->handler, $record, $this); + if (!$this->handler instanceof HandlerInterface) { + throw new \RuntimeException("The factory callable should return a HandlerInterface"); + } + } + $this->handler->handleBatch($this->buffer); + $this->buffer = array(); + } + } else { + $this->handler->handle($record); + } + + return false === $this->bubble; + } + + /** + * {@inheritdoc} + */ + public function close() + { + if (null !== $this->passthruLevel) { + $level = $this->passthruLevel; + $this->buffer = array_filter($this->buffer, function ($record) use ($level) { + return $record['level'] >= $level; + }); + if (count($this->buffer) > 0) { + $this->handler->handleBatch($this->buffer); + $this->buffer = array(); + } + } + } + + /** + * Resets the state of the handler. Stops forwarding records to the wrapped handler. + */ + public function reset() + { + $this->buffering = true; + } + + /** + * Clears the buffer without flushing any messages down to the wrapped handler. + * + * It also resets the handler to its initial buffering state. + */ + public function clear() + { + $this->buffer = array(); + $this->reset(); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php @@ -0,0 +1,195 @@ +<?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 Monolog\Formatter\WildfireFormatter; + +/** + * Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol. + * + * @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com> + */ +class FirePHPHandler extends AbstractProcessingHandler +{ + /** + * WildFire JSON header message format + */ + const PROTOCOL_URI = 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2'; + + /** + * FirePHP structure for parsing messages & their presentation + */ + const STRUCTURE_URI = 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1'; + + /** + * Must reference a "known" plugin, otherwise headers won't display in FirePHP + */ + const PLUGIN_URI = 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3'; + + /** + * Header prefix for Wildfire to recognize & parse headers + */ + const HEADER_PREFIX = 'X-Wf'; + + /** + * Whether or not Wildfire vendor-specific headers have been generated & sent yet + */ + protected static $initialized = false; + + /** + * Shared static message index between potentially multiple handlers + * @var int + */ + protected static $messageIndex = 1; + + protected static $sendHeaders = true; + + /** + * Base header creation function used by init headers & record headers + * + * @param array $meta Wildfire Plugin, Protocol & Structure Indexes + * @param string $message Log message + * @return array Complete header string ready for the client as key and message as value + */ + protected function createHeader(array $meta, $message) + { + $header = sprintf('%s-%s', self::HEADER_PREFIX, join('-', $meta)); + + return array($header => $message); + } + + /** + * Creates message header from record + * + * @see createHeader() + * @param array $record + * @return string + */ + protected function createRecordHeader(array $record) + { + // Wildfire is extensible to support multiple protocols & plugins in a single request, + // but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake. + return $this->createHeader( + array(1, 1, 1, self::$messageIndex++), + $record['formatted'] + ); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new WildfireFormatter(); + } + + /** + * Wildfire initialization headers to enable message parsing + * + * @see createHeader() + * @see sendHeader() + * @return array + */ + protected function getInitHeaders() + { + // Initial payload consists of required headers for Wildfire + return array_merge( + $this->createHeader(array('Protocol', 1), self::PROTOCOL_URI), + $this->createHeader(array(1, 'Structure', 1), self::STRUCTURE_URI), + $this->createHeader(array(1, 'Plugin', 1), self::PLUGIN_URI) + ); + } + + /** + * Send header string to the client + * + * @param string $header + * @param string $content + */ + protected function sendHeader($header, $content) + { + if (!headers_sent() && self::$sendHeaders) { + header(sprintf('%s: %s', $header, $content)); + } + } + + /** + * Creates & sends header for a record, ensuring init headers have been sent prior + * + * @see sendHeader() + * @see sendInitHeaders() + * @param array $record + */ + protected function write(array $record) + { + if (!self::$sendHeaders) { + return; + } + + // WildFire-specific headers must be sent prior to any messages + if (!self::$initialized) { + self::$initialized = true; + + self::$sendHeaders = $this->headersAccepted(); + if (!self::$sendHeaders) { + return; + } + + foreach ($this->getInitHeaders() as $header => $content) { + $this->sendHeader($header, $content); + } + } + + $header = $this->createRecordHeader($record); + if (trim(current($header)) !== '') { + $this->sendHeader(key($header), current($header)); + } + } + + /** + * Verifies if the headers are accepted by the current user agent + * + * @return Boolean + */ + protected function headersAccepted() + { + if (!empty($_SERVER['HTTP_USER_AGENT']) && preg_match('{\bFirePHP/\d+\.\d+\b}', $_SERVER['HTTP_USER_AGENT'])) { + return true; + } + + return isset($_SERVER['HTTP_X_FIREPHP_VERSION']); + } + + /** + * BC getter for the sendHeaders property that has been made static + */ + public function __get($property) + { + if ('sendHeaders' !== $property) { + throw new \InvalidArgumentException('Undefined property '.$property); + } + + return static::$sendHeaders; + } + + /** + * BC setter for the sendHeaders property that has been made static + */ + public function __set($property, $value) + { + if ('sendHeaders' !== $property) { + throw new \InvalidArgumentException('Undefined property '.$property); + } + + static::$sendHeaders = $value; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php @@ -0,0 +1,126 @@ +<?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 Monolog\Formatter\LineFormatter; +use Monolog\Logger; + +/** + * Sends logs to Fleep.io using Webhook integrations + * + * You'll need a Fleep.io account to use this handler. + * + * @see https://fleep.io/integrations/webhooks/ Fleep Webhooks Documentation + * @author Ando Roots <ando@sqroot.eu> + */ +class FleepHookHandler extends SocketHandler +{ + const FLEEP_HOST = 'fleep.io'; + + const FLEEP_HOOK_URI = '/hook/'; + + /** + * @var string Webhook token (specifies the conversation where logs are sent) + */ + protected $token; + + /** + * Construct a new Fleep.io Handler. + * + * For instructions on how to create a new web hook in your conversations + * see https://fleep.io/integrations/webhooks/ + * + * @param string $token Webhook token + * @param bool|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 + * @throws MissingExtensionException + */ + public function __construct($token, $level = Logger::DEBUG, $bubble = true) + { + if (!extension_loaded('openssl')) { + throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FleepHookHandler'); + } + + $this->token = $token; + + $connectionString = 'ssl://' . self::FLEEP_HOST . ':443'; + parent::__construct($connectionString, $level, $bubble); + } + + /** + * Returns the default formatter to use with this handler + * + * Overloaded to remove empty context and extra arrays from the end of the log message. + * + * @return LineFormatter + */ + protected function getDefaultFormatter() + { + return new LineFormatter(null, null, true, true); + } + + /** + * Handles a log record + * + * @param array $record + */ + public function write(array $record) + { + parent::write($record); + $this->closeSocket(); + } + + /** + * {@inheritdoc} + * + * @param array $record + * @return string + */ + protected function generateDataStream($record) + { + $content = $this->buildContent($record); + + return $this->buildHeader($content) . $content; + } + + /** + * Builds the header of the API Call + * + * @param string $content + * @return string + */ + private function buildHeader($content) + { + $header = "POST " . self::FLEEP_HOOK_URI . $this->token . " HTTP/1.1\r\n"; + $header .= "Host: " . self::FLEEP_HOST . "\r\n"; + $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; + $header .= "Content-Length: " . strlen($content) . "\r\n"; + $header .= "\r\n"; + + return $header; + } + + /** + * Builds the body of API call + * + * @param array $record + * @return string + */ + private function buildContent($record) + { + $dataArray = array( + 'message' => $record['formatted'] + ); + + return http_build_query($dataArray); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php @@ -0,0 +1,103 @@ +<?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 Monolog\Logger; + +/** + * Sends notifications through the Flowdock push API + * + * This must be configured with a FlowdockFormatter instance via setFormatter() + * + * Notes: + * API token - Flowdock API token + * + * @author Dominik Liebler <liebler.dominik@gmail.com> + * @see https://www.flowdock.com/api/push + */ +class FlowdockHandler extends SocketHandler +{ + /** + * @var string + */ + protected $apiToken; + + /** + * @param string $apiToken + * @param bool|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 + * + * @throws MissingExtensionException if OpenSSL is missing + */ + public function __construct($apiToken, $level = Logger::DEBUG, $bubble = true) + { + if (!extension_loaded('openssl')) { + throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FlowdockHandler'); + } + + parent::__construct('ssl://api.flowdock.com:443', $level, $bubble); + $this->apiToken = $apiToken; + } + + /** + * {@inheritdoc} + * + * @param array $record + */ + protected function write(array $record) + { + parent::write($record); + + $this->closeSocket(); + } + + /** + * {@inheritdoc} + * + * @param array $record + * @return string + */ + protected function generateDataStream($record) + { + $content = $this->buildContent($record); + + return $this->buildHeader($content) . $content; + } + + /** + * Builds the body of API call + * + * @param array $record + * @return string + */ + private function buildContent($record) + { + return json_encode($record['formatted']['flowdock']); + } + + /** + * Builds the header of the API Call + * + * @param string $content + * @return string + */ + private function buildHeader($content) + { + $header = "POST /v1/messages/team_inbox/" . $this->apiToken . " HTTP/1.1\r\n"; + $header .= "Host: api.flowdock.com\r\n"; + $header .= "Content-Type: application/json\r\n"; + $header .= "Content-Length: " . strlen($content) . "\r\n"; + $header .= "\r\n"; + + return $header; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php @@ -0,0 +1,72 @@ +<?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\IMessagePublisher; +use Gelf\PublisherInterface; +use InvalidArgumentException; +use Monolog\Logger; +use Monolog\Formatter\GelfMessageFormatter; + +/** + * Handler to send messages to a Graylog2 (http://www.graylog2.org) server + * + * @author Matt Lehner <mlehner@gmail.com> + * @author Benjamin Zikarsky <benjamin@zikarsky.de> + */ +class GelfHandler extends AbstractProcessingHandler +{ + /** + * @var Publisher the publisher object that sends the message to the server + */ + 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 + */ + 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"); + } + + $this->publisher = $publisher; + } + + /** + * {@inheritdoc} + */ + public function close() + { + $this->publisher = null; + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + $this->publisher->publish($record['formatted']); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new GelfMessageFormatter(); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php @@ -0,0 +1,80 @@ +<?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; + +/** + * Forwards records to multiple handlers + * + * @author Lenar Lõhmus <lenar@city.ee> + */ +class GroupHandler extends AbstractHandler +{ + protected $handlers; + + /** + * @param array $handlers Array of Handlers. + * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + */ + public function __construct(array $handlers, $bubble = true) + { + foreach ($handlers as $handler) { + if (!$handler instanceof HandlerInterface) { + throw new \InvalidArgumentException('The first argument of the GroupHandler must be an array of HandlerInterface instances.'); + } + } + + $this->handlers = $handlers; + $this->bubble = $bubble; + } + + /** + * {@inheritdoc} + */ + public function isHandling(array $record) + { + foreach ($this->handlers as $handler) { + if ($handler->isHandling($record)) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function handle(array $record) + { + if ($this->processors) { + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + } + + foreach ($this->handlers as $handler) { + $handler->handle($record); + } + + return false === $this->bubble; + } + + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + foreach ($this->handlers as $handler) { + $handler->handleBatch($records); + } + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php @@ -0,0 +1,90 @@ +<?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 Monolog\Formatter\FormatterInterface; + +/** + * Interface that all Monolog Handlers must implement + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +interface HandlerInterface +{ + /** + * Checks whether the given record will be handled by this handler. + * + * This is mostly done for performance reasons, to avoid calling processors for nothing. + * + * Handlers should still check the record levels within handle(), returning false in isHandling() + * is no guarantee that handle() will not be called, and isHandling() might not be called + * for a given record. + * + * @param array $record Partial log record containing only a level key + * + * @return Boolean + */ + public function isHandling(array $record); + + /** + * Handles a record. + * + * All records may be passed to this method, and the handler should discard + * those that it does not want to handle. + * + * The return value of this function controls the bubbling process of the handler stack. + * Unless the bubbling is interrupted (by returning true), the Logger class will keep on + * calling further handlers in the stack with a given log record. + * + * @param array $record The record to handle + * @return Boolean true means that this handler handled the record, and that bubbling is not permitted. + * false means the record was either not processed or that this handler allows bubbling. + */ + public function handle(array $record); + + /** + * Handles a set of records at once. + * + * @param array $records The records to handle (an array of record arrays) + */ + public function handleBatch(array $records); + + /** + * Adds a processor in the stack. + * + * @param callable $callback + * @return self + */ + public function pushProcessor($callback); + + /** + * Removes the processor on top of the stack and returns it. + * + * @return callable + */ + public function popProcessor(); + + /** + * Sets the formatter. + * + * @param FormatterInterface $formatter + * @return self + */ + public function setFormatter(FormatterInterface $formatter); + + /** + * Gets the formatter. + * + * @return FormatterInterface + */ + public function getFormatter(); +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php @@ -0,0 +1,300 @@ +<?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 Monolog\Logger; + +/** + * Sends notifications through the hipchat api to a hipchat room + * + * Notes: + * API token - HipChat API token + * 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 + * + * @author Rafael Dohms <rafael@doh.ms> + * @see https://www.hipchat.com/docs/api + */ +class HipChatHandler extends SocketHandler +{ + /** + * The maximum allowed length for the name used in the "from" field. + */ + const MAXIMUM_NAME_LENGTH = 15; + + /** + * The maximum allowed length for the message. + */ + const MAXIMUM_MESSAGE_LENGTH = 9500; + + /** + * @var string + */ + private $token; + + /** + * @var array + */ + private $room; + + /** + * @var string + */ + private $name; + + /** + * @var boolean + */ + private $notify; + + /** + * @var string + */ + 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. + */ + public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $format = 'text', $host = 'api.hipchat.com') + { + if (!$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.'); + } + + $connectionString = $useSSL ? 'ssl://'.$host.':443' : $host.':80'; + parent::__construct($connectionString, $level, $bubble); + + $this->token = $token; + $this->name = $name; + $this->notify = $notify; + $this->room = $room; + $this->format = $format; + } + + /** + * {@inheritdoc} + * + * @param array $record + * @return string + */ + protected function generateDataStream($record) + { + $content = $this->buildContent($record); + + return $this->buildHeader($content) . $content; + } + + /** + * Builds the body of API call + * + * @param array $record + * @return string + */ + private function buildContent($record) + { + $dataArray = array( + 'from' => $this->name, + 'room_id' => $this->room, + 'notify' => $this->notify, + 'message' => $record['formatted'], + 'message_format' => $this->format, + 'color' => $this->getAlertColor($record['level']), + ); + + return http_build_query($dataArray); + } + + /** + * Builds the header of the API Call + * + * @param string $content + * @return string + */ + 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"; + $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; + $header .= "Content-Length: " . strlen($content) . "\r\n"; + $header .= "\r\n"; + + return $header; + } + + /** + * Assigns a color to each level of log records. + * + * @param integer $level + * @return string + */ + protected function getAlertColor($level) + { + switch (true) { + case $level >= Logger::ERROR: + return 'red'; + case $level >= Logger::WARNING: + return 'yellow'; + case $level >= Logger::INFO: + return 'green'; + case $level == Logger::DEBUG: + return 'gray'; + default: + return 'yellow'; + } + } + + /** + * {@inheritdoc} + * + * @param array $record + */ + protected function write(array $record) + { + parent::write($record); + $this->closeSocket(); + } + + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + if (count($records) == 0) { + return true; + } + + $batchRecords = $this->combineRecords($records); + + $handled = false; + foreach ($batchRecords as $batchRecord) { + if ($this->isHandling($batchRecord)) { + $this->write($batchRecord); + $handled = true; + } + } + + if (!$handled) { + return false; + } + + return false === $this->bubble; + } + + /** + * Combines multiple records into one. Error level of the combined record + * will be the highest level from the given records. Datetime will be taken + * from the first record. + * + * @param $records + * @return array + */ + private function combineRecords($records) + { + $batchRecord = null; + $batchRecords = array(); + $messages = array(); + $formattedMessages = array(); + $level = 0; + $levelName = null; + $datetime = null; + + foreach ($records as $record) { + $record = $this->processRecord($record); + + if ($record['level'] > $level) { + $level = $record['level']; + $levelName = $record['level_name']; + } + + if (null === $datetime) { + $datetime = $record['datetime']; + } + + $messages[] = $record['message']; + $messgeStr = implode(PHP_EOL, $messages); + $formattedMessages[] = $this->getFormatter()->format($record); + $formattedMessageStr = implode('', $formattedMessages); + + $batchRecord = array( + 'message' => $messgeStr, + 'formatted' => $formattedMessageStr, + 'context' => array(), + 'extra' => array(), + ); + + if (!$this->validateStringLength($batchRecord['formatted'], static::MAXIMUM_MESSAGE_LENGTH)) { + // Pop the last message and implode the remainging messages + $lastMessage = array_pop($messages); + $lastFormattedMessage = array_pop($formattedMessages); + $batchRecord['message'] = implode(PHP_EOL, $messages); + $batchRecord['formatted'] = implode('', $formattedMessages); + + $batchRecords[] = $batchRecord; + $messages = array($lastMessage); + $formattedMessages = array($lastFormattedMessage); + + $batchRecord = null; + } + } + + if (null !== $batchRecord) { + $batchRecords[] = $batchRecord; + } + + // Set the max level and datetime for all records + foreach ($batchRecords as &$batchRecord) { + $batchRecord = array_merge( + $batchRecord, + array( + 'level' => $level, + 'level_name' => $levelName, + 'datetime' => $datetime + ) + ); + } + + return $batchRecords; + } + + /** + * Validates the length of a string. + * + * If the `mb_strlen()` function is available, it will use that, as HipChat + * allows UTF-8 characters. Otherwise, it will fall back to `strlen()`. + * + * Note that this might cause false failures in the specific case of using + * a valid name with less than 16 characters, but 16 or more bytes, on a + * system where `mb_strlen()` is unavailable. + * + * @param string $str + * @param int $length + * + * @return bool + */ + private function validateStringLength($str, $length) + { + if (function_exists('mb_strlen')) { + return (mb_strlen($str) <= $length); + } + + return (strlen($str) <= $length); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php @@ -0,0 +1,55 @@ +<?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 Monolog\Logger; + +/** + * @author Robert Kaufmann III <rok3@rok3.me> + */ +class LogEntriesHandler extends SocketHandler +{ + /** + * @var string + */ + protected $logToken; + + /** + * @param string $token Log token supplied by LogEntries + * @param boolean $useSSL Whether or not SSL encryption should be used. + * @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 + */ + public function __construct($token, $useSSL = true, $level = Logger::DEBUG, $bubble = true) + { + if ($useSSL && !extension_loaded('openssl')) { + 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'; + parent::__construct($endpoint, $level, $bubble); + $this->logToken = $token; + } + + /** + * {@inheritdoc} + * + * @param array $record + * @return string + */ + protected function generateDataStream($record) + { + return $this->logToken . ' ' . $record['formatted']; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php @@ -0,0 +1,98 @@ +<?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 Monolog\Logger; +use Monolog\Formatter\LogglyFormatter; + +/** + * Sends errors to Loggly. + * + * @author Przemek Sobstel <przemek@sobstel.org> + * @author Adam Pancutt <adam@pancutt.com> + */ +class LogglyHandler extends AbstractProcessingHandler +{ + const HOST = 'logs-01.loggly.com'; + const ENDPOINT_SINGLE = 'inputs'; + const ENDPOINT_BATCH = 'bulk'; + + protected $token; + + protected $tag; + + public function __construct($token, $level = Logger::DEBUG, $bubble = true) + { + if (!extension_loaded('curl')) { + throw new \LogicException('The curl extension is needed to use the LogglyHandler'); + } + + $this->token = $token; + + parent::__construct($level, $bubble); + } + + public function setTag($tag) + { + $this->tag = $tag; + } + + public function addTag($tag) + { + $this->tag = (strlen($this->tag) > 0) ? $this->tag .','. $tag : $tag; + } + + protected function write(array $record) + { + $this->send($record["formatted"], self::ENDPOINT_SINGLE); + } + + public function handleBatch(array $records) + { + $level = $this->level; + + $records = array_filter($records, function ($record) use ($level) { + return ($record['level'] >= $level); + }); + + if ($records) { + $this->send($this->getFormatter()->formatBatch($records), self::ENDPOINT_BATCH); + } + } + + protected function send($data, $endpoint) + { + $url = sprintf("https://%s/%s/%s/", self::HOST, $endpoint, $this->token); + + $headers = array('Content-Type: application/json'); + + if ($this->tag) { + $headers[] = "X-LOGGLY-TAG: {$this->tag}"; + } + + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + curl_exec($ch); + curl_close($ch); + } + + protected function getDefaultFormatter() + { + return new LogglyFormatter(); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php @@ -0,0 +1,55 @@ +<?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; + +/** + * Base class for all mail handlers + * + * @author Gyula Sallai + */ +abstract class MailHandler extends AbstractProcessingHandler +{ + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + $messages = array(); + + foreach ($records as $record) { + if ($record['level'] < $this->level) { + continue; + } + $messages[] = $this->processRecord($record); + } + + if (!empty($messages)) { + $this->send((string) $this->getFormatter()->formatBatch($messages), $messages); + } + } + + /** + * Send a mail with the given content + * + * @param string $content + * @param array $records the array of log records that formed this content + */ + abstract protected function send($content, array $records); + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + $this->send((string) $record['formatted'], array($record)); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php @@ -0,0 +1,69 @@ +<?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 Monolog\Logger; + +/** + * MandrillHandler uses cURL to send the emails to the Mandrill API + * + * @author Adam Nicholson <adamnicholson10@gmail.com> + */ +class MandrillHandler extends MailHandler +{ + protected $client; + protected $message; + + /** + * @param string $apiKey A valid Mandrill API key + * @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced + * @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($apiKey, $message, $level = Logger::ERROR, $bubble = true) + { + parent::__construct($level, $bubble); + + 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->apiKey = $apiKey; + } + + /** + * {@inheritdoc} + */ + protected function send($content, array $records) + { + $message = clone $this->message; + $message->setBody($content); + $message->setDate(time()); + + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, 'https://mandrillapp.com/api/1.0/messages/send-raw.json'); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array( + 'key' => $this->apiKey, + 'raw_message' => (string) $message, + 'async' => false, + ))); + + curl_exec($ch); + curl_close($ch); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php @@ -0,0 +1,21 @@ +<?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; + +/** + * Exception can be thrown if an extension for an handler is missing + * + * @author Christian Bergau <cbergau86@gmail.com> + */ +class MissingExtensionException extends \Exception +{ +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php @@ -0,0 +1,55 @@ +<?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 Monolog\Logger; +use Monolog\Formatter\NormalizerFormatter; + +/** + * Logs to a MongoDB database. + * + * usage example: + * + * $log = new Logger('application'); + * $mongodb = new MongoDBHandler(new \Mongo("mongodb://localhost:27017"), "logs", "prod"); + * $log->pushHandler($mongodb); + * + * @author Thomas Tourlourat <thomas@tourlourat.com> + */ +class MongoDBHandler extends AbstractProcessingHandler +{ + protected $mongoCollection; + + public function __construct($mongo, $database, $collection, $level = Logger::DEBUG, $bubble = true) + { + if (!($mongo instanceof \MongoClient || $mongo instanceof \Mongo)) { + throw new \InvalidArgumentException('MongoClient or Mongo instance required'); + } + + $this->mongoCollection = $mongo->selectCollection($database, $collection); + + parent::__construct($level, $bubble); + } + + protected function write(array $record) + { + $this->mongoCollection->save($record["formatted"]); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new NormalizerFormatter(); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php @@ -0,0 +1,155 @@ +<?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 Monolog\Logger; + +/** + * NativeMailerHandler uses the mail() function to send the emails + * + * @author Christophe Coevoet <stof@notk.org> + * @author Mark Garrett <mark@moderndeveloperllc.com> + */ +class NativeMailerHandler extends MailHandler +{ + /** + * The email addresses to which the message will be sent + * @var array + */ + protected $to; + + /** + * The subject of the email + * @var string + */ + protected $subject; + + /** + * Optional headers for the message + * @var array + */ + protected $headers = array(); + + /** + * The wordwrap length for the message + * @var integer + */ + protected $maxColumnWidth; + + /** + * The Content-type for the message + * @var string + */ + protected $contentType = 'text/plain'; + + /** + * The encoding for the message + * @var string + */ + protected $encoding = 'utf-8'; + + /** + * @param string|array $to The receiver of the mail + * @param string $subject The subject of the mail + * @param string $from The sender of the mail + * @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 int $maxColumnWidth The maximum column width that the message lines will have + */ + public function __construct($to, $subject, $from, $level = Logger::ERROR, $bubble = true, $maxColumnWidth = 70) + { + parent::__construct($level, $bubble); + $this->to = is_array($to) ? $to : array($to); + $this->subject = $subject; + $this->addHeader(sprintf('From: %s', $from)); + $this->maxColumnWidth = $maxColumnWidth; + } + + /** + * Add headers to the message + * + * @param string|array $headers Custom added headers + * @return null + */ + public function addHeader($headers) + { + foreach ((array) $headers as $header) { + if (strpos($header, "\n") !== false || strpos($header, "\r") !== false) { + throw new \InvalidArgumentException('Headers can not contain newline characters for security reasons'); + } + $this->headers[] = $header; + } + } + + /** + * {@inheritdoc} + */ + protected function send($content, array $records) + { + $content = wordwrap($content, $this->maxColumnWidth); + $headers = ltrim(implode("\r\n", $this->headers) . "\r\n", "\r\n"); + $headers .= 'Content-type: ' . $this->getContentType() . '; charset=' . $this->getEncoding() . "\r\n"; + if ($this->getContentType() == 'text/html' && false === strpos($headers, 'MIME-Version:')) { + $headers .= 'MIME-Version: 1.0' . "\r\n"; + } + foreach ($this->to as $to) { + mail($to, $this->subject, $content, $headers); + } + } + + /** + * @return string $contentType + */ + public function getContentType() + { + return $this->contentType; + } + + /** + * @return string $encoding + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * @param string $contentType The content type of the email - Defaults to text/plain. Use text/html for HTML + * messages. + * @return self + */ + public function setContentType($contentType) + { + if (strpos($contentType, "\n") !== false || strpos($contentType, "\r") !== false) { + throw new \InvalidArgumentException('The content type can not contain newline characters to prevent email header injection'); + } + + $this->contentType = $contentType; + + return $this; + } + + /** + * @param string $encoding + * @return self + */ + 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'); + } + + $this->encoding = $encoding; + + return $this; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php @@ -0,0 +1,174 @@ +<?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 Monolog\Logger; + +/** + * Class to record a log on a NewRelic application + * + * @see https://docs.newrelic.com/docs/agents/php-agent + */ +class NewRelicHandler extends AbstractProcessingHandler +{ + /** + * Name of the New Relic application that will receive logs from this handler. + * + * @var string + */ + protected $appName; + + /** + * Name of the current transaction + * + * @var string + */ + protected $transactionName; + + /** + * Some context and extra data is passed into the handler as arrays of values. Do we send them as is + * (useful if we are using the API), or explode them for display on the NewRelic RPM website? + * + * @var boolean + */ + protected $explodeArrays; + + /** + * {@inheritDoc} + * + * @param string $appName + * @param boolean $explodeArrays + * @param string $transactionName + */ + public function __construct( + $level = Logger::ERROR, + $bubble = true, + $appName = null, + $explodeArrays = false, + $transactionName = null + ) { + parent::__construct($level, $bubble); + + $this->appName = $appName; + $this->explodeArrays = $explodeArrays; + $this->transactionName = $transactionName; + } + + /** + * {@inheritDoc} + */ + protected function write(array $record) + { + if (!$this->isNewRelicEnabled()) { + throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler'); + } + + if ($appName = $this->getAppName($record['context'])) { + $this->setNewRelicAppName($appName); + } + + if ($transactionName = $this->getTransactionName($record['context'])) { + $this->setNewRelicTransactionName($transactionName); + unset($record['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']); + } else { + newrelic_notice_error($record['message']); + } + + foreach ($record['context'] as $key => $parameter) { + if (is_array($parameter) && $this->explodeArrays) { + foreach ($parameter as $paramKey => $paramValue) { + newrelic_add_custom_parameter('context_' . $key . '_' . $paramKey, $paramValue); + } + } else { + newrelic_add_custom_parameter('context_' . $key, $parameter); + } + } + + foreach ($record['extra'] as $key => $parameter) { + if (is_array($parameter) && $this->explodeArrays) { + foreach ($parameter as $paramKey => $paramValue) { + newrelic_add_custom_parameter('extra_' . $key . '_' . $paramKey, $paramValue); + } + } else { + newrelic_add_custom_parameter('extra_' . $key, $parameter); + } + } + } + + /** + * Checks whether the NewRelic extension is enabled in the system. + * + * @return bool + */ + protected function isNewRelicEnabled() + { + return extension_loaded('newrelic'); + } + + /** + * Returns the appname where this log should be sent. Each log can override the default appname, set in this + * handler's constructor, by providing the appname in it's context. + * + * @param array $context + * @return null|string + */ + protected function getAppName(array $context) + { + if (isset($context['appname'])) { + return $context['appname']; + } + + return $this->appName; + } + + /** + * Returns the name of the current transaction. Each log can override the default transaction name, set in this + * handler's constructor, by providing the transaction_name in it's context + * + * @param array $context + * + * @return null|string + */ + protected function getTransactionName(array $context) + { + if (isset($context['transaction_name'])) { + return $context['transaction_name']; + } + + return $this->transactionName; + } + + /** + * Sets the NewRelic application that should receive this log. + * + * @param string $appName + */ + protected function setNewRelicAppName($appName) + { + newrelic_set_appname($appName); + } + + /** + * Overwrites the name of the current transaction + * + * @param $transactionName + */ + protected function setNewRelicTransactionName($transactionName) + { + newrelic_name_transaction($transactionName); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php @@ -0,0 +1,45 @@ +<?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 Monolog\Logger; + +/** + * Blackhole + * + * Any record it can handle will be thrown away. This can be used + * to put on top of an existing stack to override it temporarily. + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class NullHandler extends AbstractHandler +{ + /** + * @param integer $level The minimum logging level at which this handler will be triggered + */ + public function __construct($level = Logger::DEBUG) + { + parent::__construct($level, false); + } + + /** + * {@inheritdoc} + */ + public function handle(array $record) + { + if ($record['level'] < $this->level) { + return false; + } + + return true; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php @@ -0,0 +1,56 @@ +<?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 Monolog\Logger; +use Psr\Log\LoggerInterface; + +/** + * Proxies log messages to an existing PSR-3 compliant logger. + * + * @author Michael Moussa <michael.moussa@gmail.com> + */ +class PsrHandler extends AbstractHandler +{ + /** + * PSR-3 compliant logger + * + * @var LoggerInterface + */ + protected $logger; + + /** + * @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied + * @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 + */ + public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, $bubble = true) + { + parent::__construct($level, $bubble); + + $this->logger = $logger; + } + + /** + * {@inheritDoc} + */ + public function handle(array $record) + { + if (!$this->isHandling($record)) { + return false; + } + + $this->logger->log(strtolower($record['level_name']), $record['message'], $record['context']); + + return false === $this->bubble; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php @@ -0,0 +1,172 @@ +<?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 Monolog\Logger; + +/** + * Sends notifications through the pushover api to mobile phones + * + * @author Sebastian Göttschkes <sebastian.goettschkes@googlemail.com> + * @see https://www.pushover.net/api + */ +class PushoverHandler extends SocketHandler +{ + private $token; + private $users; + private $title; + private $user; + private $retry; + private $expire; + + private $highPriorityLevel; + private $emergencyLevel; + + /** + * All parameters that can be sent to Pushover + * @see https://pushover.net/api + * @var array + */ + private $parameterNames = array( + 'token' => true, + 'user' => true, + 'message' => true, + 'device' => true, + 'title' => true, + 'url' => true, + 'url_title' => true, + 'priority' => true, + 'timestamp' => true, + 'sound' => true, + 'retry' => true, + 'expire' => true, + 'callback' => true, + ); + + /** + * Sounds the api supports by default + * @see https://pushover.net/api#sounds + * @var array + */ + private $sounds = array( + 'pushover', 'bike', 'bugle', 'cashregister', 'classical', 'cosmic', 'falling', 'gamelan', 'incoming', + 'intermission', 'magic', 'mechanical', 'pianobar', 'siren', 'spacealarm', 'tugboat', 'alien', 'climb', + 'persistent', 'echo', 'updown', 'none', + ); + + /** + * @param string $token Pushover api token + * @param string|array $users Pushover user id or array of ids the message will be sent to + * @param string $title Title sent to the Pushover API + * @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 Boolean $useSSL Whether to connect via SSL. Required when pushing messages to users that are not + * the pushover.net app owner. OpenSSL is required for this option. + * @param integer $highPriorityLevel The minimum logging level at which this handler will start + * sending "high priority" requests to the Pushover API + * @param integer $emergencyLevel The minimum logging level at which this handler will start + * sending "emergency" requests to the Pushover API + * @param integer $retry The retry parameter specifies how often (in seconds) the Pushover servers will send the same notification to the user. + * @param integer $expire The expire parameter specifies how many seconds your notification will continue to be retried for (every retry seconds). + */ + public function __construct($token, $users, $title = null, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $highPriorityLevel = Logger::CRITICAL, $emergencyLevel = Logger::EMERGENCY, $retry = 30, $expire = 25200) + { + $connectionString = $useSSL ? 'ssl://api.pushover.net:443' : 'api.pushover.net:80'; + parent::__construct($connectionString, $level, $bubble); + + $this->token = $token; + $this->users = (array) $users; + $this->title = $title ?: gethostname(); + $this->highPriorityLevel = Logger::toMonologLevel($highPriorityLevel); + $this->emergencyLevel = Logger::toMonologLevel($emergencyLevel); + $this->retry = $retry; + $this->expire = $expire; + } + + protected function generateDataStream($record) + { + $content = $this->buildContent($record); + + return $this->buildHeader($content) . $content; + } + + private function buildContent($record) + { + // Pushover has a limit of 512 characters on title and message combined. + $maxMessageLength = 512 - strlen($this->title); + $message = substr($record['message'], 0, $maxMessageLength); + $timestamp = $record['datetime']->getTimestamp(); + + $dataArray = array( + 'token' => $this->token, + 'user' => $this->user, + 'message' => $message, + 'title' => $this->title, + 'timestamp' => $timestamp + ); + + if (isset($record['level']) && $record['level'] >= $this->emergencyLevel) { + $dataArray['priority'] = 2; + $dataArray['retry'] = $this->retry; + $dataArray['expire'] = $this->expire; + } elseif (isset($record['level']) && $record['level'] >= $this->highPriorityLevel) { + $dataArray['priority'] = 1; + } + + // First determine the available parameters + $context = array_intersect_key($record['context'], $this->parameterNames); + $extra = array_intersect_key($record['extra'], $this->parameterNames); + + // Least important info should be merged with subsequent info + $dataArray = array_merge($extra, $context, $dataArray); + + // Only pass sounds that are supported by the API + if (isset($dataArray['sound']) && !in_array($dataArray['sound'], $this->sounds)) { + unset($dataArray['sound']); + } + + return http_build_query($dataArray); + } + + private function buildHeader($content) + { + $header = "POST /1/messages.json HTTP/1.1\r\n"; + $header .= "Host: api.pushover.net\r\n"; + $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; + $header .= "Content-Length: " . strlen($content) . "\r\n"; + $header .= "\r\n"; + + return $header; + } + + protected function write(array $record) + { + foreach ($this->users as $user) { + $this->user = $user; + + parent::write($record); + $this->closeSocket(); + } + + $this->user = null; + } + + public function setHighPriorityLevel($value) + { + $this->highPriorityLevel = $value; + } + + public function setEmergencyLevel($value) + { + $this->emergencyLevel = $value; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php @@ -0,0 +1,181 @@ +<?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 Monolog\Formatter\LineFormatter; +use Monolog\Formatter\FormatterInterface; +use Monolog\Logger; +use Raven_Client; + +/** + * Handler to send messages to a Sentry (https://github.com/getsentry/sentry) server + * using raven-php (https://github.com/getsentry/raven-php) + * + * @author Marc Abramowitz <marc@marc-abramowitz.com> + */ +class RavenHandler extends AbstractProcessingHandler +{ + /** + * Translates Monolog log levels to Raven log levels. + */ + private $logLevels = array( + Logger::DEBUG => Raven_Client::DEBUG, + Logger::INFO => Raven_Client::INFO, + Logger::NOTICE => Raven_Client::INFO, + Logger::WARNING => Raven_Client::WARNING, + Logger::ERROR => Raven_Client::ERROR, + Logger::CRITICAL => Raven_Client::FATAL, + Logger::ALERT => Raven_Client::FATAL, + Logger::EMERGENCY => Raven_Client::FATAL, + ); + + /** + * @var Raven_Client the client object that sends the message to the server + */ + protected $ravenClient; + + /** + * @var LineFormatter The formatter to use for the logs generated via handleBatch() + */ + protected $batchFormatter; + + /** + * @param Raven_Client $ravenClient + * @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(Raven_Client $ravenClient, $level = Logger::DEBUG, $bubble = true) + { + parent::__construct($level, $bubble); + + $this->ravenClient = $ravenClient; + } + + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + $level = $this->level; + + // filter records based on their level + $records = array_filter($records, function ($record) use ($level) { + return $record['level'] >= $level; + }); + + if (!$records) { + return; + } + + // the record with the highest severity is the "main" one + $record = array_reduce($records, function ($highest, $record) { + if ($record['level'] >= $highest['level']) { + return $record; + } + + return $highest; + }); + + // the other ones are added as a context item + $logs = array(); + foreach ($records as $r) { + $logs[] = $this->processRecord($r); + } + + if ($logs) { + $record['context']['logs'] = (string) $this->getBatchFormatter()->formatBatch($logs); + } + + $this->handle($record); + } + + /** + * Sets the formatter for the logs generated by handleBatch(). + * + * @param FormatterInterface $formatter + */ + public function setBatchFormatter(FormatterInterface $formatter) + { + $this->batchFormatter = $formatter; + } + + /** + * Gets the formatter for the logs generated by handleBatch(). + * + * @return FormatterInterface + */ + public function getBatchFormatter() + { + if (!$this->batchFormatter) { + $this->batchFormatter = $this->getDefaultBatchFormatter(); + } + + return $this->batchFormatter; + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + $options = array(); + $options['level'] = $this->logLevels[$record['level']]; + $options['tags'] = array(); + if (!empty($record['extra']['tags'])) { + $options['tags'] = array_merge($options['tags'], $record['extra']['tags']); + unset($record['extra']['tags']); + } + if (!empty($record['context']['tags'])) { + $options['tags'] = array_merge($options['tags'], $record['context']['tags']); + unset($record['context']['tags']); + } + if (!empty($record['context']['logger'])) { + $options['logger'] = $record['context']['logger']; + unset($record['context']['logger']); + } else { + $options['logger'] = $record['channel']; + } + if (!empty($record['context'])) { + $options['extra']['context'] = $record['context']; + } + if (!empty($record['extra'])) { + $options['extra']['extra'] = $record['extra']; + } + + if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) { + $options['extra']['message'] = $record['formatted']; + $this->ravenClient->captureException($record['context']['exception'], $options); + + return; + } + + $this->ravenClient->captureMessage($record['formatted'], array(), $options); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new LineFormatter('[%channel%] %message%'); + } + + /** + * Gets the default formatter for the logs generated by handleBatch(). + * + * @return FormatterInterface + */ + protected function getDefaultBatchFormatter() + { + return new LineFormatter(); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php @@ -0,0 +1,58 @@ +<?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 Monolog\Logger; +use Monolog\Formatter\LineFormatter; + +/** + * Logs to a Redis key using rpush + * + * usage example: + * + * $log = new Logger('application'); + * $redis = new RedisHandler(new Predis\Client("tcp://localhost:6379"), "logs", "prod"); + * $log->pushHandler($redis); + * + * @author Thomas Tourlourat <thomas@tourlourat.com> + */ +class RedisHandler extends AbstractProcessingHandler +{ + private $redisClient; + private $redisKey; + + # redis instance, key to use + public function __construct($redis, $key, $level = Logger::DEBUG, $bubble = true) + { + if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) { + throw new \InvalidArgumentException('Predis\Client or Redis instance required'); + } + + $this->redisClient = $redis; + $this->redisKey = $key; + + parent::__construct($level, $bubble); + } + + protected function write(array $record) + { + $this->redisClient->rpush($this->redisKey, $record["formatted"]); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new LineFormatter(); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php @@ -0,0 +1,73 @@ +<?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 RollbarNotifier; +use Exception; +use Monolog\Logger; + +/** + * Sends errors to Rollbar + * + * @author Paul Statezny <paulstatezny@gmail.com> + */ +class RollbarHandler extends AbstractProcessingHandler +{ + /** + * Rollbar notifier + * + * @var RollbarNotifier + */ + protected $rollbarNotifier; + + /** + * @param RollbarNotifier $rollbarNotifier RollbarNotifier object constructed with valid token + * @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(RollbarNotifier $rollbarNotifier, $level = Logger::ERROR, $bubble = true) + { + $this->rollbarNotifier = $rollbarNotifier; + + parent::__construct($level, $bubble); + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + if (isset($record['context']['exception']) && $record['context']['exception'] instanceof Exception) { + $this->rollbarNotifier->report_exception($record['context']['exception']); + } else { + $extraData = array( + 'level' => $record['level'], + 'channel' => $record['channel'], + 'datetime' => $record['datetime']->format('U'), + ); + + $this->rollbarNotifier->report_message( + $record['message'], + $record['level_name'], + array_merge($record['context'], $record['extra'], $extraData) + ); + } + } + + /** + * {@inheritdoc} + */ + public function close() + { + $this->rollbarNotifier->flush(); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php @@ -0,0 +1,153 @@ +<?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 Monolog\Logger; + +/** + * Stores logs to files that are rotated every day and a limited number of files are kept. + * + * This rotation is only intended to be used as a workaround. Using logrotate to + * handle the rotation is strongly encouraged when you can use it. + * + * @author Christophe Coevoet <stof@notk.org> + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class RotatingFileHandler extends StreamHandler +{ + protected $filename; + protected $maxFiles; + protected $mustRotate; + protected $nextRotation; + protected $filenameFormat; + protected $dateFormat; + + /** + * @param string $filename + * @param integer $maxFiles The maximal amount of files to keep (0 means unlimited) + * @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 int|null $filePermission Optional file permissions (default (0644) are only for owner read/write) + * @param Boolean $useLocking Try to lock log file before doing any writes + */ + public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false) + { + $this->filename = $filename; + $this->maxFiles = (int) $maxFiles; + $this->nextRotation = new \DateTime('tomorrow'); + $this->filenameFormat = '{filename}-{date}'; + $this->dateFormat = 'Y-m-d'; + + parent::__construct($this->getTimedFilename(), $level, $bubble, $filePermission, $useLocking); + } + + /** + * {@inheritdoc} + */ + public function close() + { + parent::close(); + + if (true === $this->mustRotate) { + $this->rotate(); + } + } + + public function setFilenameFormat($filenameFormat, $dateFormat) + { + $this->filenameFormat = $filenameFormat; + $this->dateFormat = $dateFormat; + $this->url = $this->getTimedFilename(); + $this->close(); + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + // on the first record written, if the log is new, we should rotate (once per day) + if (null === $this->mustRotate) { + $this->mustRotate = !file_exists($this->url); + } + + if ($this->nextRotation < $record['datetime']) { + $this->mustRotate = true; + $this->close(); + } + + parent::write($record); + } + + /** + * Rotates the files. + */ + protected function rotate() + { + // update filename + $this->url = $this->getTimedFilename(); + $this->nextRotation = new \DateTime('tomorrow'); + + // skip GC of old logs if files are unlimited + if (0 === $this->maxFiles) { + return; + } + + $logFiles = glob($this->getGlobPattern()); + if ($this->maxFiles >= count($logFiles)) { + // no files to remove + return; + } + + // Sorting the files by name to remove the older ones + usort($logFiles, function ($a, $b) { + return strcmp($b, $a); + }); + + foreach (array_slice($logFiles, $this->maxFiles) as $file) { + if (is_writable($file)) { + unlink($file); + } + } + } + + protected function getTimedFilename() + { + $fileInfo = pathinfo($this->filename); + $timedFilename = str_replace( + array('{filename}', '{date}'), + array($fileInfo['filename'], date($this->dateFormat)), + $fileInfo['dirname'] . '/' . $this->filenameFormat + ); + + if (!empty($fileInfo['extension'])) { + $timedFilename .= '.'.$fileInfo['extension']; + } + + return $timedFilename; + } + + protected function getGlobPattern() + { + $fileInfo = pathinfo($this->filename); + $glob = str_replace( + array('{filename}', '{date}'), + array($fileInfo['filename'], '*'), + $fileInfo['dirname'] . '/' . $this->filenameFormat + ); + if (!empty($fileInfo['extension'])) { + $glob .= '.'.$fileInfo['extension']; + } + + return $glob; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php @@ -0,0 +1,83 @@ +<?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; + + +/** + * Sampling handler + * + * A sampled event stream can be useful for logging high frequency events in + * a production environment where you only need an idea of what is happening + * and are not concerned with capturing every occurrence. Since the decision to + * handle or not handle a particular event is determined randomly, the + * resulting sampled log is not guaranteed to contain 1/N of the events that + * occurred in the application, but based on the Law of large numbers, it will + * tend to be close to this ratio with a large number of attempts. + * + * @author Bryan Davis <bd808@wikimedia.org> + * @author Kunal Mehta <legoktm@gmail.com> + */ +class SamplingHandler extends AbstractHandler +{ + /** + * @var callable|HandlerInterface $handler + */ + protected $handler; + + /** + * @var int $factor + */ + protected $factor; + + /** + * @param callable|HandlerInterface $handler Handler or factory callable($record, $fingersCrossedHandler). + * @param int $factor Sample factor + */ + public function __construct($handler, $factor) + { + parent::__construct(); + $this->handler = $handler; + $this->factor = $factor; + + 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"); + } + } + + public function isHandling(array $record) + { + return $this->handler->isHandling($record); + } + + public function handle(array $record) + { + if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) { + // The same logic as in FingersCrossedHandler + if (!$this->handler instanceof HandlerInterface) { + $this->handler = call_user_func($this->handler, $record, $this); + if (!$this->handler instanceof HandlerInterface) { + throw new \RuntimeException("The factory callable should return a HandlerInterface"); + } + } + + if ($this->processors) { + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + } + + $this->handler->handle($record); + } + + return false === $this->bubble; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php @@ -0,0 +1,234 @@ +<?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 Monolog\Logger; +use Monolog\Formatter\LineFormatter; + +/** + * Sends notifications through Slack API + * + * @author Greg Kedzierski <greg@gregkedzierski.com> + * @see https://api.slack.com/ + */ +class SlackHandler extends SocketHandler +{ + /** + * Slack API token + * @var string + */ + private $token; + + /** + * Slack channel (encoded ID or name) + * @var string + */ + private $channel; + + /** + * Name of a bot + * @var string + */ + private $username; + + /** + * Emoji icon name + * @var string + */ + private $iconEmoji; + + /** + * Whether the message should be added to Slack as attachment (plain text otherwise) + * @var bool + */ + private $useAttachment; + + /** + * Whether the the message that is added to Slack as attachment is in a short style (or not) + * @var bool + */ + private $useShortAttachment; + + /** + * Whether the attachment should include extra data (or not) + * @var bool + */ + private $includeExtra; + + /** + * @var LineFormatter + */ + 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 + */ + public function __construct($token, $channel, $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $level = Logger::CRITICAL, $bubble = true, $useShortAttachment = false, $includeExtra = false) + { + if (!extension_loaded('openssl')) { + throw new MissingExtensionException('The OpenSSL PHP extension is required to use the SlackHandler'); + } + + parent::__construct('ssl://slack.com:443', $level, $bubble); + + $this->token = $token; + $this->channel = $channel; + $this->username = $username; + $this->iconEmoji = trim($iconEmoji, ':'); + $this->useAttachment = $useAttachment; + $this->useShortAttachment = $useShortAttachment; + $this->includeExtra = $includeExtra; + if ($this->includeExtra) { + $this->lineFormatter = new LineFormatter; + } + } + + /** + * {@inheritdoc} + * + * @param array $record + * @return string + */ + protected function generateDataStream($record) + { + $content = $this->buildContent($record); + + return $this->buildHeader($content) . $content; + } + + /** + * Builds the body of API call + * + * @param array $record + * @return string + */ + private function buildContent($record) + { + $dataArray = array( + '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']) + ); + + if ($this->useShortAttachment) { + $attachment['fields'] = array( + array( + 'title' => $record['level_name'], + 'value' => $record['message'], + 'short' => false + ) + ); + } else { + $attachment['fields'] = array( + array( + 'title' => 'Message', + 'value' => $record['message'], + 'short' => false + ), + array( + 'title' => 'Level', + 'value' => $record['level_name'], + 'short' => true + ) + ); + } + + if ($this->includeExtra) { + $extra = ''; + foreach ($record['extra'] as $var => $val) { + $extra .= $var.': '.$this->lineFormatter->stringify($val)." | "; + } + + $extra = rtrim($extra, " |"); + + $attachment['fields'][] = array( + 'title' => "Extra", + 'value' => $extra, + 'short' => false + ); + } + + $dataArray['attachments'] = json_encode(array($attachment)); + } else { + $dataArray['text'] = $record['message']; + } + + if ($this->iconEmoji) { + $dataArray['icon_emoji'] = ":{$this->iconEmoji}:"; + } + + return http_build_query($dataArray); + } + + /** + * Builds the header of the API Call + * + * @param string $content + * @return string + */ + private function buildHeader($content) + { + $header = "POST /api/chat.postMessage HTTP/1.1\r\n"; + $header .= "Host: slack.com\r\n"; + $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; + $header .= "Content-Length: " . strlen($content) . "\r\n"; + $header .= "\r\n"; + + return $header; + } + + /** + * {@inheritdoc} + * + * @param array $record + */ + protected function write(array $record) + { + parent::write($record); + $this->closeSocket(); + } + + /** + * Returned a Slack message attachment color associated with + * provided level. + * + * @param int $level + * @return string + */ + protected function getAttachmentColor($level) + { + switch (true) { + case $level >= Logger::ERROR: + return 'danger'; + case $level >= Logger::WARNING: + return 'warning'; + case $level >= Logger::INFO: + return 'good'; + default: + return '#e3e4e6'; + } + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php @@ -0,0 +1,284 @@ +<?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 Monolog\Logger; + +/** + * Stores to any socket - uses fsockopen() or pfsockopen(). + * + * @author Pablo de Leon Belloc <pablolb@gmail.com> + * @see http://php.net/manual/en/function.fsockopen.php + */ +class SocketHandler extends AbstractProcessingHandler +{ + private $connectionString; + private $connectionTimeout; + private $resource; + private $timeout = 0; + private $persistent = false; + private $errno; + private $errstr; + + /** + * @param string $connectionString Socket connection string + * @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($connectionString, $level = Logger::DEBUG, $bubble = true) + { + parent::__construct($level, $bubble); + $this->connectionString = $connectionString; + $this->connectionTimeout = (float) ini_get('default_socket_timeout'); + } + + /** + * Connect (if necessary) and write to the socket + * + * @param array $record + * + * @throws \UnexpectedValueException + * @throws \RuntimeException + */ + protected function write(array $record) + { + $this->connectIfNotConnected(); + $data = $this->generateDataStream($record); + $this->writeToSocket($data); + } + + /** + * We will not close a PersistentSocket instance so it can be reused in other requests. + */ + public function close() + { + if (!$this->isPersistent()) { + $this->closeSocket(); + } + } + + /** + * Close socket, if open + */ + public function closeSocket() + { + if (is_resource($this->resource)) { + fclose($this->resource); + $this->resource = null; + } + } + + /** + * Set socket connection to nbe persistent. It only has effect before the connection is initiated. + * + * @param type $boolean + */ + public function setPersistent($boolean) + { + $this->persistent = (boolean) $boolean; + } + + /** + * Set connection timeout. Only has effect before we connect. + * + * @param float $seconds + * + * @see http://php.net/manual/en/function.fsockopen.php + */ + public function setConnectionTimeout($seconds) + { + $this->validateTimeout($seconds); + $this->connectionTimeout = (float) $seconds; + } + + /** + * Set write timeout. Only has effect before we connect. + * + * @param float $seconds + * + * @see http://php.net/manual/en/function.stream-set-timeout.php + */ + public function setTimeout($seconds) + { + $this->validateTimeout($seconds); + $this->timeout = (float) $seconds; + } + + /** + * Get current connection string + * + * @return string + */ + public function getConnectionString() + { + return $this->connectionString; + } + + /** + * Get persistent setting + * + * @return boolean + */ + public function isPersistent() + { + return $this->persistent; + } + + /** + * Get current connection timeout setting + * + * @return float + */ + public function getConnectionTimeout() + { + return $this->connectionTimeout; + } + + /** + * Get current in-transfer timeout + * + * @return float + */ + public function getTimeout() + { + return $this->timeout; + } + + /** + * Check to see if the socket is currently available. + * + * UDP might appear to be connected but might fail when writing. See http://php.net/fsockopen for details. + * + * @return boolean + */ + public function isConnected() + { + return is_resource($this->resource) + && !feof($this->resource); // on TCP - other party can close connection. + } + + /** + * Wrapper to allow mocking + */ + protected function pfsockopen() + { + return @pfsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout); + } + + /** + * Wrapper to allow mocking + */ + protected function fsockopen() + { + return @fsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout); + } + + /** + * Wrapper to allow mocking + * + * @see http://php.net/manual/en/function.stream-set-timeout.php + */ + protected function streamSetTimeout() + { + $seconds = floor($this->timeout); + $microseconds = round(($this->timeout - $seconds)*1e6); + + return stream_set_timeout($this->resource, $seconds, $microseconds); + } + + /** + * Wrapper to allow mocking + */ + protected function fwrite($data) + { + return @fwrite($this->resource, $data); + } + + /** + * Wrapper to allow mocking + */ + protected function streamGetMetadata() + { + return stream_get_meta_data($this->resource); + } + + private function validateTimeout($value) + { + $ok = filter_var($value, FILTER_VALIDATE_FLOAT); + if ($ok === false || $value < 0) { + throw new \InvalidArgumentException("Timeout must be 0 or a positive float (got $value)"); + } + } + + private function connectIfNotConnected() + { + if ($this->isConnected()) { + return; + } + $this->connect(); + } + + protected function generateDataStream($record) + { + return (string) $record['formatted']; + } + + private function connect() + { + $this->createSocketResource(); + $this->setSocketTimeout(); + } + + private function createSocketResource() + { + if ($this->isPersistent()) { + $resource = $this->pfsockopen(); + } else { + $resource = $this->fsockopen(); + } + if (!$resource) { + throw new \UnexpectedValueException("Failed connecting to $this->connectionString ($this->errno: $this->errstr)"); + } + $this->resource = $resource; + } + + private function setSocketTimeout() + { + if (!$this->streamSetTimeout()) { + throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()"); + } + } + + private function writeToSocket($data) + { + $length = strlen($data); + $sent = 0; + while ($this->isConnected() && $sent < $length) { + if (0 == $sent) { + $chunk = $this->fwrite($data); + } else { + $chunk = $this->fwrite(substr($data, $sent)); + } + if ($chunk === false) { + throw new \RuntimeException("Could not write to socket"); + } + $sent += $chunk; + $socketInfo = $this->streamGetMetadata(); + if ($socketInfo['timed_out']) { + throw new \RuntimeException("Write timed-out"); + } + } + if (!$this->isConnected() && $sent < $length) { + throw new \RuntimeException("End-of-file reached, probably we got disconnected (sent $sent of $length)"); + } + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php @@ -0,0 +1,104 @@ +<?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 Monolog\Logger; + +/** + * Stores to any stream resource + * + * Can be used to store into php://stderr, remote and local files, etc. + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class StreamHandler extends AbstractProcessingHandler +{ + protected $stream; + protected $url; + private $errorMessage; + protected $filePermission; + protected $useLocking; + + /** + * @param resource|string $stream + * @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 int|null $filePermission Optional file permissions (default (0644) are only for owner read/write) + * @param Boolean $useLocking Try to lock log file before doing any writes + * + * @throws \InvalidArgumentException If stream is not a resource or string + */ + public function __construct($stream, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false) + { + parent::__construct($level, $bubble); + if (is_resource($stream)) { + $this->stream = $stream; + } elseif (is_string($stream)) { + $this->url = $stream; + } else { + throw new \InvalidArgumentException('A stream must either be a resource or a string.'); + } + + $this->filePermission = $filePermission; + $this->useLocking = $useLocking; + } + + /** + * {@inheritdoc} + */ + public function close() + { + if (is_resource($this->stream)) { + fclose($this->stream); + } + $this->stream = null; + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + if (!is_resource($this->stream)) { + if (!$this->url) { + throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().'); + } + $this->errorMessage = null; + set_error_handler(array($this, 'customErrorHandler')); + $this->stream = fopen($this->url, 'a'); + if ($this->filePermission !== null) { + @chmod($this->url, $this->filePermission); + } + restore_error_handler(); + if (!is_resource($this->stream)) { + $this->stream = null; + throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: '.$this->errorMessage, $this->url)); + } + } + + if ($this->useLocking) { + // ignoring errors here, there's not much we can do about them + flock($this->stream, LOCK_EX); + } + + fwrite($this->stream, (string) $record['formatted']); + + if ($this->useLocking) { + flock($this->stream, LOCK_UN); + } + } + + private function customErrorHandler($code, $msg) + { + $this->errorMessage = preg_replace('{^fopen\(.*?\): }', '', $msg); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php @@ -0,0 +1,56 @@ +<?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 Monolog\Logger; + +/** + * SwiftMailerHandler uses Swift_Mailer to send the emails + * + * @author Gyula Sallai + */ +class SwiftMailerHandler extends MailHandler +{ + protected $mailer; + protected $message; + + /** + * @param \Swift_Mailer $mailer The mailer to use + * @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced + * @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(\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; + } + + /** + * {@inheritdoc} + */ + protected function send($content, array $records) + { + $message = clone $this->message; + $message->setBody($content); + $message->setDate(time()); + + $this->mailer->send($message); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php @@ -0,0 +1,67 @@ +<?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 Monolog\Logger; + +/** + * Logs to syslog service. + * + * usage example: + * + * $log = new Logger('application'); + * $syslog = new SyslogHandler('myfacility', 'local6'); + * $formatter = new LineFormatter("%channel%.%level_name%: %message% %extra%"); + * $syslog->setFormatter($formatter); + * $log->pushHandler($syslog); + * + * @author Sven Paulus <sven@karlsruhe.org> + */ +class SyslogHandler extends AbstractSyslogHandler +{ + protected $ident; + protected $logopts; + + /** + * @param string $ident + * @param mixed $facility + * @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 int $logopts Option flags for the openlog() call, defaults to LOG_PID + */ + public function __construct($ident, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $logopts = LOG_PID) + { + parent::__construct($facility, $level, $bubble); + + $this->ident = $ident; + $this->logopts = $logopts; + } + + /** + * {@inheritdoc} + */ + public function close() + { + closelog(); + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + if (!openlog($this->ident, $this->logopts, $this->facility)) { + throw new \LogicException('Can\'t open syslog for ident "'.$this->ident.'" and facility "'.$this->facility.'"'); + } + syslog($this->logLevels[$record['level']], (string) $record['formatted']); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php @@ -0,0 +1,46 @@ +<?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\SyslogUdp; + +class UdpSocket +{ + const DATAGRAM_MAX_LENGTH = 65023; + + public function __construct($ip, $port = 514) + { + $this->ip = $ip; + $this->port = $port; + $this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); + } + + public function write($line, $header = "") + { + $this->send($this->assembleMessage($line, $header)); + } + + public function close() + { + socket_close($this->socket); + } + + protected function send($chunk) + { + socket_sendto($this->socket, $chunk, strlen($chunk), $flags = 0, $this->ip, $this->port); + } + + protected function assembleMessage($line, $header) + { + $chunkSize = self::DATAGRAM_MAX_LENGTH - strlen($header); + + return $header . substr($line, 0, $chunkSize); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php @@ -0,0 +1,80 @@ +<?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 Monolog\Logger; +use Monolog\Handler\SyslogUdp\UdpSocket; + +/** + * A Handler for logging to a remote syslogd server. + * + * @author Jesper Skovgaard Nielsen <nulpunkt@gmail.com> + */ +class SyslogUdpHandler extends AbstractSyslogHandler +{ + /** + * @param string $host + * @param int $port + * @param mixed $facility + * @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($host, $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true) + { + parent::__construct($facility, $level, $bubble); + + $this->socket = new UdpSocket($host, $port ?: 514); + } + + protected function write(array $record) + { + $lines = $this->splitMessageIntoLines($record['formatted']); + + $header = $this->makeCommonSyslogHeader($this->logLevels[$record['level']]); + + foreach ($lines as $line) { + $this->socket->write($line, $header); + } + } + + public function close() + { + $this->socket->close(); + } + + private function splitMessageIntoLines($message) + { + if (is_array($message)) { + $message = implode("\n", $message); + } + + return preg_split('/$\R?^/m', $message); + } + + /** + * Make common syslog header (see rfc5424) + */ + protected function makeCommonSyslogHeader($severity) + { + $priority = $severity + $this->facility; + + return "<$priority>1 "; + } + + /** + * Inject your own socket, mainly used for testing + */ + public function setSocket($socket) + { + $this->socket = $socket; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php @@ -0,0 +1,140 @@ +<?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 Monolog\Logger; + +/** + * Used for testing purposes. + * + * It records all records and gives you access to them for verification. + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class TestHandler extends AbstractProcessingHandler +{ + protected $records = array(); + protected $recordsByLevel = array(); + + public function getRecords() + { + return $this->records; + } + + public function hasEmergency($record) + { + return $this->hasRecord($record, Logger::EMERGENCY); + } + + public function hasAlert($record) + { + return $this->hasRecord($record, Logger::ALERT); + } + + public function hasCritical($record) + { + return $this->hasRecord($record, Logger::CRITICAL); + } + + public function hasError($record) + { + return $this->hasRecord($record, Logger::ERROR); + } + + public function hasWarning($record) + { + return $this->hasRecord($record, Logger::WARNING); + } + + public function hasNotice($record) + { + return $this->hasRecord($record, Logger::NOTICE); + } + + public function hasInfo($record) + { + return $this->hasRecord($record, Logger::INFO); + } + + public function hasDebug($record) + { + return $this->hasRecord($record, Logger::DEBUG); + } + + public function hasEmergencyRecords() + { + return isset($this->recordsByLevel[Logger::EMERGENCY]); + } + + public function hasAlertRecords() + { + return isset($this->recordsByLevel[Logger::ALERT]); + } + + public function hasCriticalRecords() + { + return isset($this->recordsByLevel[Logger::CRITICAL]); + } + + public function hasErrorRecords() + { + return isset($this->recordsByLevel[Logger::ERROR]); + } + + public function hasWarningRecords() + { + return isset($this->recordsByLevel[Logger::WARNING]); + } + + public function hasNoticeRecords() + { + return isset($this->recordsByLevel[Logger::NOTICE]); + } + + public function hasInfoRecords() + { + return isset($this->recordsByLevel[Logger::INFO]); + } + + public function hasDebugRecords() + { + return isset($this->recordsByLevel[Logger::DEBUG]); + } + + protected function hasRecord($record, $level) + { + if (!isset($this->recordsByLevel[$level])) { + return false; + } + + if (is_array($record)) { + $record = $record['message']; + } + + foreach ($this->recordsByLevel[$level] as $rec) { + if ($rec['message'] === $record) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + $this->recordsByLevel[$record['level']][] = $record; + $this->records[] = $record; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php @@ -0,0 +1,57 @@ +<?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; + +/** + * Forwards records to multiple handlers suppressing failures of each handler + * and continuing through to give every handler a chance to succeed. + * + * @author Craig D'Amelio <craig@damelio.ca> + */ +class WhatFailureGroupHandler extends GroupHandler +{ + /** + * {@inheritdoc} + */ + public function handle(array $record) + { + if ($this->processors) { + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + } + + foreach ($this->handlers as $handler) { + try { + $handler->handle($record); + } catch (\Exception $e) { + // What failure? + } + } + + return false === $this->bubble; + } + + /** + * {@inheritdoc} + */ + public function handleBatch(array $records) + { + foreach ($this->handlers as $handler) { + try { + $handler->handleBatch($records); + } catch (\Exception $e) { + // What failure? + } + } + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php @@ -0,0 +1,95 @@ +<?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 Monolog\Formatter\NormalizerFormatter; +use Monolog\Logger; + +/** + * Handler sending logs to Zend Monitor + * + * @author Christian Bergau <cbergau86@gmail.com> + */ +class ZendMonitorHandler extends AbstractProcessingHandler +{ + /** + * Monolog level / ZendMonitor Custom Event priority map + * + * @var array + */ + protected $levelMap = array( + Logger::DEBUG => 1, + Logger::INFO => 2, + Logger::NOTICE => 3, + Logger::WARNING => 4, + Logger::ERROR => 5, + Logger::CRITICAL => 6, + Logger::ALERT => 7, + Logger::EMERGENCY => 0, + ); + + /** + * Construct + * + * @param int $level + * @param bool $bubble + * @throws MissingExtensionException + */ + public function __construct($level = Logger::DEBUG, $bubble = true) + { + if (!function_exists('zend_monitor_custom_event')) { + throw new MissingExtensionException('You must have Zend Server installed in order to use this handler'); + } + parent::__construct($level, $bubble); + } + + /** + * {@inheritdoc} + */ + protected function write(array $record) + { + $this->writeZendMonitorCustomEvent( + $this->levelMap[$record['level']], + $record['message'], + $record['formatted'] + ); + } + + /** + * Write a record to Zend Monitor + * + * @param int $level + * @param string $message + * @param array $formatted + */ + protected function writeZendMonitorCustomEvent($level, $message, $formatted) + { + zend_monitor_custom_event($level, $message, $formatted); + } + + /** + * {@inheritdoc} + */ + public function getDefaultFormatter() + { + return new NormalizerFormatter(); + } + + /** + * Get the level map + * + * @return array + */ + public function getLevelMap() + { + return $this->levelMap; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Logger.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Logger.php @@ -0,0 +1,615 @@ +<?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; + +use Monolog\Handler\HandlerInterface; +use Monolog\Handler\StreamHandler; +use Psr\Log\LoggerInterface; +use Psr\Log\InvalidArgumentException; + +/** + * Monolog log channel + * + * It contains a stack of Handlers and a stack of Processors, + * and uses them to store records that are added to it. + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class Logger implements LoggerInterface +{ + /** + * Detailed debug information + */ + const DEBUG = 100; + + /** + * Interesting events + * + * Examples: User logs in, SQL logs. + */ + const INFO = 200; + + /** + * Uncommon events + */ + const NOTICE = 250; + + /** + * Exceptional occurrences that are not errors + * + * Examples: Use of deprecated APIs, poor use of an API, + * undesirable things that are not necessarily wrong. + */ + const WARNING = 300; + + /** + * Runtime errors + */ + const ERROR = 400; + + /** + * Critical conditions + * + * Example: Application component unavailable, unexpected exception. + */ + const CRITICAL = 500; + + /** + * Action must be taken immediately + * + * Example: Entire website down, database unavailable, etc. + * This should trigger the SMS alerts and wake you up. + */ + const ALERT = 550; + + /** + * Urgent alert. + */ + const EMERGENCY = 600; + + /** + * Monolog API version + * + * This is only bumped when API breaks are done and should + * follow the major version of the library + * + * @var int + */ + const API = 1; + + /** + * Logging levels from syslog protocol defined in RFC 5424 + * + * @var array $levels Logging levels + */ + protected static $levels = array( + 100 => 'DEBUG', + 200 => 'INFO', + 250 => 'NOTICE', + 300 => 'WARNING', + 400 => 'ERROR', + 500 => 'CRITICAL', + 550 => 'ALERT', + 600 => 'EMERGENCY', + ); + + /** + * @var \DateTimeZone + */ + protected static $timezone; + + /** + * @var string + */ + protected $name; + + /** + * The handler stack + * + * @var HandlerInterface[] + */ + protected $handlers; + + /** + * Processors that will process all log records + * + * To process records of a single handler instead, add the processor on that specific handler + * + * @var callable[] + */ + protected $processors; + + /** + * @param string $name The logging channel + * @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc. + * @param callable[] $processors Optional array of processors + */ + public function __construct($name, array $handlers = array(), array $processors = array()) + { + $this->name = $name; + $this->handlers = $handlers; + $this->processors = $processors; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Pushes a handler on to the stack. + * + * @param HandlerInterface $handler + */ + public function pushHandler(HandlerInterface $handler) + { + array_unshift($this->handlers, $handler); + } + + /** + * Pops a handler from the stack + * + * @return HandlerInterface + */ + public function popHandler() + { + if (!$this->handlers) { + throw new \LogicException('You tried to pop from an empty handler stack.'); + } + + return array_shift($this->handlers); + } + + /** + * @return HandlerInterface[] + */ + public function getHandlers() + { + return $this->handlers; + } + + /** + * Adds a processor on to the stack. + * + * @param callable $callback + */ + public function pushProcessor($callback) + { + if (!is_callable($callback)) { + 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); + } + + /** + * Removes the processor on top of the stack and returns it. + * + * @return callable + */ + public function popProcessor() + { + if (!$this->processors) { + throw new \LogicException('You tried to pop from an empty processor stack.'); + } + + return array_shift($this->processors); + } + + /** + * @return callable[] + */ + public function getProcessors() + { + return $this->processors; + } + + /** + * Adds a log record. + * + * @param integer $level The logging level + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addRecord($level, $message, array $context = array()) + { + if (!$this->handlers) { + $this->pushHandler(new StreamHandler('php://stderr', static::DEBUG)); + } + + $levelName = static::getLevelName($level); + + // check if any handler will handle this message so we can return early and save cycles + $handlerKey = null; + foreach ($this->handlers as $key => $handler) { + if ($handler->isHandling(array('level' => $level))) { + $handlerKey = $key; + break; + } + } + + if (null === $handlerKey) { + return false; + } + + if (!static::$timezone) { + static::$timezone = new \DateTimeZone(date_default_timezone_get() ?: 'UTC'); + } + + $record = array( + 'message' => (string) $message, + 'context' => $context, + 'level' => $level, + 'level_name' => $levelName, + 'channel' => $this->name, + 'datetime' => \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true)), static::$timezone)->setTimezone(static::$timezone), + 'extra' => array(), + ); + + foreach ($this->processors as $processor) { + $record = call_user_func($processor, $record); + } + while (isset($this->handlers[$handlerKey]) && + false === $this->handlers[$handlerKey]->handle($record)) { + $handlerKey++; + } + + return true; + } + + /** + * Adds a log record at the DEBUG level. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addDebug($message, array $context = array()) + { + return $this->addRecord(static::DEBUG, $message, $context); + } + + /** + * Adds a log record at the INFO level. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addInfo($message, array $context = array()) + { + return $this->addRecord(static::INFO, $message, $context); + } + + /** + * Adds a log record at the NOTICE level. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addNotice($message, array $context = array()) + { + return $this->addRecord(static::NOTICE, $message, $context); + } + + /** + * Adds a log record at the WARNING level. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addWarning($message, array $context = array()) + { + return $this->addRecord(static::WARNING, $message, $context); + } + + /** + * Adds a log record at the ERROR level. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addError($message, array $context = array()) + { + return $this->addRecord(static::ERROR, $message, $context); + } + + /** + * Adds a log record at the CRITICAL level. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addCritical($message, array $context = array()) + { + return $this->addRecord(static::CRITICAL, $message, $context); + } + + /** + * Adds a log record at the ALERT level. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addAlert($message, array $context = array()) + { + return $this->addRecord(static::ALERT, $message, $context); + } + + /** + * Adds a log record at the EMERGENCY level. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function addEmergency($message, array $context = array()) + { + return $this->addRecord(static::EMERGENCY, $message, $context); + } + + /** + * Gets all supported logging levels. + * + * @return array Assoc array with human-readable level names => level codes. + */ + public static function getLevels() + { + return array_flip(static::$levels); + } + + /** + * Gets the name of the logging level. + * + * @param integer $level + * @return string + */ + public static function getLevelName($level) + { + if (!isset(static::$levels[$level])) { + throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels))); + } + + return static::$levels[$level]; + } + + /** + * Converts PSR-3 levels to Monolog ones if necessary + * + * @param string|int Level number (monolog) or name (PSR-3) + * @return int + */ + public static function toMonologLevel($level) + { + if (is_string($level) && defined(__CLASS__.'::'.strtoupper($level))) { + return constant(__CLASS__.'::'.strtoupper($level)); + } + + return $level; + } + + /** + * Checks whether the Logger has a handler that listens on the given level + * + * @param integer $level + * @return Boolean + */ + public function isHandling($level) + { + $record = array( + 'level' => $level, + ); + + foreach ($this->handlers as $handler) { + if ($handler->isHandling($record)) { + return true; + } + } + + return false; + } + + /** + * Adds a log record at an arbitrary level. + * + * This method allows for compatibility with common interfaces. + * + * @param mixed $level The log level + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function log($level, $message, array $context = array()) + { + if (is_string($level) && defined(__CLASS__.'::'.strtoupper($level))) { + $level = constant(__CLASS__.'::'.strtoupper($level)); + } + + return $this->addRecord($level, $message, $context); + } + + /** + * Adds a log record at the DEBUG level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function debug($message, array $context = array()) + { + return $this->addRecord(static::DEBUG, $message, $context); + } + + /** + * Adds a log record at the INFO level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function info($message, array $context = array()) + { + return $this->addRecord(static::INFO, $message, $context); + } + + /** + * Adds a log record at the NOTICE level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function notice($message, array $context = array()) + { + return $this->addRecord(static::NOTICE, $message, $context); + } + + /** + * Adds a log record at the WARNING level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function warn($message, array $context = array()) + { + return $this->addRecord(static::WARNING, $message, $context); + } + + /** + * Adds a log record at the WARNING level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function warning($message, array $context = array()) + { + return $this->addRecord(static::WARNING, $message, $context); + } + + /** + * Adds a log record at the ERROR level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function err($message, array $context = array()) + { + return $this->addRecord(static::ERROR, $message, $context); + } + + /** + * Adds a log record at the ERROR level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function error($message, array $context = array()) + { + return $this->addRecord(static::ERROR, $message, $context); + } + + /** + * Adds a log record at the CRITICAL level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function crit($message, array $context = array()) + { + return $this->addRecord(static::CRITICAL, $message, $context); + } + + /** + * Adds a log record at the CRITICAL level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function critical($message, array $context = array()) + { + return $this->addRecord(static::CRITICAL, $message, $context); + } + + /** + * Adds a log record at the ALERT level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function alert($message, array $context = array()) + { + return $this->addRecord(static::ALERT, $message, $context); + } + + /** + * Adds a log record at the EMERGENCY level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function emerg($message, array $context = array()) + { + return $this->addRecord(static::EMERGENCY, $message, $context); + } + + /** + * Adds a log record at the EMERGENCY level. + * + * This method allows for compatibility with common interfaces. + * + * @param string $message The log message + * @param array $context The log context + * @return Boolean Whether the record has been processed + */ + public function emergency($message, array $context = array()) + { + return $this->addRecord(static::EMERGENCY, $message, $context); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php @@ -0,0 +1,64 @@ +<?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\Processor; + +use Monolog\Logger; + +/** + * Injects Git branch and Git commit SHA in all records + * + * @author Nick Otter + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class GitProcessor +{ + private $level; + private static $cache; + + public function __construct($level = Logger::DEBUG) + { + $this->level = Logger::toMonologLevel($level); + } + + /** + * @param array $record + * @return array + */ + public function __invoke(array $record) + { + // return if the level is not high enough + if ($record['level'] < $this->level) { + return $record; + } + + $record['extra']['git'] = self::getGitInfo(); + + return $record; + } + + private static function getGitInfo() + { + if (self::$cache) { + return self::$cache; + } + + $branches = `git branch -v --no-abbrev`; + if (preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) { + return self::$cache = array( + 'branch' => $matches[1], + 'commit' => $matches[2], + ); + } + + return self::$cache = array(); + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php @@ -0,0 +1,82 @@ +<?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\Processor; + +use Monolog\Logger; + +/** + * Injects line/file:class/function where the log message came from + * + * Warning: This only works if the handler processes the logs directly. + * If you put the processor on a handler that is behind a FingersCrossedHandler + * for example, the processor will only be called once the trigger level is reached, + * and all the log records will have the same file/line/.. data from the call that + * triggered the FingersCrossedHandler. + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class IntrospectionProcessor +{ + private $level; + + private $skipClassesPartials; + + public function __construct($level = Logger::DEBUG, array $skipClassesPartials = array('Monolog\\')) + { + $this->level = Logger::toMonologLevel($level); + $this->skipClassesPartials = $skipClassesPartials; + } + + /** + * @param array $record + * @return array + */ + public function __invoke(array $record) + { + // return if the level is not high enough + if ($record['level'] < $this->level) { + return $record; + } + + $trace = debug_backtrace(); + + // skip first since it's always the current method + array_shift($trace); + // the call_user_func call is also skipped + array_shift($trace); + + $i = 0; + + while (isset($trace[$i]['class'])) { + foreach ($this->skipClassesPartials as $part) { + if (strpos($trace[$i]['class'], $part) !== false) { + $i++; + continue 2; + } + } + break; + } + + // we should have the call source now + $record['extra'] = array_merge( + $record['extra'], + array( + 'file' => isset($trace[$i-1]['file']) ? $trace[$i-1]['file'] : null, + 'line' => isset($trace[$i-1]['line']) ? $trace[$i-1]['line'] : null, + 'class' => isset($trace[$i]['class']) ? $trace[$i]['class'] : null, + 'function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : null, + ) + ); + + return $record; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php @@ -0,0 +1,40 @@ +<?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\Processor; + +/** + * Injects memory_get_peak_usage in all records + * + * @see Monolog\Processor\MemoryProcessor::__construct() for options + * @author Rob Jensen + */ +class MemoryPeakUsageProcessor extends MemoryProcessor +{ + /** + * @param array $record + * @return array + */ + public function __invoke(array $record) + { + $bytes = memory_get_peak_usage($this->realUsage); + $formatted = $this->formatBytes($bytes); + + $record['extra'] = array_merge( + $record['extra'], + array( + 'memory_peak_usage' => $formatted, + ) + ); + + return $record; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.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\Processor; + +/** + * Some methods that are common for all memory processors + * + * @author Rob Jensen + */ +abstract class MemoryProcessor +{ + /** + * @var boolean If true, get the real size of memory allocated from system. Else, only the memory used by emalloc() is reported. + */ + protected $realUsage; + + /** + * @var boolean If true, then format memory size to human readable string (MB, KB, B depending on size) + */ + protected $useFormatting; + + /** + * @param boolean $realUsage Set this to true to get the real size of memory allocated from system. + * @param boolean $useFormatting If true, then format memory size to human readable string (MB, KB, B depending on size) + */ + public function __construct($realUsage = true, $useFormatting = true) + { + $this->realUsage = (boolean) $realUsage; + $this->useFormatting = (boolean) $useFormatting; + } + + /** + * Formats bytes into a human readable string if $this->useFormatting is true, otherwise return $bytes as is + * + * @param int $bytes + * @return string|int Formatted string if $this->useFormatting is true, otherwise return $bytes as is + */ + protected function formatBytes($bytes) + { + $bytes = (int) $bytes; + + if (!$this->useFormatting) { + return $bytes; + } + + if ($bytes > 1024*1024) { + return round($bytes/1024/1024, 2).' MB'; + } elseif ($bytes > 1024) { + return round($bytes/1024, 2).' KB'; + } + + return $bytes . ' B'; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php @@ -0,0 +1,40 @@ +<?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\Processor; + +/** + * Injects memory_get_usage in all records + * + * @see Monolog\Processor\MemoryProcessor::__construct() for options + * @author Rob Jensen + */ +class MemoryUsageProcessor extends MemoryProcessor +{ + /** + * @param array $record + * @return array + */ + public function __invoke(array $record) + { + $bytes = memory_get_usage($this->realUsage); + $formatted = $this->formatBytes($bytes); + + $record['extra'] = array_merge( + $record['extra'], + array( + 'memory_usage' => $formatted, + ) + ); + + return $record; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php @@ -0,0 +1,31 @@ +<?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\Processor; + +/** + * Adds value of getmypid into records + * + * @author Andreas Hörnicke + */ +class ProcessIdProcessor +{ + /** + * @param array $record + * @return array + */ + public function __invoke(array $record) + { + $record['extra']['process_id'] = getmypid(); + + return $record; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php @@ -0,0 +1,48 @@ +<?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\Processor; + +/** + * Processes a record's message according to PSR-3 rules + * + * It replaces {foo} with the value from $context['foo'] + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class PsrLogMessageProcessor +{ + /** + * @param array $record + * @return array + */ + public function __invoke(array $record) + { + if (false === strpos($record['message'], '{')) { + return $record; + } + + $replacements = array(); + foreach ($record['context'] as $key => $val) { + if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) { + $replacements['{'.$key.'}'] = $val; + } elseif (is_object($val)) { + $replacements['{'.$key.'}'] = '[object '.get_class($val).']'; + } else { + $replacements['{'.$key.'}'] = '['.gettype($val).']'; + } + } + + $record['message'] = strtr($record['message'], $replacements); + + return $record; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php @@ -0,0 +1,34 @@ +<?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\Processor; + +/** + * Adds a tags array into record + * + * @author Martijn Riemers + */ +class TagProcessor +{ + private $tags; + + public function __construct(array $tags = array()) + { + $this->tags = $tags; + } + + public function __invoke(array $record) + { + $record['extra']['tags'] = $this->tags; + + return $record; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php @@ -0,0 +1,38 @@ +<?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\Processor; + +/** + * Adds a unique identifier into records + * + * @author Simon Mönch <sm@webfactory.de> + */ +class UidProcessor +{ + private $uid; + + public function __construct($length = 7) + { + if (!is_int($length) || $length > 32 || $length < 1) { + throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32'); + } + + $this->uid = substr(hash('md5', uniqid('', true)), 0, $length); + } + + public function __invoke(array $record) + { + $record['extra']['uid'] = $this->uid; + + return $record; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php @@ -0,0 +1,105 @@ +<?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\Processor; + +/** + * Injects url/method and remote IP of the current web request in all records + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class WebProcessor +{ + /** + * @var array|\ArrayAccess + */ + protected $serverData; + + /** + * @var array + */ + protected $extraFields = array( + 'url' => 'REQUEST_URI', + 'ip' => 'REMOTE_ADDR', + 'http_method' => 'REQUEST_METHOD', + 'server' => 'SERVER_NAME', + 'referrer' => 'HTTP_REFERER', + ); + + /** + * @param array|\ArrayAccess $serverData Array or object w/ ArrayAccess that provides access to the $_SERVER data + * @param array|null $extraFields Extra field names to be added (all available by default) + */ + public function __construct($serverData = null, array $extraFields = null) + { + if (null === $serverData) { + $this->serverData = &$_SERVER; + } elseif (is_array($serverData) || $serverData instanceof \ArrayAccess) { + $this->serverData = $serverData; + } else { + throw new \UnexpectedValueException('$serverData must be an array or object implementing ArrayAccess.'); + } + + if (null !== $extraFields) { + foreach (array_keys($this->extraFields) as $fieldName) { + if (!in_array($fieldName, $extraFields)) { + unset($this->extraFields[$fieldName]); + } + } + } + } + + /** + * @param array $record + * @return array + */ + public function __invoke(array $record) + { + // skip processing if for some reason request data + // is not present (CLI or wonky SAPIs) + if (!isset($this->serverData['REQUEST_URI'])) { + return $record; + } + + $record['extra'] = $this->appendExtraFields($record['extra']); + + return $record; + } + + /** + * @param string $extraName + * @param string $serverName + * @return $this + */ + public function addExtraField($extraName, $serverName) + { + $this->extraFields[$extraName] = $serverName; + + return $this; + } + + /** + * @param array $extra + * @return array + */ + private function appendExtraFields(array $extra) + { + foreach ($this->extraFields as $extraName => $serverName) { + $extra[$extraName] = isset($this->serverData[$serverName]) ? $this->serverData[$serverName] : null; + } + + if (isset($this->serverData['UNIQUE_ID'])) { + $extra['unique_id'] = $this->serverData['UNIQUE_ID']; + } + + return $extra; + } +} diff --git a/core/update/update/vendor/monolog/monolog/src/Monolog/Registry.php b/core/update/update/vendor/monolog/monolog/src/Monolog/Registry.php @@ -0,0 +1,118 @@ +<?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; + +use InvalidArgumentException; + +/** + * Monolog log registry + * + * Allows to get `Logger` instances in the global scope + * via static method calls on this class. + * + * <code> + * $application = new Monolog\Logger('application'); + * $api = new Monolog\Logger('api'); + * + * Monolog\Registry::addLogger($application); + * Monolog\Registry::addLogger($api); + * + * function testLogger() + * { + * Monolog\Registry::api()->addError('Sent to $api Logger instance'); + * Monolog\Registry::application()->addError('Sent to $application Logger instance'); + * } + * </code> + * + * @author Tomas Tatarko <tomas@tatarko.sk> + */ +class Registry +{ + /** + * List of all loggers in the registry (ba named indexes) + * + * @var Logger[] + */ + private static $loggers = array(); + + /** + * Adds new logging channel to the registry + * + * @param Logger $logger Instance of the logging channel + * @param string|null $name Name of the logging channel ($logger->getName() by default) + * @param boolean $overwrite Overwrite instance in the registry if the given name already exists? + * @throws \InvalidArgumentException If $overwrite set to false and named Logger instance already exists + */ + public static function addLogger(Logger $logger, $name = null, $overwrite = false) + { + $name = $name ?: $logger->getName(); + + if (isset(self::$loggers[$name]) && !$overwrite) { + throw new InvalidArgumentException('Logger with the given name already exists'); + } + + self::$loggers[$name] = $logger; + } + + /** + * Removes instance from registry by name or instance + * + * @param string|Logger $logger Name or logger instance + */ + public static function removeLogger($logger) + { + if ($logger instanceof Logger) { + if (false !== ($idx = array_search($logger, self::$loggers, true))) { + unset(self::$loggers[$idx]); + } + } else { + unset(self::$loggers[$logger]); + } + } + + /** + * Clears the registry + */ + public static function clear() + { + self::$loggers = array(); + } + + /** + * Gets Logger instance from the registry + * + * @param string $name Name of the requested Logger instance + * @return Logger Requested instance of Logger + * @throws \InvalidArgumentException If named Logger instance is not in the registry + */ + public static function getInstance($name) + { + if (!isset(self::$loggers[$name])) { + throw new InvalidArgumentException(sprintf('Requested "%s" logger instance is not in the registry', $name)); + } + + return self::$loggers[$name]; + } + + /** + * Gets Logger instance from the registry via static method call + * + * @param string $name Name of the requested Logger instance + * @param array $arguments Arguments passed to static method call + * @return Logger Requested instance of Logger + * @throws \InvalidArgumentException If named Logger instance is not in the registry + */ + public static function __callStatic($name, $arguments) + { + return self::getInstance($name); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/ErrorHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/ErrorHandlerTest.php @@ -0,0 +1,31 @@ +<?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; + +use Monolog\Handler\TestHandler; + +class ErrorHandlerTest extends \PHPUnit_Framework_TestCase +{ + public function testHandleError() + { + $logger = new Logger('test', array($handler = new TestHandler)); + $errHandler = new ErrorHandler($logger); + + $errHandler->registerErrorHandler(array(E_USER_NOTICE => Logger::EMERGENCY), false); + trigger_error('Foo', E_USER_ERROR); + $this->assertCount(1, $handler->getRecords()); + $this->assertTrue($handler->hasErrorRecords()); + trigger_error('Foo', E_USER_NOTICE); + $this->assertCount(2, $handler->getRecords()); + $this->assertTrue($handler->hasEmergencyRecords()); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/ChromePHPFormatterTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/ChromePHPFormatterTest.php @@ -0,0 +1,158 @@ +<?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\Formatter; + +use Monolog\Logger; + +class ChromePHPFormatterTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Monolog\Formatter\ChromePHPFormatter::format + */ + public function testDefaultFormat() + { + $formatter = new ChromePHPFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('ip' => '127.0.0.1'), + 'message' => 'log', + ); + + $message = $formatter->format($record); + + $this->assertEquals( + array( + 'meh', + array( + 'message' => 'log', + 'context' => array('from' => 'logger'), + 'extra' => array('ip' => '127.0.0.1'), + ), + 'unknown', + 'error' + ), + $message + ); + } + + /** + * @covers Monolog\Formatter\ChromePHPFormatter::format + */ + public function testFormatWithFileAndLine() + { + $formatter = new ChromePHPFormatter(); + $record = array( + 'level' => Logger::CRITICAL, + 'level_name' => 'CRITICAL', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('ip' => '127.0.0.1', 'file' => 'test', 'line' => 14), + 'message' => 'log', + ); + + $message = $formatter->format($record); + + $this->assertEquals( + array( + 'meh', + array( + 'message' => 'log', + 'context' => array('from' => 'logger'), + 'extra' => array('ip' => '127.0.0.1'), + ), + 'test : 14', + 'error' + ), + $message + ); + } + + /** + * @covers Monolog\Formatter\ChromePHPFormatter::format + */ + public function testFormatWithoutContext() + { + $formatter = new ChromePHPFormatter(); + $record = array( + 'level' => Logger::DEBUG, + 'level_name' => 'DEBUG', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + $message = $formatter->format($record); + + $this->assertEquals( + array( + 'meh', + 'log', + 'unknown', + 'log' + ), + $message + ); + } + + /** + * @covers Monolog\Formatter\ChromePHPFormatter::formatBatch + */ + public function testBatchFormatThrowException() + { + $formatter = new ChromePHPFormatter(); + $records = array( + array( + 'level' => Logger::INFO, + 'level_name' => 'INFO', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ), + array( + 'level' => Logger::WARNING, + 'level_name' => 'WARNING', + 'channel' => 'foo', + 'context' => array(), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log2', + ), + ); + + $this->assertEquals( + array( + array( + 'meh', + 'log', + 'unknown', + 'info' + ), + array( + 'foo', + 'log2', + 'unknown', + 'warn' + ), + ), + $formatter->formatBatch($records) + ); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/ElasticaFormatterTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/ElasticaFormatterTest.php @@ -0,0 +1,79 @@ +<?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\Formatter; + +use Monolog\Logger; + +class ElasticaFormatterTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + if (!class_exists("Elastica\Document")) { + $this->markTestSkipped("ruflin/elastica not installed"); + } + } + + /** + * @covers Monolog\Formatter\ElasticaFormatter::__construct + * @covers Monolog\Formatter\ElasticaFormatter::format + * @covers Monolog\Formatter\ElasticaFormatter::getDocument + */ + public function testFormat() + { + // test log message + $msg = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('foo' => 7, 'bar', 'class' => new \stdClass), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + // expected values + $expected = $msg; + $expected['datetime'] = '1970-01-01T00:00:00+0000'; + $expected['context'] = array( + 'class' => '[object] (stdClass: {})', + 'foo' => 7, + 0 => 'bar', + ); + + // format log message + $formatter = new ElasticaFormatter('my_index', 'doc_type'); + $doc = $formatter->format($msg); + $this->assertInstanceOf('Elastica\Document', $doc); + + // Document parameters + $params = $doc->getParams(); + $this->assertEquals('my_index', $params['_index']); + $this->assertEquals('doc_type', $params['_type']); + + // Document data values + $data = $doc->getData(); + foreach (array_keys($expected) as $key) { + $this->assertEquals($expected[$key], $data[$key]); + } + } + + /** + * @covers Monolog\Formatter\ElasticaFormatter::getIndex + * @covers Monolog\Formatter\ElasticaFormatter::getType + */ + public function testGetters() + { + $formatter = new ElasticaFormatter('my_index', 'doc_type'); + $this->assertEquals('my_index', $formatter->getIndex()); + $this->assertEquals('doc_type', $formatter->getType()); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/FlowdockFormatterTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/FlowdockFormatterTest.php @@ -0,0 +1,55 @@ +<?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\Formatter; + +use Monolog\Logger; +use Monolog\TestCase; + +class FlowdockFormatterTest extends TestCase +{ + /** + * @covers Monolog\Formatter\FlowdockFormatter::format + */ + public function testFormat() + { + $formatter = new FlowdockFormatter('test_source', 'source@test.com'); + $record = $this->getRecord(); + + $expected = array( + 'source' => 'test_source', + 'from_address' => 'source@test.com', + 'subject' => 'in test_source: WARNING - test', + 'content' => 'test', + 'tags' => array('#logs', '#warning', '#test'), + 'project' => 'test_source', + ); + $formatted = $formatter->format($record); + + $this->assertEquals($expected, $formatted['flowdock']); + } + + /** + * @ covers Monolog\Formatter\FlowdockFormatter::formatBatch + */ + public function testFormatBatch() + { + $formatter = new FlowdockFormatter('test_source', 'source@test.com'); + $records = array( + $this->getRecord(Logger::WARNING), + $this->getRecord(Logger::DEBUG), + ); + $formatted = $formatter->formatBatch($records); + + $this->assertArrayHasKey('flowdock', $formatted[0]); + $this->assertArrayHasKey('flowdock', $formatted[1]); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/GelfMessageFormatterTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/GelfMessageFormatterTest.php @@ -0,0 +1,189 @@ +<?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\Formatter; + +use Monolog\Logger; + +class GelfMessageFormatterTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + if (!class_exists('\Gelf\Message')) { + $this->markTestSkipped("graylog2/gelf-php or mlehner/gelf-php is not installed"); + } + } + + /** + * @covers Monolog\Formatter\GelfMessageFormatter::format + */ + public function testDefaultFormatter() + { + $formatter = new GelfMessageFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + $message = $formatter->format($record); + + $this->assertInstanceOf('Gelf\Message', $message); + $this->assertEquals(0, $message->getTimestamp()); + $this->assertEquals('log', $message->getShortMessage()); + $this->assertEquals('meh', $message->getFacility()); + $this->assertEquals(null, $message->getLine()); + $this->assertEquals(null, $message->getFile()); + $this->assertEquals($this->isLegacy() ? 3 : 'error', $message->getLevel()); + $this->assertNotEmpty($message->getHost()); + + $formatter = new GelfMessageFormatter('mysystem'); + + $message = $formatter->format($record); + + $this->assertInstanceOf('Gelf\Message', $message); + $this->assertEquals('mysystem', $message->getHost()); + } + + /** + * @covers Monolog\Formatter\GelfMessageFormatter::format + */ + public function testFormatWithFileAndLine() + { + $formatter = new GelfMessageFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('file' => 'test', 'line' => 14), + 'message' => 'log', + ); + + $message = $formatter->format($record); + + $this->assertInstanceOf('Gelf\Message', $message); + $this->assertEquals('test', $message->getFile()); + $this->assertEquals(14, $message->getLine()); + } + + /** + * @covers Monolog\Formatter\GelfMessageFormatter::format + */ + public function testFormatWithContext() + { + $formatter = new GelfMessageFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => 'pair'), + 'message' => 'log' + ); + + $message = $formatter->format($record); + + $this->assertInstanceOf('Gelf\Message', $message); + + $message_array = $message->toArray(); + + $this->assertArrayHasKey('_ctxt_from', $message_array); + $this->assertEquals('logger', $message_array['_ctxt_from']); + + // Test with extraPrefix + $formatter = new GelfMessageFormatter(null, null, 'CTX'); + $message = $formatter->format($record); + + $this->assertInstanceOf('Gelf\Message', $message); + + $message_array = $message->toArray(); + + $this->assertArrayHasKey('_CTXfrom', $message_array); + $this->assertEquals('logger', $message_array['_CTXfrom']); + } + + /** + * @covers Monolog\Formatter\GelfMessageFormatter::format + */ + public function testFormatWithContextContainingException() + { + $formatter = new GelfMessageFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger', 'exception' => array( + 'class' => '\Exception', + 'file' => '/some/file/in/dir.php:56', + 'trace' => array('/some/file/1.php:23', '/some/file/2.php:3') + )), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log' + ); + + $message = $formatter->format($record); + + $this->assertInstanceOf('Gelf\Message', $message); + + $this->assertEquals("/some/file/in/dir.php", $message->getFile()); + $this->assertEquals("56", $message->getLine()); + } + + /** + * @covers Monolog\Formatter\GelfMessageFormatter::format + */ + public function testFormatWithExtra() + { + $formatter = new GelfMessageFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => 'pair'), + 'message' => 'log' + ); + + $message = $formatter->format($record); + + $this->assertInstanceOf('Gelf\Message', $message); + + $message_array = $message->toArray(); + + $this->assertArrayHasKey('_key', $message_array); + $this->assertEquals('pair', $message_array['_key']); + + // Test with extraPrefix + $formatter = new GelfMessageFormatter(null, 'EXT'); + $message = $formatter->format($record); + + $this->assertInstanceOf('Gelf\Message', $message); + + $message_array = $message->toArray(); + + $this->assertArrayHasKey('_EXTkey', $message_array); + $this->assertEquals('pair', $message_array['_EXTkey']); + } + + private function isLegacy() + { + return interface_exists('\Gelf\IMessagePublisher'); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/JsonFormatterTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/JsonFormatterTest.php @@ -0,0 +1,78 @@ +<?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\Formatter; + +use Monolog\Logger; +use Monolog\TestCase; + +class JsonFormatterTest extends TestCase +{ + /** + * @covers Monolog\Formatter\JsonFormatter::__construct + * @covers Monolog\Formatter\JsonFormatter::getBatchMode + * @covers Monolog\Formatter\JsonFormatter::isAppendingNewlines + */ + public function testConstruct() + { + $formatter = new JsonFormatter(); + $this->assertEquals(JsonFormatter::BATCH_MODE_JSON, $formatter->getBatchMode()); + $this->assertEquals(true, $formatter->isAppendingNewlines()); + $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_NEWLINES, false); + $this->assertEquals(JsonFormatter::BATCH_MODE_NEWLINES, $formatter->getBatchMode()); + $this->assertEquals(false, $formatter->isAppendingNewlines()); + } + + /** + * @covers Monolog\Formatter\JsonFormatter::format + */ + public function testFormat() + { + $formatter = new JsonFormatter(); + $record = $this->getRecord(); + $this->assertEquals(json_encode($record)."\n", $formatter->format($record)); + + $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false); + $record = $this->getRecord(); + $this->assertEquals(json_encode($record), $formatter->format($record)); + } + + /** + * @covers Monolog\Formatter\JsonFormatter::formatBatch + * @covers Monolog\Formatter\JsonFormatter::formatBatchJson + */ + public function testFormatBatch() + { + $formatter = new JsonFormatter(); + $records = array( + $this->getRecord(Logger::WARNING), + $this->getRecord(Logger::DEBUG), + ); + $this->assertEquals(json_encode($records), $formatter->formatBatch($records)); + } + + /** + * @covers Monolog\Formatter\JsonFormatter::formatBatch + * @covers Monolog\Formatter\JsonFormatter::formatBatchNewlines + */ + public function testFormatBatchNewlines() + { + $formatter = new JsonFormatter(JsonFormatter::BATCH_MODE_NEWLINES); + $records = $expected = array( + $this->getRecord(Logger::WARNING), + $this->getRecord(Logger::DEBUG), + ); + array_walk($expected, function (&$value, $key) { + $value = json_encode($value); + }); + $this->assertEquals(implode("\n", $expected), $formatter->formatBatch($records)); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/LineFormatterTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/LineFormatterTest.php @@ -0,0 +1,208 @@ +<?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\Formatter; + +/** + * @covers Monolog\Formatter\LineFormatter + */ +class LineFormatterTest extends \PHPUnit_Framework_TestCase +{ + public function testDefFormatWithString() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $message = $formatter->format(array( + 'level_name' => 'WARNING', + 'channel' => 'log', + 'context' => array(), + 'message' => 'foo', + 'datetime' => new \DateTime, + 'extra' => array(), + )); + $this->assertEquals('['.date('Y-m-d').'] log.WARNING: foo [] []'."\n", $message); + } + + public function testDefFormatWithArrayContext() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $message = $formatter->format(array( + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'message' => 'foo', + 'datetime' => new \DateTime, + 'extra' => array(), + 'context' => array( + 'foo' => 'bar', + 'baz' => 'qux', + 'bool' => false, + 'null' => null, + ) + )); + $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: foo {"foo":"bar","baz":"qux","bool":false,"null":null} []'."\n", $message); + } + + public function testDefFormatExtras() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $message = $formatter->format(array( + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime, + 'extra' => array('ip' => '127.0.0.1'), + 'message' => 'log', + )); + $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: log [] {"ip":"127.0.0.1"}'."\n", $message); + } + + public function testFormatExtras() + { + $formatter = new LineFormatter("[%datetime%] %channel%.%level_name%: %message% %context% %extra.file% %extra%\n", 'Y-m-d'); + $message = $formatter->format(array( + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime, + 'extra' => array('ip' => '127.0.0.1', 'file' => 'test'), + 'message' => 'log', + )); + $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: log [] test {"ip":"127.0.0.1"}'."\n", $message); + } + + public function testContextAndExtraOptionallyNotShownIfEmpty() + { + $formatter = new LineFormatter(null, 'Y-m-d', false, true); + $message = $formatter->format(array( + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime, + 'extra' => array(), + 'message' => 'log', + )); + $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: log '."\n", $message); + } + + public function testDefFormatWithObject() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $message = $formatter->format(array( + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime, + 'extra' => array('foo' => new TestFoo, 'bar' => new TestBar, 'baz' => array(), 'res' => fopen('php://memory', 'rb')), + '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); + } + + public function testDefFormatWithException() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $message = $formatter->format(array( + 'level_name' => 'CRITICAL', + 'channel' => 'core', + 'context' => array('exception' => new \RuntimeException('Foo')), + 'datetime' => new \DateTime, + 'extra' => array(), + 'message' => 'foobar', + )); + + $path = str_replace('\\/', '/', json_encode(__FILE__)); + + $this->assertEquals('['.date('Y-m-d').'] core.CRITICAL: foobar {"exception":"[object] (RuntimeException(code: 0): Foo at '.substr($path, 1, -1).':'.(__LINE__-8).')"} []'."\n", $message); + } + + public function testDefFormatWithPreviousException() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $previous = new \LogicException('Wut?'); + $message = $formatter->format(array( + 'level_name' => 'CRITICAL', + 'channel' => 'core', + 'context' => array('exception' => new \RuntimeException('Foo', 0, $previous)), + 'datetime' => new \DateTime, + 'extra' => array(), + 'message' => 'foobar', + )); + + $path = str_replace('\\/', '/', json_encode(__FILE__)); + + $this->assertEquals('['.date('Y-m-d').'] core.CRITICAL: foobar {"exception":"[object] (RuntimeException(code: 0): Foo at '.substr($path, 1, -1).':'.(__LINE__-8).', LogicException(code: 0): Wut? at '.substr($path, 1, -1).':'.(__LINE__-12).')"} []'."\n", $message); + } + + public function testBatchFormat() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $message = $formatter->formatBatch(array( + array( + 'level_name' => 'CRITICAL', + 'channel' => 'test', + 'message' => 'bar', + 'context' => array(), + 'datetime' => new \DateTime, + 'extra' => array(), + ), + array( + 'level_name' => 'WARNING', + 'channel' => 'log', + 'message' => 'foo', + 'context' => array(), + 'datetime' => new \DateTime, + 'extra' => array(), + ), + )); + $this->assertEquals('['.date('Y-m-d').'] test.CRITICAL: bar [] []'."\n".'['.date('Y-m-d').'] log.WARNING: foo [] []'."\n", $message); + } + + public function testFormatShouldStripInlineLineBreaks() + { + $formatter = new LineFormatter(null, 'Y-m-d'); + $message = $formatter->format( + array( + 'message' => "foo\nbar", + 'context' => array(), + 'extra' => array(), + ) + ); + + $this->assertRegExp('/foo bar/', $message); + } + + public function testFormatShouldNotStripInlineLineBreaksWhenFlagIsSet() + { + $formatter = new LineFormatter(null, 'Y-m-d', true); + $message = $formatter->format( + array( + 'message' => "foo\nbar", + 'context' => array(), + 'extra' => array(), + ) + ); + + $this->assertRegExp('/foo\nbar/', $message); + } +} + +class TestFoo +{ + public $foo = 'foo'; +} + +class TestBar +{ + public function __toString() + { + return 'bar'; + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/LogglyFormatterTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/LogglyFormatterTest.php @@ -0,0 +1,40 @@ +<?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\Formatter; + +use Monolog\TestCase; + +class LogglyFormatterTest extends TestCase +{ + /** + * @covers Monolog\Formatter\LogglyFormatter::__construct + */ + public function testConstruct() + { + $formatter = new LogglyFormatter(); + $this->assertEquals(LogglyFormatter::BATCH_MODE_NEWLINES, $formatter->getBatchMode()); + $formatter = new LogglyFormatter(LogglyFormatter::BATCH_MODE_JSON); + $this->assertEquals(LogglyFormatter::BATCH_MODE_JSON, $formatter->getBatchMode()); + } + + /** + * @covers Monolog\Formatter\LogglyFormatter::format + */ + public function testFormat() + { + $formatter = new LogglyFormatter(); + $record = $this->getRecord(); + $formatted_decoded = json_decode($formatter->format($record), true); + $this->assertArrayHasKey("timestamp", $formatted_decoded); + $this->assertEquals(new \DateTime($formatted_decoded["timestamp"]), $record["datetime"]); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/LogstashFormatterTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/LogstashFormatterTest.php @@ -0,0 +1,289 @@ +<?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\Formatter; + +use Monolog\Logger; + +class LogstashFormatterTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Monolog\Formatter\LogstashFormatter::format + */ + public function testDefaultFormatter() + { + $formatter = new LogstashFormatter('test', 'hostname'); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + $message = json_decode($formatter->format($record), true); + + $this->assertEquals("1970-01-01T00:00:00.000000+00:00", $message['@timestamp']); + $this->assertEquals('log', $message['@message']); + $this->assertEquals('meh', $message['@fields']['channel']); + $this->assertContains('meh', $message['@tags']); + $this->assertEquals(Logger::ERROR, $message['@fields']['level']); + $this->assertEquals('test', $message['@type']); + $this->assertEquals('hostname', $message['@source']); + + $formatter = new LogstashFormatter('mysystem'); + + $message = json_decode($formatter->format($record), true); + + $this->assertEquals('mysystem', $message['@type']); + } + + /** + * @covers Monolog\Formatter\LogstashFormatter::format + */ + public function testFormatWithFileAndLine() + { + $formatter = new LogstashFormatter('test'); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('file' => 'test', 'line' => 14), + 'message' => 'log', + ); + + $message = json_decode($formatter->format($record), true); + + $this->assertEquals('test', $message['@fields']['file']); + $this->assertEquals(14, $message['@fields']['line']); + } + + /** + * @covers Monolog\Formatter\LogstashFormatter::format + */ + public function testFormatWithContext() + { + $formatter = new LogstashFormatter('test'); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => 'pair'), + 'message' => 'log' + ); + + $message = json_decode($formatter->format($record), true); + + $message_array = $message['@fields']; + + $this->assertArrayHasKey('ctxt_from', $message_array); + $this->assertEquals('logger', $message_array['ctxt_from']); + + // Test with extraPrefix + $formatter = new LogstashFormatter('test', null, null, 'CTX'); + $message = json_decode($formatter->format($record), true); + + $message_array = $message['@fields']; + + $this->assertArrayHasKey('CTXfrom', $message_array); + $this->assertEquals('logger', $message_array['CTXfrom']); + } + + /** + * @covers Monolog\Formatter\LogstashFormatter::format + */ + public function testFormatWithExtra() + { + $formatter = new LogstashFormatter('test'); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => 'pair'), + 'message' => 'log' + ); + + $message = json_decode($formatter->format($record), true); + + $message_array = $message['@fields']; + + $this->assertArrayHasKey('key', $message_array); + $this->assertEquals('pair', $message_array['key']); + + // Test with extraPrefix + $formatter = new LogstashFormatter('test', null, 'EXT'); + $message = json_decode($formatter->format($record), true); + + $message_array = $message['@fields']; + + $this->assertArrayHasKey('EXTkey', $message_array); + $this->assertEquals('pair', $message_array['EXTkey']); + } + + public function testFormatWithApplicationName() + { + $formatter = new LogstashFormatter('app', 'test'); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => 'pair'), + 'message' => 'log' + ); + + $message = json_decode($formatter->format($record), true); + + $this->assertArrayHasKey('@type', $message); + $this->assertEquals('app', $message['@type']); + } + + /** + * @covers Monolog\Formatter\LogstashFormatter::format + */ + public function testDefaultFormatterV1() + { + $formatter = new LogstashFormatter('test', 'hostname', null, 'ctxt_', LogstashFormatter::V1); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + $message = json_decode($formatter->format($record), true); + + $this->assertEquals("1970-01-01T00:00:00.000000+00:00", $message['@timestamp']); + $this->assertEquals("1", $message['@version']); + $this->assertEquals('log', $message['message']); + $this->assertEquals('meh', $message['channel']); + $this->assertEquals('ERROR', $message['level']); + $this->assertEquals('test', $message['type']); + $this->assertEquals('hostname', $message['host']); + + $formatter = new LogstashFormatter('mysystem', null, null, 'ctxt_', LogstashFormatter::V1); + + $message = json_decode($formatter->format($record), true); + + $this->assertEquals('mysystem', $message['type']); + } + + /** + * @covers Monolog\Formatter\LogstashFormatter::format + */ + public function testFormatWithFileAndLineV1() + { + $formatter = new LogstashFormatter('test', null, null, 'ctxt_', LogstashFormatter::V1); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('file' => 'test', 'line' => 14), + 'message' => 'log', + ); + + $message = json_decode($formatter->format($record), true); + + $this->assertEquals('test', $message['file']); + $this->assertEquals(14, $message['line']); + } + + /** + * @covers Monolog\Formatter\LogstashFormatter::format + */ + public function testFormatWithContextV1() + { + $formatter = new LogstashFormatter('test', null, null, 'ctxt_', LogstashFormatter::V1); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => 'pair'), + 'message' => 'log' + ); + + $message = json_decode($formatter->format($record), true); + + $this->assertArrayHasKey('ctxt_from', $message); + $this->assertEquals('logger', $message['ctxt_from']); + + // Test with extraPrefix + $formatter = new LogstashFormatter('test', null, null, 'CTX', LogstashFormatter::V1); + $message = json_decode($formatter->format($record), true); + + $this->assertArrayHasKey('CTXfrom', $message); + $this->assertEquals('logger', $message['CTXfrom']); + } + + /** + * @covers Monolog\Formatter\LogstashFormatter::format + */ + public function testFormatWithExtraV1() + { + $formatter = new LogstashFormatter('test', null, null, 'ctxt_', LogstashFormatter::V1); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => 'pair'), + 'message' => 'log' + ); + + $message = json_decode($formatter->format($record), true); + + $this->assertArrayHasKey('key', $message); + $this->assertEquals('pair', $message['key']); + + // Test with extraPrefix + $formatter = new LogstashFormatter('test', null, 'EXT', 'ctxt_', LogstashFormatter::V1); + $message = json_decode($formatter->format($record), true); + + $this->assertArrayHasKey('EXTkey', $message); + $this->assertEquals('pair', $message['EXTkey']); + } + + public function testFormatWithApplicationNameV1() + { + $formatter = new LogstashFormatter('app', 'test', null, 'ctxt_', LogstashFormatter::V1); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('key' => 'pair'), + 'message' => 'log' + ); + + $message = json_decode($formatter->format($record), true); + + $this->assertArrayHasKey('type', $message); + $this->assertEquals('app', $message['type']); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/MongoDBFormatterTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/MongoDBFormatterTest.php @@ -0,0 +1,253 @@ +<?php + +namespace Monolog\Formatter; + +use Monolog\Logger; + +/** + * @author Florian Plattner <me@florianplattner.de> + */ +class MongoDBFormatterTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + if (!class_exists('MongoDate')) { + $this->markTestSkipped('mongo extension not installed'); + } + } + + public function constructArgumentProvider() + { + return array( + array(1, true, 1, true), + array(0, false, 0, false), + ); + } + + /** + * @param $traceDepth + * @param $traceAsString + * @param $expectedTraceDepth + * @param $expectedTraceAsString + * + * @dataProvider constructArgumentProvider + */ + public function testConstruct($traceDepth, $traceAsString, $expectedTraceDepth, $expectedTraceAsString) + { + $formatter = new MongoDBFormatter($traceDepth, $traceAsString); + + $reflTrace = new \ReflectionProperty($formatter, 'exceptionTraceAsString'); + $reflTrace->setAccessible(true); + $this->assertEquals($expectedTraceAsString, $reflTrace->getValue($formatter)); + + $reflDepth = new\ReflectionProperty($formatter, 'maxNestingLevel'); + $reflDepth->setAccessible(true); + $this->assertEquals($expectedTraceDepth, $reflDepth->getValue($formatter)); + } + + public function testSimpleFormat() + { + $record = array( + 'message' => 'some log message', + 'context' => array(), + 'level' => Logger::WARNING, + 'level_name' => Logger::getLevelName(Logger::WARNING), + 'channel' => 'test', + 'datetime' => new \DateTime('2014-02-01 00:00:00'), + 'extra' => array(), + ); + + $formatter = new MongoDBFormatter(); + $formattedRecord = $formatter->format($record); + + $this->assertCount(7, $formattedRecord); + $this->assertEquals('some log message', $formattedRecord['message']); + $this->assertEquals(array(), $formattedRecord['context']); + $this->assertEquals(Logger::WARNING, $formattedRecord['level']); + $this->assertEquals(Logger::getLevelName(Logger::WARNING), $formattedRecord['level_name']); + $this->assertEquals('test', $formattedRecord['channel']); + $this->assertInstanceOf('\MongoDate', $formattedRecord['datetime']); + $this->assertEquals('0.00000000 1391212800', $formattedRecord['datetime']->__toString()); + $this->assertEquals(array(), $formattedRecord['extra']); + } + + public function testRecursiveFormat() + { + $someObject = new \stdClass(); + $someObject->foo = 'something'; + $someObject->bar = 'stuff'; + + $record = array( + 'message' => 'some log message', + 'context' => array( + 'stuff' => new \DateTime('2014-02-01 02:31:33'), + 'some_object' => $someObject, + 'context_string' => 'some string', + 'context_int' => 123456, + 'except' => new \Exception('exception message', 987), + ), + 'level' => Logger::WARNING, + 'level_name' => Logger::getLevelName(Logger::WARNING), + 'channel' => 'test', + 'datetime' => new \DateTime('2014-02-01 00:00:00'), + 'extra' => array(), + ); + + $formatter = new MongoDBFormatter(); + $formattedRecord = $formatter->format($record); + + $this->assertCount(5, $formattedRecord['context']); + $this->assertInstanceOf('\MongoDate', $formattedRecord['context']['stuff']); + $this->assertEquals('0.00000000 1391221893', $formattedRecord['context']['stuff']->__toString()); + $this->assertEquals( + array( + 'foo' => 'something', + 'bar' => 'stuff', + 'class' => 'stdClass', + ), + $formattedRecord['context']['some_object'] + ); + $this->assertEquals('some string', $formattedRecord['context']['context_string']); + $this->assertEquals(123456, $formattedRecord['context']['context_int']); + + $this->assertCount(5, $formattedRecord['context']['except']); + $this->assertEquals('exception message', $formattedRecord['context']['except']['message']); + $this->assertEquals(987, $formattedRecord['context']['except']['code']); + $this->assertInternalType('string', $formattedRecord['context']['except']['file']); + $this->assertInternalType('integer', $formattedRecord['context']['except']['code']); + $this->assertInternalType('string', $formattedRecord['context']['except']['trace']); + $this->assertEquals('Exception', $formattedRecord['context']['except']['class']); + } + + public function testFormatDepthArray() + { + $record = array( + 'message' => 'some log message', + 'context' => array( + 'nest2' => array( + 'property' => 'anything', + 'nest3' => array( + 'nest4' => 'value', + 'property' => 'nothing' + ) + ) + ), + 'level' => Logger::WARNING, + 'level_name' => Logger::getLevelName(Logger::WARNING), + 'channel' => 'test', + 'datetime' => new \DateTime('2014-02-01 00:00:00'), + 'extra' => array(), + ); + + $formatter = new MongoDBFormatter(2); + $formattedResult = $formatter->format($record); + + $this->assertEquals( + array( + 'nest2' => array( + 'property' => 'anything', + 'nest3' => '[...]', + ) + ), + $formattedResult['context'] + ); + } + + public function testFormatDepthArrayInfiniteNesting() + { + $record = array( + 'message' => 'some log message', + 'context' => array( + 'nest2' => array( + 'property' => 'something', + 'nest3' => array( + 'property' => 'anything', + 'nest4' => array( + 'property' => 'nothing', + ), + ) + ) + ), + 'level' => Logger::WARNING, + 'level_name' => Logger::getLevelName(Logger::WARNING), + 'channel' => 'test', + 'datetime' => new \DateTime('2014-02-01 00:00:00'), + 'extra' => array(), + ); + + $formatter = new MongoDBFormatter(0); + $formattedResult = $formatter->format($record); + + $this->assertEquals( + array( + 'nest2' => array( + 'property' => 'something', + 'nest3' => array( + 'property' => 'anything', + 'nest4' => array( + 'property' => 'nothing', + ) + ), + ) + ), + $formattedResult['context'] + ); + } + + public function testFormatDepthObjects() + { + $someObject = new \stdClass(); + $someObject->property = 'anything'; + $someObject->nest3 = new \stdClass(); + $someObject->nest3->property = 'nothing'; + $someObject->nest3->nest4 = 'invisible'; + + $record = array( + 'message' => 'some log message', + 'context' => array( + 'nest2' => $someObject + ), + 'level' => Logger::WARNING, + 'level_name' => Logger::getLevelName(Logger::WARNING), + 'channel' => 'test', + 'datetime' => new \DateTime('2014-02-01 00:00:00'), + 'extra' => array(), + ); + + $formatter = new MongoDBFormatter(2, true); + $formattedResult = $formatter->format($record); + + $this->assertEquals( + array( + 'nest2' => array( + 'property' => 'anything', + 'nest3' => '[...]', + 'class' => 'stdClass', + ), + ), + $formattedResult['context'] + ); + } + + public function testFormatDepthException() + { + $record = array( + 'message' => 'some log message', + 'context' => array( + 'nest2' => new \Exception('exception message', 987), + ), + 'level' => Logger::WARNING, + 'level_name' => Logger::getLevelName(Logger::WARNING), + 'channel' => 'test', + 'datetime' => new \DateTime('2014-02-01 00:00:00'), + 'extra' => array(), + ); + + $formatter = new MongoDBFormatter(2, false); + $formattedRecord = $formatter->format($record); + + $this->assertEquals('exception message', $formattedRecord['context']['nest2']['message']); + $this->assertEquals(987, $formattedRecord['context']['nest2']['code']); + $this->assertEquals('[...]', $formattedRecord['context']['nest2']['trace']); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/NormalizerFormatterTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/NormalizerFormatterTest.php @@ -0,0 +1,247 @@ +<?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\Formatter; + +/** + * @covers Monolog\Formatter\NormalizerFormatter + */ +class NormalizerFormatterTest extends \PHPUnit_Framework_TestCase +{ + public function testFormat() + { + $formatter = new NormalizerFormatter('Y-m-d'); + $formatted = $formatter->format(array( + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'message' => 'foo', + 'datetime' => new \DateTime, + 'extra' => array('foo' => new TestFooNorm, 'bar' => new TestBarNorm, 'baz' => array(), 'res' => fopen('php://memory', 'rb')), + 'context' => array( + 'foo' => 'bar', + 'baz' => 'qux', + ), + )); + + $this->assertEquals(array( + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'message' => 'foo', + 'datetime' => date('Y-m-d'), + 'extra' => array( + 'foo' => '[object] (Monolog\\Formatter\\TestFooNorm: {"foo":"foo"})', + 'bar' => '[object] (Monolog\\Formatter\\TestBarNorm: {})', + 'baz' => array(), + 'res' => '[resource]', + ), + 'context' => array( + 'foo' => 'bar', + 'baz' => 'qux', + ) + ), $formatted); + } + + public function testFormatExceptions() + { + $formatter = new NormalizerFormatter('Y-m-d'); + $e = new \LogicException('bar'); + $e2 = new \RuntimeException('foo', 0, $e); + $formatted = $formatter->format(array( + 'exception' => $e2, + )); + + $this->assertGreaterThan(5, count($formatted['exception']['trace'])); + $this->assertTrue(isset($formatted['exception']['previous'])); + unset($formatted['exception']['trace'], $formatted['exception']['previous']); + + $this->assertEquals(array( + 'exception' => array( + 'class' => get_class($e2), + 'message' => $e2->getMessage(), + 'code' => $e2->getCode(), + 'file' => $e2->getFile().':'.$e2->getLine(), + ) + ), $formatted); + } + + public function testBatchFormat() + { + $formatter = new NormalizerFormatter('Y-m-d'); + $formatted = $formatter->formatBatch(array( + array( + 'level_name' => 'CRITICAL', + 'channel' => 'test', + 'message' => 'bar', + 'context' => array(), + 'datetime' => new \DateTime, + 'extra' => array(), + ), + array( + 'level_name' => 'WARNING', + 'channel' => 'log', + 'message' => 'foo', + 'context' => array(), + 'datetime' => new \DateTime, + 'extra' => array(), + ), + )); + $this->assertEquals(array( + array( + 'level_name' => 'CRITICAL', + 'channel' => 'test', + 'message' => 'bar', + 'context' => array(), + 'datetime' => date('Y-m-d'), + 'extra' => array(), + ), + array( + 'level_name' => 'WARNING', + 'channel' => 'log', + 'message' => 'foo', + 'context' => array(), + 'datetime' => date('Y-m-d'), + 'extra' => array(), + ), + ), $formatted); + } + + /** + * Test issue #137 + */ + public function testIgnoresRecursiveObjectReferences() + { + // set up the recursion + $foo = new \stdClass(); + $bar = new \stdClass(); + + $foo->bar = $bar; + $bar->foo = $foo; + + // set an error handler to assert that the error is not raised anymore + $that = $this; + set_error_handler(function ($level, $message, $file, $line, $context) use ($that) { + if (error_reporting() & $level) { + restore_error_handler(); + $that->fail("$message should not be raised"); + } + }); + + $formatter = new NormalizerFormatter(); + $reflMethod = new \ReflectionMethod($formatter, 'toJson'); + $reflMethod->setAccessible(true); + $res = $reflMethod->invoke($formatter, array($foo, $bar), true); + + restore_error_handler(); + + $this->assertEquals(@json_encode(array($foo, $bar)), $res); + } + + public function testIgnoresInvalidTypes() + { + // set up the recursion + $resource = fopen(__FILE__, 'r'); + + // set an error handler to assert that the error is not raised anymore + $that = $this; + set_error_handler(function ($level, $message, $file, $line, $context) use ($that) { + if (error_reporting() & $level) { + restore_error_handler(); + $that->fail("$message should not be raised"); + } + }); + + $formatter = new NormalizerFormatter(); + $reflMethod = new \ReflectionMethod($formatter, 'toJson'); + $reflMethod->setAccessible(true); + $res = $reflMethod->invoke($formatter, array($resource), true); + + restore_error_handler(); + + $this->assertEquals(@json_encode(array($resource)), $res); + } + + public function testExceptionTraceWithArgs() + { + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('Not supported in HHVM since it detects errors differently'); + } + + // This happens i.e. in React promises or Guzzle streams where stream wrappers are registered + // and no file or line are included in the trace because it's treated as internal function + set_error_handler(function ($errno, $errstr, $errfile, $errline) { + throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); + }); + + try { + // 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); + // Just do something stupid with a resource/wrapped resource as argument + array_keys($wrappedResource); + } catch (\Exception $e) { + restore_error_handler(); + } + + $formatter = new NormalizerFormatter(); + $record = array('context' => array('exception' => $e)); + $result = $formatter->format($record); + + $this->assertRegExp( + '%"resource":"\[resource\]"%', + $result['context']['exception']['trace'][0] + ); + + if (version_compare(PHP_VERSION, '5.5.0', '>=')) { + $pattern = '%"wrappedResource":"\[object\] \(Monolog\\\\\\\\Formatter\\\\\\\\TestStreamFoo: \)"%'; + } else { + $pattern = '%\\\\"resource\\\\":null%'; + } + + // Tests that the wrapped resource is ignored while encoding, only works for PHP <= 5.4 + $this->assertRegExp( + $pattern, + $result['context']['exception']['trace'][0] + ); + } +} + +class TestFooNorm +{ + public $foo = 'foo'; +} + +class TestBarNorm +{ + public function __toString() + { + return 'bar'; + } +} + +class TestStreamFoo +{ + public $foo; + public $resource; + + public function __construct($resource) + { + $this->resource = $resource; + $this->foo = 'BAR'; + } + + public function __toString() + { + fseek($this->resource, 0); + + return $this->foo . ' - ' . (string) stream_get_contents($this->resource); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/ScalarFormatterTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/ScalarFormatterTest.php @@ -0,0 +1,98 @@ +<?php +namespace Monolog\Formatter; + +class ScalarFormatterTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + $this->formatter = new ScalarFormatter(); + } + + public function buildTrace(\Exception $e) + { + $data = array(); + $trace = $e->getTrace(); + foreach ($trace as $frame) { + if (isset($frame['file'])) { + $data[] = $frame['file'].':'.$frame['line']; + } else { + $data[] = json_encode($frame); + } + } + + return $data; + } + + public function encodeJson($data) + { + if (version_compare(PHP_VERSION, '5.4.0', '>=')) { + return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } + + return json_encode($data); + } + + public function testFormat() + { + $exception = new \Exception('foo'); + $formatted = $this->formatter->format(array( + 'foo' => 'string', + 'bar' => 1, + 'baz' => false, + 'bam' => array(1, 2, 3), + 'bat' => array('foo' => 'bar'), + 'bap' => \DateTime::createFromFormat(\DateTime::ISO8601, '1970-01-01T00:00:00+0000'), + 'ban' => $exception + )); + + $this->assertSame(array( + 'foo' => 'string', + 'bar' => 1, + 'baz' => false, + 'bam' => $this->encodeJson(array(1, 2, 3)), + 'bat' => $this->encodeJson(array('foo' => 'bar')), + 'bap' => '1970-01-01 00:00:00', + 'ban' => $this->encodeJson(array( + 'class' => get_class($exception), + 'message' => $exception->getMessage(), + 'code' => $exception->getCode(), + 'file' => $exception->getFile() . ':' . $exception->getLine(), + 'trace' => $this->buildTrace($exception) + )) + ), $formatted); + } + + public function testFormatWithErrorContext() + { + $context = array('file' => 'foo', 'line' => 1); + $formatted = $this->formatter->format(array( + 'context' => $context + )); + + $this->assertSame(array( + 'context' => $this->encodeJson($context) + ), $formatted); + } + + public function testFormatWithExceptionContext() + { + $exception = new \Exception('foo'); + $formatted = $this->formatter->format(array( + 'context' => array( + 'exception' => $exception + ) + )); + + $this->assertSame(array( + 'context' => $this->encodeJson(array( + 'exception' => array( + 'class' => get_class($exception), + 'message' => $exception->getMessage(), + 'code' => $exception->getCode(), + 'file' => $exception->getFile() . ':' . $exception->getLine(), + 'trace' => $this->buildTrace($exception) + ) + )) + ), $formatted); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/WildfireFormatterTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Formatter/WildfireFormatterTest.php @@ -0,0 +1,142 @@ +<?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\Formatter; + +use Monolog\Logger; + +class WildfireFormatterTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Monolog\Formatter\WildfireFormatter::format + */ + public function testDefaultFormat() + { + $wildfire = new WildfireFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('ip' => '127.0.0.1'), + 'message' => 'log', + ); + + $message = $wildfire->format($record); + + $this->assertEquals( + '125|[{"Type":"ERROR","File":"","Line":"","Label":"meh"},' + .'{"message":"log","context":{"from":"logger"},"extra":{"ip":"127.0.0.1"}}]|', + $message + ); + } + + /** + * @covers Monolog\Formatter\WildfireFormatter::format + */ + public function testFormatWithFileAndLine() + { + $wildfire = new WildfireFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('from' => 'logger'), + 'datetime' => new \DateTime("@0"), + 'extra' => array('ip' => '127.0.0.1', 'file' => 'test', 'line' => 14), + 'message' => 'log', + ); + + $message = $wildfire->format($record); + + $this->assertEquals( + '129|[{"Type":"ERROR","File":"test","Line":14,"Label":"meh"},' + .'{"message":"log","context":{"from":"logger"},"extra":{"ip":"127.0.0.1"}}]|', + $message + ); + } + + /** + * @covers Monolog\Formatter\WildfireFormatter::format + */ + public function testFormatWithoutContext() + { + $wildfire = new WildfireFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + $message = $wildfire->format($record); + + $this->assertEquals( + '58|[{"Type":"ERROR","File":"","Line":"","Label":"meh"},"log"]|', + $message + ); + } + + /** + * @covers Monolog\Formatter\WildfireFormatter::formatBatch + * @expectedException BadMethodCallException + */ + public function testBatchFormatThrowException() + { + $wildfire = new WildfireFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array(), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + $wildfire->formatBatch(array($record)); + } + + /** + * @covers Monolog\Formatter\WildfireFormatter::format + */ + public function testTableFormat() + { + $wildfire = new WildfireFormatter(); + $record = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'table-channel', + 'context' => array( + WildfireFormatter::TABLE => array( + array('col1', 'col2', 'col3'), + array('val1', 'val2', 'val3'), + array('foo1', 'foo2', 'foo3'), + array('bar1', 'bar2', 'bar3'), + ), + ), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'table-message', + ); + + $message = $wildfire->format($record); + + $this->assertEquals( + '171|[{"Type":"TABLE","File":"","Line":"","Label":"table-channel: table-message"},[["col1","col2","col3"],["val1","val2","val3"],["foo1","foo2","foo3"],["bar1","bar2","bar3"]]]|', + $message + ); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Functional/Handler/FirePHPHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Functional/Handler/FirePHPHandlerTest.php @@ -0,0 +1,32 @@ +<?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/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/AbstractHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/AbstractHandlerTest.php @@ -0,0 +1,115 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; +use Monolog\Formatter\LineFormatter; +use Monolog\Processor\WebProcessor; + +class AbstractHandlerTest extends TestCase +{ + /** + * @covers Monolog\Handler\AbstractHandler::__construct + * @covers Monolog\Handler\AbstractHandler::getLevel + * @covers Monolog\Handler\AbstractHandler::setLevel + * @covers Monolog\Handler\AbstractHandler::getBubble + * @covers Monolog\Handler\AbstractHandler::setBubble + * @covers Monolog\Handler\AbstractHandler::getFormatter + * @covers Monolog\Handler\AbstractHandler::setFormatter + */ + public function testConstructAndGetSet() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler', array(Logger::WARNING, false)); + $this->assertEquals(Logger::WARNING, $handler->getLevel()); + $this->assertEquals(false, $handler->getBubble()); + + $handler->setLevel(Logger::ERROR); + $handler->setBubble(true); + $handler->setFormatter($formatter = new LineFormatter); + $this->assertEquals(Logger::ERROR, $handler->getLevel()); + $this->assertEquals(true, $handler->getBubble()); + $this->assertSame($formatter, $handler->getFormatter()); + } + + /** + * @covers Monolog\Handler\AbstractHandler::handleBatch + */ + public function testHandleBatch() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler'); + $handler->expects($this->exactly(2)) + ->method('handle'); + $handler->handleBatch(array($this->getRecord(), $this->getRecord())); + } + + /** + * @covers Monolog\Handler\AbstractHandler::isHandling + */ + public function testIsHandling() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler', array(Logger::WARNING, false)); + $this->assertTrue($handler->isHandling($this->getRecord())); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG))); + } + + /** + * @covers Monolog\Handler\AbstractHandler::__construct + */ + public function testHandlesPsrStyleLevels() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler', array('warning', false)); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG))); + $handler->setLevel('debug'); + $this->assertTrue($handler->isHandling($this->getRecord(Logger::DEBUG))); + } + + /** + * @covers Monolog\Handler\AbstractHandler::getFormatter + * @covers Monolog\Handler\AbstractHandler::getDefaultFormatter + */ + public function testGetFormatterInitializesDefault() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler'); + $this->assertInstanceOf('Monolog\Formatter\LineFormatter', $handler->getFormatter()); + } + + /** + * @covers Monolog\Handler\AbstractHandler::pushProcessor + * @covers Monolog\Handler\AbstractHandler::popProcessor + * @expectedException LogicException + */ + public function testPushPopProcessor() + { + $logger = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler'); + $processor1 = new WebProcessor; + $processor2 = new WebProcessor; + + $logger->pushProcessor($processor1); + $logger->pushProcessor($processor2); + + $this->assertEquals($processor2, $logger->popProcessor()); + $this->assertEquals($processor1, $logger->popProcessor()); + $logger->popProcessor(); + } + + /** + * @covers Monolog\Handler\AbstractHandler::pushProcessor + * @expectedException InvalidArgumentException + */ + public function testPushProcessorWithNonCallable() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler'); + + $handler->pushProcessor(new \stdClass()); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/AbstractProcessingHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/AbstractProcessingHandlerTest.php @@ -0,0 +1,80 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; +use Monolog\Processor\WebProcessor; + +class AbstractProcessingHandlerTest extends TestCase +{ + /** + * @covers Monolog\Handler\AbstractProcessingHandler::handle + */ + public function testHandleLowerLevelMessage() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::WARNING, true)); + $this->assertFalse($handler->handle($this->getRecord(Logger::DEBUG))); + } + + /** + * @covers Monolog\Handler\AbstractProcessingHandler::handle + */ + public function testHandleBubbling() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::DEBUG, true)); + $this->assertFalse($handler->handle($this->getRecord())); + } + + /** + * @covers Monolog\Handler\AbstractProcessingHandler::handle + */ + public function testHandleNotBubbling() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::DEBUG, false)); + $this->assertTrue($handler->handle($this->getRecord())); + } + + /** + * @covers Monolog\Handler\AbstractProcessingHandler::handle + */ + public function testHandleIsFalseWhenNotHandled() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::WARNING, false)); + $this->assertTrue($handler->handle($this->getRecord())); + $this->assertFalse($handler->handle($this->getRecord(Logger::DEBUG))); + } + + /** + * @covers Monolog\Handler\AbstractProcessingHandler::processRecord + */ + public function testProcessRecord() + { + $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler'); + $handler->pushProcessor(new WebProcessor(array( + 'REQUEST_URI' => '', + 'REQUEST_METHOD' => '', + 'REMOTE_ADDR' => '', + 'SERVER_NAME' => '', + 'UNIQUE_ID' => '', + ))); + $handledRecord = null; + $handler->expects($this->once()) + ->method('write') + ->will($this->returnCallback(function ($record) use (&$handledRecord) { + $handledRecord = $record; + })) + ; + $handler->handle($this->getRecord()); + $this->assertEquals(6, count($handledRecord['extra'])); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/AmqpHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/AmqpHandlerTest.php @@ -0,0 +1,137 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; +use PhpAmqpLib\Message\AMQPMessage; +use PhpAmqpLib\Channel\AMQPChannel; +use PhpAmqpLib\Connection\AMQPConnection; + +/** + * @covers Monolog\Handler\RotatingFileHandler + */ +class AmqpHandlerTest extends TestCase +{ + public function testHandleAmqpExt() + { + if (!class_exists('AMQPConnection') || !class_exists('AMQPExchange')) { + $this->markTestSkipped("amqp-php not installed"); + } + + if (!class_exists('AMQPChannel')) { + $this->markTestSkipped("Please update AMQP to version >= 1.0"); + } + + $messages = array(); + + $exchange = $this->getMock('AMQPExchange', array('publish', 'setName'), array(), '', false); + $exchange->expects($this->once()) + ->method('setName') + ->with('log') + ; + $exchange->expects($this->any()) + ->method('publish') + ->will($this->returnCallback(function ($message, $routing_key, $flags = 0, $attributes = array()) use (&$messages) { + $messages[] = array($message, $routing_key, $flags, $attributes); + })) + ; + + $handler = new AmqpHandler($exchange, 'log'); + + $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); + + $expected = array( + array( + 'message' => 'test', + 'context' => array( + 'data' => array(), + 'foo' => 34, + ), + 'level' => 300, + 'level_name' => 'WARNING', + 'channel' => 'test', + 'extra' => array(), + ), + 'warn.test', + 0, + array( + 'delivery_mode' => 2, + 'Content-type' => 'application/json' + ) + ); + + $handler->handle($record); + + $this->assertCount(1, $messages); + $messages[0][0] = json_decode($messages[0][0], true); + unset($messages[0][0]['datetime']); + $this->assertEquals($expected, $messages[0]); + } + + public function testHandlePhpAmqpLib() + { + if (!class_exists('PhpAmqpLib\Connection\AMQPConnection')) { + $this->markTestSkipped("php-amqplib not installed"); + } + + $messages = array(); + + $exchange = $this->getMock('PhpAmqpLib\Channel\AMQPChannel', array('basic_publish', '__destruct'), array(), '', false); + + $exchange->expects($this->any()) + ->method('basic_publish') + ->will($this->returnCallback(function (AMQPMessage $msg, $exchange = "", $routing_key = "", $mandatory = false, $immediate = false, $ticket = null) use (&$messages) { + $messages[] = array($msg, $exchange, $routing_key, $mandatory, $immediate, $ticket); + })) + ; + + $handler = new AmqpHandler($exchange, 'log'); + + $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); + + $expected = array( + array( + 'message' => 'test', + 'context' => array( + 'data' => array(), + 'foo' => 34, + ), + 'level' => 300, + 'level_name' => 'WARNING', + 'channel' => 'test', + 'extra' => array(), + ), + 'log', + 'warn.test', + false, + false, + null, + array( + 'delivery_mode' => 2, + 'content_type' => 'application/json' + ) + ); + + $handler->handle($record); + + $this->assertCount(1, $messages); + + /* @var $msg AMQPMessage */ + $msg = $messages[0][0]; + $messages[0][0] = json_decode($msg->body, true); + $messages[0][] = $msg->get_properties(); + unset($messages[0][0]['datetime']); + + $this->assertEquals($expected, $messages[0]); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/BrowserConsoleHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/BrowserConsoleHandlerTest.php @@ -0,0 +1,130 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +/** + * @covers Monolog\Handler\BrowserConsoleHandlerTest + */ +class BrowserConsoleHandlerTest extends TestCase +{ + protected function setUp() + { + BrowserConsoleHandler::reset(); + } + + protected function generateScript() + { + $reflMethod = new \ReflectionMethod('Monolog\Handler\BrowserConsoleHandler', 'generateScript'); + $reflMethod->setAccessible(true); + + return $reflMethod->invoke(null); + } + + public function testStyling() + { + $handler = new BrowserConsoleHandler(); + $handler->setFormatter($this->getIdentityFormatter()); + + $handler->handle($this->getRecord(Logger::DEBUG, 'foo[[bar]]{color: red}')); + + $expected = <<<EOF +(function (c) {if (c && c.groupCollapsed) { +c.log("%cfoo%cbar%c", "font-weight: normal", "color: red", "font-weight: normal"); +}})(console); +EOF; + + $this->assertEquals($expected, $this->generateScript()); + } + + public function testEscaping() + { + $handler = new BrowserConsoleHandler(); + $handler->setFormatter($this->getIdentityFormatter()); + + $handler->handle($this->getRecord(Logger::DEBUG, "[foo] [[\"bar\n[baz]\"]]{color: red}")); + + $expected = <<<EOF +(function (c) {if (c && c.groupCollapsed) { +c.log("%c[foo] %c\"bar\\n[baz]\"%c", "font-weight: normal", "color: red", "font-weight: normal"); +}})(console); +EOF; + + $this->assertEquals($expected, $this->generateScript()); + } + + public function testAutolabel() + { + $handler = new BrowserConsoleHandler(); + $handler->setFormatter($this->getIdentityFormatter()); + + $handler->handle($this->getRecord(Logger::DEBUG, '[[foo]]{macro: autolabel}')); + $handler->handle($this->getRecord(Logger::DEBUG, '[[bar]]{macro: autolabel}')); + $handler->handle($this->getRecord(Logger::DEBUG, '[[foo]]{macro: autolabel}')); + + $expected = <<<EOF +(function (c) {if (c && c.groupCollapsed) { +c.log("%c%cfoo%c", "font-weight: normal", "background-color: blue; color: white; border-radius: 3px; padding: 0 2px 0 2px", "font-weight: normal"); +c.log("%c%cbar%c", "font-weight: normal", "background-color: green; color: white; border-radius: 3px; padding: 0 2px 0 2px", "font-weight: normal"); +c.log("%c%cfoo%c", "font-weight: normal", "background-color: blue; color: white; border-radius: 3px; padding: 0 2px 0 2px", "font-weight: normal"); +}})(console); +EOF; + + $this->assertEquals($expected, $this->generateScript()); + } + + public function testContext() + { + $handler = new BrowserConsoleHandler(); + $handler->setFormatter($this->getIdentityFormatter()); + + $handler->handle($this->getRecord(Logger::DEBUG, 'test', array('foo' => 'bar'))); + + $expected = <<<EOF +(function (c) {if (c && c.groupCollapsed) { +c.groupCollapsed("%ctest", "font-weight: normal"); +c.log("%c%s", "font-weight: bold", "Context"); +c.log("%s: %o", "foo", "bar"); +c.groupEnd(); +}})(console); +EOF; + + $this->assertEquals($expected, $this->generateScript()); + } + + public function testConcurrentHandlers() + { + $handler1 = new BrowserConsoleHandler(); + $handler1->setFormatter($this->getIdentityFormatter()); + + $handler2 = new BrowserConsoleHandler(); + $handler2->setFormatter($this->getIdentityFormatter()); + + $handler1->handle($this->getRecord(Logger::DEBUG, 'test1')); + $handler2->handle($this->getRecord(Logger::DEBUG, 'test2')); + $handler1->handle($this->getRecord(Logger::DEBUG, 'test3')); + $handler2->handle($this->getRecord(Logger::DEBUG, 'test4')); + + $expected = <<<EOF +(function (c) {if (c && c.groupCollapsed) { +c.log("%ctest1", "font-weight: normal"); +c.log("%ctest2", "font-weight: normal"); +c.log("%ctest3", "font-weight: normal"); +c.log("%ctest4", "font-weight: normal"); +}})(console); +EOF; + + $this->assertEquals($expected, $this->generateScript()); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/BufferHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/BufferHandlerTest.php @@ -0,0 +1,158 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +class BufferHandlerTest extends TestCase +{ + private $shutdownCheckHandler; + + /** + * @covers Monolog\Handler\BufferHandler::__construct + * @covers Monolog\Handler\BufferHandler::handle + * @covers Monolog\Handler\BufferHandler::close + */ + public function testHandleBuffers() + { + $test = new TestHandler(); + $handler = new BufferHandler($test); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $this->assertFalse($test->hasDebugRecords()); + $this->assertFalse($test->hasInfoRecords()); + $handler->close(); + $this->assertTrue($test->hasInfoRecords()); + $this->assertTrue(count($test->getRecords()) === 2); + } + + /** + * @covers Monolog\Handler\BufferHandler::close + * @covers Monolog\Handler\BufferHandler::flush + */ + public function testPropagatesRecordsAtEndOfRequest() + { + $test = new TestHandler(); + $handler = new BufferHandler($test); + $handler->handle($this->getRecord(Logger::WARNING)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $this->shutdownCheckHandler = $test; + register_shutdown_function(array($this, 'checkPropagation')); + } + + public function checkPropagation() + { + if (!$this->shutdownCheckHandler->hasWarningRecords() || !$this->shutdownCheckHandler->hasDebugRecords()) { + echo '!!! BufferHandlerTest::testPropagatesRecordsAtEndOfRequest failed to verify that the messages have been propagated' . PHP_EOL; + exit(1); + } + } + + /** + * @covers Monolog\Handler\BufferHandler::handle + */ + public function testHandleBufferLimit() + { + $test = new TestHandler(); + $handler = new BufferHandler($test, 2); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $handler->handle($this->getRecord(Logger::WARNING)); + $handler->close(); + $this->assertTrue($test->hasWarningRecords()); + $this->assertTrue($test->hasInfoRecords()); + $this->assertFalse($test->hasDebugRecords()); + } + + /** + * @covers Monolog\Handler\BufferHandler::handle + */ + public function testHandleBufferLimitWithFlushOnOverflow() + { + $test = new TestHandler(); + $handler = new BufferHandler($test, 3, Logger::DEBUG, true, true); + + // send two records + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $this->assertFalse($test->hasDebugRecords()); + $this->assertCount(0, $test->getRecords()); + + // overflow + $handler->handle($this->getRecord(Logger::INFO)); + $this->assertTrue($test->hasDebugRecords()); + $this->assertCount(3, $test->getRecords()); + + // should buffer again + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertCount(3, $test->getRecords()); + + $handler->close(); + $this->assertCount(5, $test->getRecords()); + $this->assertTrue($test->hasWarningRecords()); + $this->assertTrue($test->hasInfoRecords()); + } + + /** + * @covers Monolog\Handler\BufferHandler::handle + */ + public function testHandleLevel() + { + $test = new TestHandler(); + $handler = new BufferHandler($test, 0, Logger::INFO); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $handler->handle($this->getRecord(Logger::WARNING)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->close(); + $this->assertTrue($test->hasWarningRecords()); + $this->assertTrue($test->hasInfoRecords()); + $this->assertFalse($test->hasDebugRecords()); + } + + /** + * @covers Monolog\Handler\BufferHandler::flush + */ + public function testFlush() + { + $test = new TestHandler(); + $handler = new BufferHandler($test, 0); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $handler->flush(); + $this->assertTrue($test->hasInfoRecords()); + $this->assertTrue($test->hasDebugRecords()); + $this->assertFalse($test->hasWarningRecords()); + } + + /** + * @covers Monolog\Handler\BufferHandler::handle + */ + public function testHandleUsesProcessors() + { + $test = new TestHandler(); + $handler = new BufferHandler($test); + $handler->pushProcessor(function ($record) { + $record['extra']['foo'] = true; + + return $record; + }); + $handler->handle($this->getRecord(Logger::WARNING)); + $handler->flush(); + $this->assertTrue($test->hasWarningRecords()); + $records = $test->getRecords(); + $this->assertTrue($records[0]['extra']['foo']); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/ChromePHPHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/ChromePHPHandlerTest.php @@ -0,0 +1,141 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +/** + * @covers Monolog\Handler\ChromePHPHandler + */ +class ChromePHPHandlerTest extends TestCase +{ + protected function setUp() + { + TestChromePHPHandler::reset(); + $_SERVER['HTTP_USER_AGENT'] = 'Monolog Test; Chrome/1.0'; + } + + public function testHeaders() + { + $handler = new TestChromePHPHandler(); + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::WARNING)); + + $expected = array( + 'X-ChromeLogger-Data' => base64_encode(utf8_encode(json_encode(array( + 'version' => ChromePHPHandler::VERSION, + 'columns' => array('label', 'log', 'backtrace', 'type'), + 'rows' => array( + 'test', + 'test', + ), + 'request_uri' => '', + )))) + ); + + $this->assertEquals($expected, $handler->getHeaders()); + } + + public function testHeadersOverflow() + { + $handler = new TestChromePHPHandler(); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::WARNING, str_repeat('a', 150*1024))); + + // overflow chrome headers limit + $handler->handle($this->getRecord(Logger::WARNING, str_repeat('a', 100*1024))); + + $expected = array( + 'X-ChromeLogger-Data' => base64_encode(utf8_encode(json_encode(array( + 'version' => ChromePHPHandler::VERSION, + 'columns' => array('label', 'log', 'backtrace', 'type'), + 'rows' => array( + array( + 'test', + 'test', + 'unknown', + 'log', + ), + array( + 'test', + str_repeat('a', 150*1024), + 'unknown', + 'warn', + ), + array( + 'monolog', + 'Incomplete logs, chrome header size limit reached', + 'unknown', + 'warn', + ), + ), + 'request_uri' => '', + )))) + ); + + $this->assertEquals($expected, $handler->getHeaders()); + } + + public function testConcurrentHandlers() + { + $handler = new TestChromePHPHandler(); + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::WARNING)); + + $handler2 = new TestChromePHPHandler(); + $handler2->setFormatter($this->getIdentityFormatter()); + $handler2->handle($this->getRecord(Logger::DEBUG)); + $handler2->handle($this->getRecord(Logger::WARNING)); + + $expected = array( + 'X-ChromeLogger-Data' => base64_encode(utf8_encode(json_encode(array( + 'version' => ChromePHPHandler::VERSION, + 'columns' => array('label', 'log', 'backtrace', 'type'), + 'rows' => array( + 'test', + 'test', + 'test', + 'test', + ), + 'request_uri' => '', + )))) + ); + + $this->assertEquals($expected, $handler2->getHeaders()); + } +} + +class TestChromePHPHandler extends ChromePHPHandler +{ + protected $headers = array(); + + public static function reset() + { + self::$initialized = false; + self::$overflowed = false; + self::$sendHeaders = true; + self::$json['rows'] = array(); + } + + protected function sendHeader($header, $content) + { + $this->headers[$header] = $content; + } + + public function getHeaders() + { + return $this->headers; + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/CouchDBHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/CouchDBHandlerTest.php @@ -0,0 +1,41 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +class CouchDBHandlerTest extends TestCase +{ + public function testHandle() + { + $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 { + $handler->handle($record); + } catch (\RuntimeException $e) { + $this->markTestSkipped('Could not connect to couchdb server on http://localhost:5984'); + } + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/DoctrineCouchDBHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/DoctrineCouchDBHandlerTest.php @@ -0,0 +1,52 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +class DoctrineCouchDBHandlerTest extends TestCase +{ + protected function setup() + { + if (!class_exists('Doctrine\CouchDB\CouchDBClient')) { + $this->markTestSkipped('The "doctrine/couchdb" package is not installed'); + } + } + + public function testHandle() + { + $client = $this->getMockBuilder('Doctrine\\CouchDB\\CouchDBClient') + ->setMethods(array('postDocument')) + ->disableOriginalConstructor() + ->getMock(); + + $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(), + ); + + $client->expects($this->once()) + ->method('postDocument') + ->with($expected); + + $handler = new DoctrineCouchDBHandler($client); + $handler->handle($record); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/DynamoDbHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/DynamoDbHandlerTest.php @@ -0,0 +1,73 @@ +<?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 Monolog\TestCase; + +class DynamoDbHandlerTest extends TestCase +{ + public function setUp() + { + if (!class_exists('Aws\DynamoDb\DynamoDbClient')) { + $this->markTestSkipped('aws/aws-sdk-php not installed'); + } + + $this->client = $this->getMockBuilder('Aws\DynamoDb\DynamoDbClient') + ->setMethods(array('formatAttributes', '__call')) + ->disableOriginalConstructor()->getMock(); + } + + public function testConstruct() + { + $this->assertInstanceOf('Monolog\Handler\DynamoDbHandler', new DynamoDbHandler($this->client, 'foo')); + } + + public function testInterface() + { + $this->assertInstanceOf('Monolog\Handler\HandlerInterface', new DynamoDbHandler($this->client, 'foo')); + } + + public function testGetFormatter() + { + $handler = new DynamoDbHandler($this->client, 'foo'); + $this->assertInstanceOf('Monolog\Formatter\ScalarFormatter', $handler->getFormatter()); + } + + public function testHandle() + { + $record = $this->getRecord(); + $formatter = $this->getMock('Monolog\Formatter\FormatterInterface'); + $formatted = array('foo' => 1, 'bar' => 2); + $handler = new DynamoDbHandler($this->client, 'foo'); + $handler->setFormatter($formatter); + + $formatter + ->expects($this->once()) + ->method('format') + ->with($record) + ->will($this->returnValue($formatted)); + $this->client + ->expects($this->once()) + ->method('formatAttributes') + ->with($this->isType('array')) + ->will($this->returnValue($formatted)); + $this->client + ->expects($this->once()) + ->method('__call') + ->with('putItem', array(array( + 'TableName' => 'foo', + 'Item' => $formatted + ))); + + $handler->handle($record); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/ElasticSearchHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/ElasticSearchHandlerTest.php @@ -0,0 +1,239 @@ +<?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 Monolog\Formatter\ElasticaFormatter; +use Monolog\Formatter\NormalizerFormatter; +use Monolog\TestCase; +use Monolog\Logger; +use Elastica\Client; +use Elastica\Request; +use Elastica\Response; + +class ElasticSearchHandlerTest extends TestCase +{ + /** + * @var Client mock + */ + protected $client; + + /** + * @var array Default handler options + */ + protected $options = array( + 'index' => 'my_index', + 'type' => 'doc_type', + ); + + public function setUp() + { + // Elastica lib required + if (!class_exists("Elastica\Client")) { + $this->markTestSkipped("ruflin/elastica not installed"); + } + + // base mock Elastica Client object + $this->client = $this->getMockBuilder('Elastica\Client') + ->setMethods(array('addDocuments')) + ->disableOriginalConstructor() + ->getMock(); + } + + /** + * @covers Monolog\Handler\ElasticSearchHandler::write + * @covers Monolog\Handler\ElasticSearchHandler::handleBatch + * @covers Monolog\Handler\ElasticSearchHandler::bulkSend + * @covers Monolog\Handler\ElasticSearchHandler::getDefaultFormatter + */ + public function testHandle() + { + // log message + $msg = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('foo' => 7, 'bar', 'class' => new \stdClass), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + // format expected result + $formatter = new ElasticaFormatter($this->options['index'], $this->options['type']); + $expected = array($formatter->format($msg)); + + // setup ES client mock + $this->client->expects($this->any()) + ->method('addDocuments') + ->with($expected); + + // perform tests + $handler = new ElasticSearchHandler($this->client, $this->options); + $handler->handle($msg); + $handler->handleBatch(array($msg)); + } + + /** + * @covers Monolog\Handler\ElasticSearchHandler::setFormatter + */ + public function testSetFormatter() + { + $handler = new ElasticSearchHandler($this->client); + $formatter = new ElasticaFormatter('index_new', 'type_new'); + $handler->setFormatter($formatter); + $this->assertInstanceOf('Monolog\Formatter\ElasticaFormatter', $handler->getFormatter()); + $this->assertEquals('index_new', $handler->getFormatter()->getIndex()); + $this->assertEquals('type_new', $handler->getFormatter()->getType()); + } + + /** + * @covers Monolog\Handler\ElasticSearchHandler::setFormatter + * @expectedException InvalidArgumentException + * @expectedExceptionMessage ElasticSearchHandler is only compatible with ElasticaFormatter + */ + public function testSetFormatterInvalid() + { + $handler = new ElasticSearchHandler($this->client); + $formatter = new NormalizerFormatter(); + $handler->setFormatter($formatter); + } + + /** + * @covers Monolog\Handler\ElasticSearchHandler::__construct + * @covers Monolog\Handler\ElasticSearchHandler::getOptions + */ + public function testOptions() + { + $expected = array( + 'index' => $this->options['index'], + 'type' => $this->options['type'], + 'ignore_error' => false, + ); + $handler = new ElasticSearchHandler($this->client, $this->options); + $this->assertEquals($expected, $handler->getOptions()); + } + + /** + * @covers Monolog\Handler\ElasticSearchHandler::bulkSend + * @dataProvider providerTestConnectionErrors + */ + public function testConnectionErrors($ignore, $expectedError) + { + $clientOpts = array('host' => '127.0.0.1', 'port' => 1); + $client = new Client($clientOpts); + $handlerOpts = array('ignore_error' => $ignore); + $handler = new ElasticSearchHandler($client, $handlerOpts); + + if ($expectedError) { + $this->setExpectedException($expectedError[0], $expectedError[1]); + $handler->handle($this->getRecord()); + } else { + $this->assertFalse($handler->handle($this->getRecord())); + } + } + + /** + * @return array + */ + public function providerTestConnectionErrors() + { + return array( + array(false, array('RuntimeException', 'Error sending messages to Elasticsearch')), + array(true, false), + ); + } + + /** + * Integration test using localhost Elastic Search server + * + * @covers Monolog\Handler\ElasticSearchHandler::__construct + * @covers Monolog\Handler\ElasticSearchHandler::handleBatch + * @covers Monolog\Handler\ElasticSearchHandler::bulkSend + * @covers Monolog\Handler\ElasticSearchHandler::getDefaultFormatter + */ + public function testHandleIntegration() + { + $msg = array( + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => array('foo' => 7, 'bar', 'class' => new \stdClass), + 'datetime' => new \DateTime("@0"), + 'extra' => array(), + 'message' => 'log', + ); + + $expected = $msg; + $expected['datetime'] = $msg['datetime']->format(\DateTime::ISO8601); + $expected['context'] = array( + 'class' => '[object] (stdClass: {})', + 'foo' => 7, + 0 => 'bar', + ); + + $client = new Client(); + $handler = new ElasticSearchHandler($client, $this->options); + try { + $handler->handleBatch(array($msg)); + } catch (\RuntimeException $e) { + $this->markTestSkipped("Cannot connect to Elastic Search server on localhost"); + } + + // check document id from ES server response + $documentId = $this->getCreatedDocId($client->getLastResponse()); + $this->assertNotEmpty($documentId, 'No elastic document id received'); + + // retrieve document source from ES and validate + $document = $this->getDocSourceFromElastic( + $client, + $this->options['index'], + $this->options['type'], + $documentId + ); + $this->assertEquals($expected, $document); + + // remove test index from ES + $client->request("/{$this->options['index']}", Request::DELETE); + } + + /** + * Return last created document id from ES response + * @param Response $response Elastica Response object + * @return string|null + */ + protected function getCreatedDocId(Response $response) + { + $data = $response->getData(); + if (!empty($data['items'][0]['create']['_id'])) { + return $data['items'][0]['create']['_id']; + } + } + + /** + * Retrieve document by id from Elasticsearch + * @param Client $client Elastica client + * @param string $index + * @param string $type + * @param string $documentId + * @return array + */ + protected function getDocSourceFromElastic(Client $client, $index, $type, $documentId) + { + $resp = $client->request("/{$index}/{$type}/{$documentId}", Request::GET); + $data = $resp->getData(); + if (!empty($data['_source'])) { + return $data['_source']; + } + + return array(); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/ErrorLogHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/ErrorLogHandlerTest.php @@ -0,0 +1,66 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; +use Monolog\Formatter\LineFormatter; + +function error_log() +{ + $GLOBALS['error_log'][] = func_get_args(); +} + +class ErrorLogHandlerTest extends TestCase +{ + protected function setUp() + { + $GLOBALS['error_log'] = array(); + } + + /** + * @covers Monolog\Handler\ErrorLogHandler::__construct + * @expectedException InvalidArgumentException + * @expectedExceptionMessage The given message type "42" is not supported + */ + public function testShouldNotAcceptAnInvalidTypeOnContructor() + { + new ErrorLogHandler(42); + } + + /** + * @covers Monolog\Handler\ErrorLogHandler::write + */ + public function testShouldLogMessagesUsingErrorLogFuncion() + { + $type = ErrorLogHandler::OPERATING_SYSTEM; + $handler = new ErrorLogHandler($type); + $handler->setFormatter(new LineFormatter('%channel%.%level_name%: %message% %context% %extra%', null, true)); + $handler->handle($this->getRecord(Logger::ERROR, "Foo\nBar\r\n\r\nBaz")); + + $this->assertSame("test.ERROR: Foo\nBar\r\n\r\nBaz [] []", $GLOBALS['error_log'][0][0]); + $this->assertSame($GLOBALS['error_log'][0][1], $type); + + $handler = new ErrorLogHandler($type, Logger::DEBUG, true, true); + $handler->setFormatter(new LineFormatter(null, null, true)); + $handler->handle($this->getRecord(Logger::ERROR, "Foo\nBar\r\n\r\nBaz")); + + $this->assertStringMatchesFormat('[%s] test.ERROR: Foo', $GLOBALS['error_log'][1][0]); + $this->assertSame($GLOBALS['error_log'][1][1], $type); + + $this->assertStringMatchesFormat('Bar', $GLOBALS['error_log'][2][0]); + $this->assertSame($GLOBALS['error_log'][2][1], $type); + + $this->assertStringMatchesFormat('Baz [] []', $GLOBALS['error_log'][3][0]); + $this->assertSame($GLOBALS['error_log'][3][1], $type); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/FilterHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/FilterHandlerTest.php @@ -0,0 +1,170 @@ +<?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 Monolog\Logger; +use Monolog\TestCase; + +class FilterHandlerTest extends TestCase +{ + /** + * @covers Monolog\Handler\FilterHandler::isHandling + */ + public function testIsHandling() + { + $test = new TestHandler(); + $handler = new FilterHandler($test, Logger::INFO, Logger::NOTICE); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG))); + $this->assertTrue($handler->isHandling($this->getRecord(Logger::INFO))); + $this->assertTrue($handler->isHandling($this->getRecord(Logger::NOTICE))); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::WARNING))); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::ERROR))); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::CRITICAL))); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::ALERT))); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::EMERGENCY))); + } + + /** + * @covers Monolog\Handler\FilterHandler::handle + * @covers Monolog\Handler\FilterHandler::setAcceptedLevels + * @covers Monolog\Handler\FilterHandler::isHandling + */ + public function testHandleProcessOnlyNeededLevels() + { + $test = new TestHandler(); + $handler = new FilterHandler($test, Logger::INFO, Logger::NOTICE); + + $handler->handle($this->getRecord(Logger::DEBUG)); + $this->assertFalse($test->hasDebugRecords()); + + $handler->handle($this->getRecord(Logger::INFO)); + $this->assertTrue($test->hasInfoRecords()); + $handler->handle($this->getRecord(Logger::NOTICE)); + $this->assertTrue($test->hasNoticeRecords()); + + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertFalse($test->hasWarningRecords()); + $handler->handle($this->getRecord(Logger::ERROR)); + $this->assertFalse($test->hasErrorRecords()); + $handler->handle($this->getRecord(Logger::CRITICAL)); + $this->assertFalse($test->hasCriticalRecords()); + $handler->handle($this->getRecord(Logger::ALERT)); + $this->assertFalse($test->hasAlertRecords()); + $handler->handle($this->getRecord(Logger::EMERGENCY)); + $this->assertFalse($test->hasEmergencyRecords()); + + $test = new TestHandler(); + $handler = new FilterHandler($test, array(Logger::INFO, Logger::ERROR)); + + $handler->handle($this->getRecord(Logger::DEBUG)); + $this->assertFalse($test->hasDebugRecords()); + $handler->handle($this->getRecord(Logger::INFO)); + $this->assertTrue($test->hasInfoRecords()); + $handler->handle($this->getRecord(Logger::NOTICE)); + $this->assertFalse($test->hasNoticeRecords()); + $handler->handle($this->getRecord(Logger::ERROR)); + $this->assertTrue($test->hasErrorRecords()); + $handler->handle($this->getRecord(Logger::CRITICAL)); + $this->assertFalse($test->hasCriticalRecords()); + } + + /** + * @covers Monolog\Handler\FilterHandler::setAcceptedLevels + * @covers Monolog\Handler\FilterHandler::getAcceptedLevels + */ + public function testAcceptedLevelApi() + { + $test = new TestHandler(); + $handler = new FilterHandler($test); + + $levels = array(Logger::INFO, Logger::ERROR); + $handler->setAcceptedLevels($levels); + $this->assertSame($levels, $handler->getAcceptedLevels()); + + $handler->setAcceptedLevels(array('info', 'error')); + $this->assertSame($levels, $handler->getAcceptedLevels()); + + $levels = array(Logger::CRITICAL, Logger::ALERT, Logger::EMERGENCY); + $handler->setAcceptedLevels(Logger::CRITICAL, Logger::EMERGENCY); + $this->assertSame($levels, $handler->getAcceptedLevels()); + + $handler->setAcceptedLevels('critical', 'emergency'); + $this->assertSame($levels, $handler->getAcceptedLevels()); + } + + /** + * @covers Monolog\Handler\FilterHandler::handle + */ + public function testHandleUsesProcessors() + { + $test = new TestHandler(); + $handler = new FilterHandler($test, Logger::DEBUG, Logger::EMERGENCY); + $handler->pushProcessor( + function ($record) { + $record['extra']['foo'] = true; + + return $record; + } + ); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasWarningRecords()); + $records = $test->getRecords(); + $this->assertTrue($records[0]['extra']['foo']); + } + + /** + * @covers Monolog\Handler\FilterHandler::handle + */ + public function testHandleRespectsBubble() + { + $test = new TestHandler(); + + $handler = new FilterHandler($test, Logger::INFO, Logger::NOTICE, false); + $this->assertTrue($handler->handle($this->getRecord(Logger::INFO))); + $this->assertFalse($handler->handle($this->getRecord(Logger::WARNING))); + + $handler = new FilterHandler($test, Logger::INFO, Logger::NOTICE, true); + $this->assertFalse($handler->handle($this->getRecord(Logger::INFO))); + $this->assertFalse($handler->handle($this->getRecord(Logger::WARNING))); + } + + /** + * @covers Monolog\Handler\FilterHandler::handle + */ + public function testHandleWithCallback() + { + $test = new TestHandler(); + $handler = new FilterHandler( + function ($record, $handler) use ($test) { + return $test; + }, Logger::INFO, Logger::NOTICE, false + ); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $this->assertFalse($test->hasDebugRecords()); + $this->assertTrue($test->hasInfoRecords()); + } + + /** + * @covers Monolog\Handler\FilterHandler::handle + * @expectedException \RuntimeException + */ + public function testHandleWithBadCallbackThrowsException() + { + $handler = new FilterHandler( + function ($record, $handler) { + return 'foo'; + } + ); + $handler->handle($this->getRecord(Logger::WARNING)); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/FingersCrossedHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/FingersCrossedHandlerTest.php @@ -0,0 +1,240 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; +use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy; +use Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy; + +class FingersCrossedHandlerTest extends TestCase +{ + /** + * @covers Monolog\Handler\FingersCrossedHandler::__construct + * @covers Monolog\Handler\FingersCrossedHandler::handle + */ + public function testHandleBuffers() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $this->assertFalse($test->hasDebugRecords()); + $this->assertFalse($test->hasInfoRecords()); + $handler->handle($this->getRecord(Logger::WARNING)); + $handler->close(); + $this->assertTrue($test->hasInfoRecords()); + $this->assertTrue(count($test->getRecords()) === 3); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::handle + */ + public function testHandleStopsBufferingAfterTrigger() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test); + $handler->handle($this->getRecord(Logger::WARNING)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->close(); + $this->assertTrue($test->hasWarningRecords()); + $this->assertTrue($test->hasDebugRecords()); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::handle + * @covers Monolog\Handler\FingersCrossedHandler::reset + */ + public function testHandleRestartBufferingAfterReset() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test); + $handler->handle($this->getRecord(Logger::WARNING)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->reset(); + $handler->handle($this->getRecord(Logger::INFO)); + $handler->close(); + $this->assertTrue($test->hasWarningRecords()); + $this->assertTrue($test->hasDebugRecords()); + $this->assertFalse($test->hasInfoRecords()); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::handle + */ + public function testHandleRestartBufferingAfterBeingTriggeredWhenStopBufferingIsDisabled() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, Logger::WARNING, 0, false, false); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::WARNING)); + $handler->handle($this->getRecord(Logger::INFO)); + $handler->close(); + $this->assertTrue($test->hasWarningRecords()); + $this->assertTrue($test->hasDebugRecords()); + $this->assertFalse($test->hasInfoRecords()); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::handle + */ + public function testHandleBufferLimit() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, Logger::WARNING, 2); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasWarningRecords()); + $this->assertTrue($test->hasInfoRecords()); + $this->assertFalse($test->hasDebugRecords()); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::handle + */ + public function testHandleWithCallback() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler(function ($record, $handler) use ($test) { + return $test; + }); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + $this->assertFalse($test->hasDebugRecords()); + $this->assertFalse($test->hasInfoRecords()); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasInfoRecords()); + $this->assertTrue(count($test->getRecords()) === 3); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::handle + * @expectedException RuntimeException + */ + public function testHandleWithBadCallbackThrowsException() + { + $handler = new FingersCrossedHandler(function ($record, $handler) { + return 'foo'; + }); + $handler->handle($this->getRecord(Logger::WARNING)); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::isHandling + */ + public function testIsHandlingAlways() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, Logger::ERROR); + $this->assertTrue($handler->isHandling($this->getRecord(Logger::DEBUG))); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::__construct + * @covers Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy::__construct + * @covers Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy::isHandlerActivated + */ + public function testErrorLevelActivationStrategy() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, new ErrorLevelActivationStrategy(Logger::WARNING)); + $handler->handle($this->getRecord(Logger::DEBUG)); + $this->assertFalse($test->hasDebugRecords()); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasDebugRecords()); + $this->assertTrue($test->hasWarningRecords()); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::__construct + * @covers Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy::__construct + * @covers Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy::isHandlerActivated + */ + public function testErrorLevelActivationStrategyWithPsrLevel() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, new ErrorLevelActivationStrategy('warning')); + $handler->handle($this->getRecord(Logger::DEBUG)); + $this->assertFalse($test->hasDebugRecords()); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasDebugRecords()); + $this->assertTrue($test->hasWarningRecords()); + } + + /** + * @covers Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy::__construct + * @covers Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy::isHandlerActivated + */ + public function testChannelLevelActivationStrategy() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, new ChannelLevelActivationStrategy(Logger::ERROR, array('othertest' => Logger::DEBUG))); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertFalse($test->hasWarningRecords()); + $record = $this->getRecord(Logger::DEBUG); + $record['channel'] = 'othertest'; + $handler->handle($record); + $this->assertTrue($test->hasDebugRecords()); + $this->assertTrue($test->hasWarningRecords()); + } + + /** + * @covers Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy::__construct + * @covers Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy::isHandlerActivated + */ + public function testChannelLevelActivationStrategyWithPsrLevels() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, new ChannelLevelActivationStrategy('error', array('othertest' => 'debug'))); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertFalse($test->hasWarningRecords()); + $record = $this->getRecord(Logger::DEBUG); + $record['channel'] = 'othertest'; + $handler->handle($record); + $this->assertTrue($test->hasDebugRecords()); + $this->assertTrue($test->hasWarningRecords()); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::handle + */ + public function testHandleUsesProcessors() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, Logger::INFO); + $handler->pushProcessor(function ($record) { + $record['extra']['foo'] = true; + + return $record; + }); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasWarningRecords()); + $records = $test->getRecords(); + $this->assertTrue($records[0]['extra']['foo']); + } + + /** + * @covers Monolog\Handler\FingersCrossedHandler::close + */ + public function testPassthruOnClose() + { + $test = new TestHandler(); + $handler = new FingersCrossedHandler($test, new ErrorLevelActivationStrategy(Logger::WARNING), 0, true, true, Logger::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/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/FirePHPHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/FirePHPHandlerTest.php @@ -0,0 +1,96 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +/** + * @covers Monolog\Handler\FirePHPHandler + */ +class FirePHPHandlerTest extends TestCase +{ + public function setUp() + { + TestFirePHPHandler::reset(); + $_SERVER['HTTP_USER_AGENT'] = 'Monolog Test; FirePHP/1.0'; + } + + public function testHeaders() + { + $handler = new TestFirePHPHandler; + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::WARNING)); + + $expected = array( + 'X-Wf-Protocol-1' => 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2', + 'X-Wf-1-Structure-1' => 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1', + 'X-Wf-1-Plugin-1' => 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3', + 'X-Wf-1-1-1-1' => 'test', + 'X-Wf-1-1-1-2' => 'test', + ); + + $this->assertEquals($expected, $handler->getHeaders()); + } + + public function testConcurrentHandlers() + { + $handler = new TestFirePHPHandler; + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::WARNING)); + + $handler2 = new TestFirePHPHandler; + $handler2->setFormatter($this->getIdentityFormatter()); + $handler2->handle($this->getRecord(Logger::DEBUG)); + $handler2->handle($this->getRecord(Logger::WARNING)); + + $expected = array( + 'X-Wf-Protocol-1' => 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2', + 'X-Wf-1-Structure-1' => 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1', + 'X-Wf-1-Plugin-1' => 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3', + 'X-Wf-1-1-1-1' => 'test', + 'X-Wf-1-1-1-2' => 'test', + ); + + $expected2 = array( + 'X-Wf-1-1-1-3' => 'test', + 'X-Wf-1-1-1-4' => 'test', + ); + + $this->assertEquals($expected, $handler->getHeaders()); + $this->assertEquals($expected2, $handler2->getHeaders()); + } +} + +class TestFirePHPHandler extends FirePHPHandler +{ + protected $headers = array(); + + public static function reset() + { + self::$initialized = false; + self::$sendHeaders = true; + self::$messageIndex = 1; + } + + protected function sendHeader($header, $content) + { + $this->headers[$header] = $content; + } + + public function getHeaders() + { + return $this->headers; + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/Fixtures/.gitkeep b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/Fixtures/.gitkeep diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/FleepHookHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/FleepHookHandlerTest.php @@ -0,0 +1,85 @@ +<?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 Monolog\Formatter\LineFormatter; +use Monolog\Logger; +use Monolog\TestCase; + +/** + * @coversDefaultClass \Monolog\Handler\FleepHookHandler + */ +class FleepHookHandlerTest extends TestCase +{ + /** + * Default token to use in tests + */ + const TOKEN = '123abc'; + + /** + * @var FleepHookHandler + */ + private $handler; + + public function setUp() + { + parent::setUp(); + + if (!extension_loaded('openssl')) { + $this->markTestSkipped('This test requires openssl extension to run'); + } + + // Create instances of the handler and logger for convenience + $this->handler = new FleepHookHandler(self::TOKEN); + } + + /** + * @covers ::__construct + */ + public function testConstructorSetsExpectedDefaults() + { + $this->assertEquals(Logger::DEBUG, $this->handler->getLevel()); + $this->assertEquals(true, $this->handler->getBubble()); + } + + /** + * @covers ::getDefaultFormatter + */ + public function testHandlerUsesLineFormatterWhichIgnoresEmptyArrays() + { + $record = array( + 'message' => 'msg', + 'context' => array(), + 'level' => Logger::DEBUG, + 'level_name' => Logger::getLevelName(Logger::DEBUG), + 'channel' => 'channel', + 'datetime' => new \DateTime(), + 'extra' => array(), + ); + + $expectedFormatter = new LineFormatter(null, null, true, true); + $expected = $expectedFormatter->format($record); + + $handlerFormatter = $this->handler->getFormatter(); + $actual = $handlerFormatter->format($record); + + $this->assertEquals($expected, $actual, 'Empty context and extra arrays should not be rendered'); + } + + /** + * @covers ::__construct + */ + public function testConnectionStringisConstructedCorrectly() + { + $this->assertEquals('ssl://' . FleepHookHandler::FLEEP_HOST . ':443', $this->handler->getConnectionString()); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/FlowdockHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/FlowdockHandlerTest.php @@ -0,0 +1,88 @@ +<?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 Monolog\Formatter\FlowdockFormatter; +use Monolog\TestCase; +use Monolog\Logger; + +/** + * @author Dominik Liebler <liebler.dominik@gmail.com> + * @see https://www.hipchat.com/docs/api + */ +class FlowdockHandlerTest extends TestCase +{ + /** + * @var resource + */ + private $res; + + /** + * @var FlowdockHandler + */ + private $handler; + + public function setUp() + { + if (!extension_loaded('openssl')) { + $this->markTestSkipped('This test requires openssl to run'); + } + } + + public function testWriteHeader() + { + $this->createHandler(); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/POST \/v1\/messages\/team_inbox\/.* HTTP\/1.1\\r\\nHost: api.flowdock.com\\r\\nContent-Type: application\/json\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); + + return $content; + } + + /** + * @depends testWriteHeader + */ + public function testWriteContent($content) + { + $this->assertRegexp('/"source":"test_source"/', $content); + $this->assertRegexp('/"from_address":"source@test\.com"/', $content); + } + + private function createHandler($token = 'myToken') + { + $constructorArgs = array($token, Logger::DEBUG); + $this->res = fopen('php://memory', 'a'); + $this->handler = $this->getMock( + '\Monolog\Handler\FlowdockHandler', + array('fsockopen', 'streamSetTimeout', 'closeSocket'), + $constructorArgs + ); + + $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->handler, 'localhost:1234'); + + $this->handler->expects($this->any()) + ->method('fsockopen') + ->will($this->returnValue($this->res)); + $this->handler->expects($this->any()) + ->method('streamSetTimeout') + ->will($this->returnValue(true)); + $this->handler->expects($this->any()) + ->method('closeSocket') + ->will($this->returnValue(true)); + + $this->handler->setFormatter(new FlowdockFormatter('test_source', 'source@test.com')); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerLegacyTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerLegacyTest.php @@ -0,0 +1,93 @@ +<?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\Message; +use Monolog\TestCase; +use Monolog\Logger; +use Monolog\Formatter\GelfMessageFormatter; + +class GelfHandlerLegacyTest extends TestCase +{ + public function setUp() + { + if (!class_exists('Gelf\MessagePublisher') || !class_exists('Gelf\Message')) { + $this->markTestSkipped("mlehner/gelf-php not installed"); + } + } + + /** + * @covers Monolog\Handler\GelfHandler::__construct + */ + public function testConstruct() + { + $handler = new GelfHandler($this->getMessagePublisher()); + $this->assertInstanceOf('Monolog\Handler\GelfHandler', $handler); + } + + protected function getHandler($messagePublisher) + { + $handler = new GelfHandler($messagePublisher); + + return $handler; + } + + protected function getMessagePublisher() + { + return new MockMessagePublisher('localhost'); + } + + public function testDebug() + { + $messagePublisher = $this->getMessagePublisher(); + $handler = $this->getHandler($messagePublisher); + + $record = $this->getRecord(Logger::DEBUG, "A test debug message"); + $handler->handle($record); + + $this->assertEquals(7, $messagePublisher->lastMessage->getLevel()); + $this->assertEquals('test', $messagePublisher->lastMessage->getFacility()); + $this->assertEquals($record['message'], $messagePublisher->lastMessage->getShortMessage()); + $this->assertEquals(null, $messagePublisher->lastMessage->getFullMessage()); + } + + public function testWarning() + { + $messagePublisher = $this->getMessagePublisher(); + $handler = $this->getHandler($messagePublisher); + + $record = $this->getRecord(Logger::WARNING, "A test warning message"); + $handler->handle($record); + + $this->assertEquals(4, $messagePublisher->lastMessage->getLevel()); + $this->assertEquals('test', $messagePublisher->lastMessage->getFacility()); + $this->assertEquals($record['message'], $messagePublisher->lastMessage->getShortMessage()); + $this->assertEquals(null, $messagePublisher->lastMessage->getFullMessage()); + } + + public function testInjectedGelfMessageFormatter() + { + $messagePublisher = $this->getMessagePublisher(); + $handler = $this->getHandler($messagePublisher); + + $handler->setFormatter(new GelfMessageFormatter('mysystem', 'EXT', 'CTX')); + + $record = $this->getRecord(Logger::WARNING, "A test warning message"); + $record['extra']['blarg'] = 'yep'; + $record['context']['from'] = 'logger'; + $handler->handle($record); + + $this->assertEquals('mysystem', $messagePublisher->lastMessage->getHost()); + $this->assertArrayHasKey('_EXTblarg', $messagePublisher->lastMessage->toArray()); + $this->assertArrayHasKey('_CTXfrom', $messagePublisher->lastMessage->toArray()); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerTest.php @@ -0,0 +1,117 @@ +<?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\Message; +use Monolog\TestCase; +use Monolog\Logger; +use Monolog\Formatter\GelfMessageFormatter; + +class GelfHandlerTest extends TestCase +{ + public function setUp() + { + if (!class_exists('Gelf\Publisher') || !class_exists('Gelf\Message')) { + $this->markTestSkipped("graylog2/gelf-php not installed"); + } + } + + /** + * @covers Monolog\Handler\GelfHandler::__construct + */ + public function testConstruct() + { + $handler = new GelfHandler($this->getMessagePublisher()); + $this->assertInstanceOf('Monolog\Handler\GelfHandler', $handler); + } + + protected function getHandler($messagePublisher) + { + $handler = new GelfHandler($messagePublisher); + + return $handler; + } + + protected function getMessagePublisher() + { + return $this->getMock('Gelf\Publisher', array('publish'), array(), '', false); + } + + public function testDebug() + { + $record = $this->getRecord(Logger::DEBUG, "A test debug message"); + $expectedMessage = new Message(); + $expectedMessage + ->setLevel(7) + ->setFacility("test") + ->setShortMessage($record['message']) + ->setTimestamp($record['datetime']) + ; + + $messagePublisher = $this->getMessagePublisher(); + $messagePublisher->expects($this->once()) + ->method('publish') + ->with($expectedMessage); + + $handler = $this->getHandler($messagePublisher); + + $handler->handle($record); + } + + public function testWarning() + { + $record = $this->getRecord(Logger::WARNING, "A test warning message"); + $expectedMessage = new Message(); + $expectedMessage + ->setLevel(4) + ->setFacility("test") + ->setShortMessage($record['message']) + ->setTimestamp($record['datetime']) + ; + + $messagePublisher = $this->getMessagePublisher(); + $messagePublisher->expects($this->once()) + ->method('publish') + ->with($expectedMessage); + + $handler = $this->getHandler($messagePublisher); + + $handler->handle($record); + } + + public function testInjectedGelfMessageFormatter() + { + $record = $this->getRecord(Logger::WARNING, "A test warning message"); + $record['extra']['blarg'] = 'yep'; + $record['context']['from'] = 'logger'; + + $expectedMessage = new Message(); + $expectedMessage + ->setLevel(4) + ->setFacility("test") + ->setHost("mysystem") + ->setShortMessage($record['message']) + ->setTimestamp($record['datetime']) + ->setAdditional("EXTblarg", 'yep') + ->setAdditional("CTXfrom", 'logger') + ; + + $messagePublisher = $this->getMessagePublisher(); + $messagePublisher->expects($this->once()) + ->method('publish') + ->with($expectedMessage); + + $handler = $this->getHandler($messagePublisher); + $handler->setFormatter(new GelfMessageFormatter('mysystem', 'EXT', 'CTX')); + $handler->handle($record); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/GroupHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/GroupHandlerTest.php @@ -0,0 +1,89 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +class GroupHandlerTest extends TestCase +{ + /** + * @covers Monolog\Handler\GroupHandler::__construct + * @expectedException InvalidArgumentException + */ + public function testConstructorOnlyTakesHandler() + { + new GroupHandler(array(new TestHandler(), "foo")); + } + + /** + * @covers Monolog\Handler\GroupHandler::__construct + * @covers Monolog\Handler\GroupHandler::handle + */ + public function testHandle() + { + $testHandlers = array(new TestHandler(), new TestHandler()); + $handler = new GroupHandler($testHandlers); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + foreach ($testHandlers as $test) { + $this->assertTrue($test->hasDebugRecords()); + $this->assertTrue($test->hasInfoRecords()); + $this->assertTrue(count($test->getRecords()) === 2); + } + } + + /** + * @covers Monolog\Handler\GroupHandler::handleBatch + */ + public function testHandleBatch() + { + $testHandlers = array(new TestHandler(), new TestHandler()); + $handler = new GroupHandler($testHandlers); + $handler->handleBatch(array($this->getRecord(Logger::DEBUG), $this->getRecord(Logger::INFO))); + foreach ($testHandlers as $test) { + $this->assertTrue($test->hasDebugRecords()); + $this->assertTrue($test->hasInfoRecords()); + $this->assertTrue(count($test->getRecords()) === 2); + } + } + + /** + * @covers Monolog\Handler\GroupHandler::isHandling + */ + public function testIsHandling() + { + $testHandlers = array(new TestHandler(Logger::ERROR), new TestHandler(Logger::WARNING)); + $handler = new GroupHandler($testHandlers); + $this->assertTrue($handler->isHandling($this->getRecord(Logger::ERROR))); + $this->assertTrue($handler->isHandling($this->getRecord(Logger::WARNING))); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG))); + } + + /** + * @covers Monolog\Handler\GroupHandler::handle + */ + public function testHandleUsesProcessors() + { + $test = new TestHandler(); + $handler = new GroupHandler(array($test)); + $handler->pushProcessor(function ($record) { + $record['extra']['foo'] = true; + + return $record; + }); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasWarningRecords()); + $records = $test->getRecords(); + $this->assertTrue($records[0]['extra']['foo']); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/HipChatHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/HipChatHandlerTest.php @@ -0,0 +1,166 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +/** + * @author Rafael Dohms <rafael@doh.ms> + * @see https://www.hipchat.com/docs/api + */ +class HipChatHandlerTest extends TestCase +{ + private $res; + private $handler; + + public function testWriteHeader() + { + $this->createHandler(); + $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: api.hipchat.com\\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&notify=0&message=test1&message_format=text&color=red$/', $content); + } + + public function testWriteWithComplexMessage() + { + $this->createHandler(); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Backup of database "example" finished in 16 minutes.')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content); + } + + /** + * @dataProvider provideLevelColors + */ + public function testWriteWithErrorLevelsAndColors($level, $expectedColor) + { + $this->createHandler(); + $this->handler->handle($this->getRecord($level, 'Backup of database "example" finished in 16 minutes.')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/color='.$expectedColor.'/', $content); + } + + public function provideLevelColors() + { + return array( + array(Logger::DEBUG, 'gray'), + array(Logger::INFO, 'green'), + array(Logger::WARNING, 'yellow'), + array(Logger::ERROR, 'red'), + array(Logger::CRITICAL, 'red'), + array(Logger::ALERT, 'red'), + array(Logger::EMERGENCY,'red'), + array(Logger::NOTICE, 'green'), + ); + } + + /** + * @dataProvider provideBatchRecords + */ + public function testHandleBatch($records, $expectedColor) + { + $this->createHandler(); + + $this->handler->handleBatch($records); + + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/color='.$expectedColor.'/', $content); + } + + public function provideBatchRecords() + { + return array( + array( + array( + array('level' => Logger::WARNING, 'message' => 'Oh bugger!', 'level_name' => 'warning', 'datetime' => new \DateTime()), + array('level' => Logger::NOTICE, 'message' => 'Something noticeable happened.', 'level_name' => 'notice', 'datetime' => new \DateTime()), + array('level' => Logger::CRITICAL, 'message' => 'Everything is broken!', 'level_name' => 'critical', 'datetime' => new \DateTime()) + ), + 'red', + ), + array( + array( + array('level' => Logger::WARNING, 'message' => 'Oh bugger!', 'level_name' => 'warning', 'datetime' => new \DateTime()), + array('level' => Logger::NOTICE, 'message' => 'Something noticeable happened.', 'level_name' => 'notice', 'datetime' => new \DateTime()), + ), + 'yellow', + ), + array( + array( + array('level' => Logger::DEBUG, 'message' => 'Just debugging.', 'level_name' => 'debug', 'datetime' => new \DateTime()), + array('level' => Logger::NOTICE, 'message' => 'Something noticeable happened.', 'level_name' => 'notice', 'datetime' => new \DateTime()), + ), + 'green', + ), + array( + array( + array('level' => Logger::DEBUG, 'message' => 'Just debugging.', 'level_name' => 'debug', 'datetime' => new \DateTime()), + ), + 'gray', + ), + ); + } + + private function createHandler($token = 'myToken', $room = 'room1', $name = 'Monolog', $notify = false) + { + $constructorArgs = array($token, $room, $name, $notify, Logger::DEBUG); + $this->res = fopen('php://memory', 'a'); + $this->handler = $this->getMock( + '\Monolog\Handler\HipChatHandler', + array('fsockopen', 'streamSetTimeout', 'closeSocket'), + $constructorArgs + ); + + $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->handler, 'localhost:1234'); + + $this->handler->expects($this->any()) + ->method('fsockopen') + ->will($this->returnValue($this->res)); + $this->handler->expects($this->any()) + ->method('streamSetTimeout') + ->will($this->returnValue(true)); + $this->handler->expects($this->any()) + ->method('closeSocket') + ->will($this->returnValue(true)); + + $this->handler->setFormatter($this->getIdentityFormatter()); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testCreateWithTooLongName() + { + $hipChatHandler = new \Monolog\Handler\HipChatHandler('token', 'room', 'SixteenCharsHere'); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/LogEntriesHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/LogEntriesHandlerTest.php @@ -0,0 +1,84 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +/** + * @author Robert Kaufmann III <rok3@rok3.me> + */ +class LogEntriesHandlerTest extends TestCase +{ + /** + * @var resource + */ + private $res; + + /** + * @var LogEntriesHandler + */ + private $handler; + + public function testWriteContent() + { + $this->createHandler(); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Critical write test')); + + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/testToken \[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] test.CRITICAL: Critical write test/', $content); + } + + public function testWriteBatchContent() + { + $records = array( + $this->getRecord(), + $this->getRecord(), + $this->getRecord() + ); + $this->createHandler(); + $this->handler->handleBatch($records); + + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/(testToken \[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] .* \[\] \[\]\n){3}/', $content); + } + + private function createHandler() + { + $useSSL = extension_loaded('openssl'); + $args = array('testToken', $useSSL, Logger::DEBUG, true); + $this->res = fopen('php://memory', 'a'); + $this->handler = $this->getMock( + '\Monolog\Handler\LogEntriesHandler', + array('fsockopen', 'streamSetTimeout', 'closeSocket'), + $args + ); + + $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->handler, 'localhost:1234'); + + $this->handler->expects($this->any()) + ->method('fsockopen') + ->will($this->returnValue($this->res)); + $this->handler->expects($this->any()) + ->method('streamSetTimeout') + ->will($this->returnValue(true)); + $this->handler->expects($this->any()) + ->method('closeSocket') + ->will($this->returnValue(true)); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/MailHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/MailHandlerTest.php @@ -0,0 +1,75 @@ +<?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 Monolog\Logger; +use Monolog\TestCase; + +class MailHandlerTest extends TestCase +{ + /** + * @covers Monolog\Handler\MailHandler::handleBatch + */ + public function testHandleBatch() + { + $formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface'); + $formatter->expects($this->once()) + ->method('formatBatch'); // Each record is formatted + + $handler = $this->getMockForAbstractClass('Monolog\\Handler\\MailHandler'); + $handler->expects($this->once()) + ->method('send'); + $handler->expects($this->never()) + ->method('write'); // write is for individual records + + $handler->setFormatter($formatter); + + $handler->handleBatch($this->getMultipleRecords()); + } + + /** + * @covers Monolog\Handler\MailHandler::handleBatch + */ + public function testHandleBatchNotSendsMailIfMessagesAreBelowLevel() + { + $records = array( + $this->getRecord(Logger::DEBUG, 'debug message 1'), + $this->getRecord(Logger::DEBUG, 'debug message 2'), + $this->getRecord(Logger::INFO, 'information'), + ); + + $handler = $this->getMockForAbstractClass('Monolog\\Handler\\MailHandler'); + $handler->expects($this->never()) + ->method('send'); + $handler->setLevel(Logger::ERROR); + + $handler->handleBatch($records); + } + + /** + * @covers Monolog\Handler\MailHandler::write + */ + public function testHandle() + { + $handler = $this->getMockForAbstractClass('Monolog\\Handler\\MailHandler'); + + $record = $this->getRecord(); + $records = array($record); + $records[0]['formatted'] = '['.$record['datetime']->format('Y-m-d H:i:s').'] test.WARNING: test [] []'."\n"; + + $handler->expects($this->once()) + ->method('send') + ->with($records[0]['formatted'], $records); + + $handler->handle($record); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/MockRavenClient.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/MockRavenClient.php @@ -0,0 +1,26 @@ +<?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 Raven_Client; + +class MockRavenClient extends Raven_Client +{ + public function capture($data, $stack, $vars = null) + { + $this->lastData = $data; + $this->lastStack = $stack; + } + + public $lastData; + public $lastStack; +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/MongoDBHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/MongoDBHandlerTest.php @@ -0,0 +1,65 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +class MongoDBHandlerTest extends TestCase +{ + /** + * @expectedException InvalidArgumentException + */ + public function testConstructorShouldThrowExceptionForInvalidMongo() + { + new MongoDBHandler(new \stdClass(), 'DB', 'Collection'); + } + + public function testHandle() + { + $mongo = $this->getMock('Mongo', array('selectCollection'), array(), '', false); + $collection = $this->getMock('stdClass', array('save')); + + $mongo->expects($this->once()) + ->method('selectCollection') + ->with('DB', 'Collection') + ->will($this->returnValue($collection)); + + $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(), + ); + + $collection->expects($this->once()) + ->method('save') + ->with($expected); + + $handler = new MongoDBHandler($mongo, 'DB', 'Collection'); + $handler->handle($record); + } +} + +if (!class_exists('Mongo')) { + class Mongo + { + public function selectCollection() + { + } + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/NativeMailerHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/NativeMailerHandlerTest.php @@ -0,0 +1,61 @@ +<?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 Monolog\TestCase; + +class NativeMailerHandlerTest extends TestCase +{ + /** + * @expectedException InvalidArgumentException + */ + public function testConstructorHeaderInjection() + { + $mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', "receiver@example.org\r\nFrom: faked@attacker.org"); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testSetterHeaderInjection() + { + $mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', 'receiver@example.org'); + $mailer->addHeader("Content-Type: text/html\r\nFrom: faked@attacker.org"); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testSetterArrayHeaderInjection() + { + $mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', 'receiver@example.org'); + $mailer->addHeader(array("Content-Type: text/html\r\nFrom: faked@attacker.org")); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testSetterContentTypeInjection() + { + $mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', 'receiver@example.org'); + $mailer->setContentType("text/html\r\nFrom: faked@attacker.org"); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testSetterEncodingInjection() + { + $mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', 'receiver@example.org'); + $mailer->setEncoding("utf-8\r\nFrom: faked@attacker.org"); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/NewRelicHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/NewRelicHandlerTest.php @@ -0,0 +1,192 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +class NewRelicHandlerTest extends TestCase +{ + public static $appname; + public static $customParameters; + public static $transactionName; + + public function setUp() + { + self::$appname = null; + self::$customParameters = array(); + self::$transactionName = null; + } + + /** + * @expectedException Monolog\Handler\MissingExtensionException + */ + public function testThehandlerThrowsAnExceptionIfTheNRExtensionIsNotLoaded() + { + $handler = new StubNewRelicHandlerWithoutExtension(); + $handler->handle($this->getRecord(Logger::ERROR)); + } + + public function testThehandlerCanHandleTheRecord() + { + $handler = new StubNewRelicHandler(); + $handler->handle($this->getRecord(Logger::ERROR)); + } + + public function testThehandlerCanAddContextParamsToTheNewRelicTrace() + { + $handler = new StubNewRelicHandler(); + $handler->handle($this->getRecord(Logger::ERROR, 'log message', array('a' => 'b'))); + $this->assertEquals(array('context_a' => 'b'), self::$customParameters); + } + + public function testThehandlerCanAddExplodedContextParamsToTheNewRelicTrace() + { + $handler = new StubNewRelicHandler(Logger::ERROR, true, self::$appname, true); + $handler->handle($this->getRecord( + Logger::ERROR, + 'log message', + array('a' => array('key1' => 'value1', 'key2' => 'value2')) + )); + $this->assertEquals( + array('context_a_key1' => 'value1', 'context_a_key2' => 'value2'), + self::$customParameters + ); + } + + public function testThehandlerCanAddExtraParamsToTheNewRelicTrace() + { + $record = $this->getRecord(Logger::ERROR, 'log message'); + $record['extra'] = array('c' => 'd'); + + $handler = new StubNewRelicHandler(); + $handler->handle($record); + + $this->assertEquals(array('extra_c' => 'd'), self::$customParameters); + } + + public function testThehandlerCanAddExplodedExtraParamsToTheNewRelicTrace() + { + $record = $this->getRecord(Logger::ERROR, 'log message'); + $record['extra'] = array('c' => array('key1' => 'value1', 'key2' => 'value2')); + + $handler = new StubNewRelicHandler(Logger::ERROR, true, self::$appname, true); + $handler->handle($record); + + $this->assertEquals( + array('extra_c_key1' => 'value1', 'extra_c_key2' => 'value2'), + self::$customParameters + ); + } + + public function testThehandlerCanAddExtraContextAndParamsToTheNewRelicTrace() + { + $record = $this->getRecord(Logger::ERROR, 'log message', array('a' => 'b')); + $record['extra'] = array('c' => 'd'); + + $handler = new StubNewRelicHandler(); + $handler->handle($record); + + $expected = array( + 'context_a' => 'b', + 'extra_c' => 'd', + ); + + $this->assertEquals($expected, self::$customParameters); + } + + public function testTheAppNameIsNullByDefault() + { + $handler = new StubNewRelicHandler(); + $handler->handle($this->getRecord(Logger::ERROR, 'log message')); + + $this->assertEquals(null, self::$appname); + } + + public function testTheAppNameCanBeInjectedFromtheConstructor() + { + $handler = new StubNewRelicHandler(Logger::DEBUG, false, 'myAppName'); + $handler->handle($this->getRecord(Logger::ERROR, 'log message')); + + $this->assertEquals('myAppName', self::$appname); + } + + public function testTheAppNameCanBeOverriddenFromEachLog() + { + $handler = new StubNewRelicHandler(Logger::DEBUG, false, 'myAppName'); + $handler->handle($this->getRecord(Logger::ERROR, 'log message', array('appname' => 'logAppName'))); + + $this->assertEquals('logAppName', self::$appname); + } + + public function testTheTransactionNameIsNullByDefault() + { + $handler = new StubNewRelicHandler(); + $handler->handle($this->getRecord(Logger::ERROR, 'log message')); + + $this->assertEquals(null, self::$transactionName); + } + + public function testTheTransactionNameCanBeInjectedFromtheConstructor() + { + $handler = new StubNewRelicHandler(Logger::DEBUG, false, null, false, 'myTransaction'); + $handler->handle($this->getRecord(Logger::ERROR, 'log message')); + + $this->assertEquals('myTransaction', self::$transactionName); + } + + public function testTheTransactionNameCanBeOverriddenFromEachLog() + { + $handler = new StubNewRelicHandler(Logger::DEBUG, false, null, false, 'myTransaction'); + $handler->handle($this->getRecord(Logger::ERROR, 'log message', array('transaction_name' => 'logTransactName'))); + + $this->assertEquals('logTransactName', self::$transactionName); + } +} + +class StubNewRelicHandlerWithoutExtension extends NewRelicHandler +{ + protected function isNewRelicEnabled() + { + return false; + } +} + +class StubNewRelicHandler extends NewRelicHandler +{ + protected function isNewRelicEnabled() + { + return true; + } +} + +function newrelic_notice_error() +{ + return true; +} + +function newrelic_set_appname($appname) +{ + return NewRelicHandlerTest::$appname = $appname; +} + +function newrelic_name_transaction($transactionName) +{ + return NewRelicHandlerTest::$transactionName = $transactionName; +} + +function newrelic_add_custom_parameter($key, $value) +{ + NewRelicHandlerTest::$customParameters[$key] = $value; + + return true; +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/NullHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/NullHandlerTest.php @@ -0,0 +1,33 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +/** + * @covers Monolog\Handler\NullHandler::handle + */ +class NullHandlerTest extends TestCase +{ + public function testHandle() + { + $handler = new NullHandler(); + $this->assertTrue($handler->handle($this->getRecord())); + } + + public function testHandleLowerLevelRecord() + { + $handler = new NullHandler(Logger::WARNING); + $this->assertFalse($handler->handle($this->getRecord(Logger::DEBUG))); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/PsrHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/PsrHandlerTest.php @@ -0,0 +1,50 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +/** + * @covers Monolog\Handler\PsrHandler::handle + */ +class PsrHandlerTest extends TestCase +{ + public function logLevelProvider() + { + $levels = array(); + $monologLogger = new Logger(''); + + foreach ($monologLogger->getLevels() as $levelName => $level) { + $levels[] = array($levelName, $level); + } + + return $levels; + } + + /** + * @dataProvider logLevelProvider + */ + public function testHandlesAllLevels($levelName, $level) + { + $message = 'Hello, world! ' . $level; + $context = array('foo' => 'bar', 'level' => $level); + + $psrLogger = $this->getMock('Psr\Log\NullLogger'); + $psrLogger->expects($this->once()) + ->method('log') + ->with(strtolower($levelName), $message, $context); + + $handler = new PsrHandler($psrLogger); + $handler->handle(array('level' => $level, 'level_name' => $levelName, 'message' => $message, 'context' => $context)); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/PushoverHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/PushoverHandlerTest.php @@ -0,0 +1,141 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +/** + * Almost all examples (expected header, titles, messages) taken from + * https://www.pushover.net/api + * @author Sebastian Göttschkes <sebastian.goettschkes@googlemail.com> + * @see https://www.pushover.net/api + */ +class PushoverHandlerTest extends TestCase +{ + private $res; + private $handler; + + public function testWriteHeader() + { + $this->createHandler(); + $this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/POST \/1\/messages.json HTTP\/1.1\\r\\nHost: api.pushover.net\\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('/token=myToken&user=myUser&message=test1&title=Monolog&timestamp=\d{10}$/', $content); + } + + public function testWriteWithComplexTitle() + { + $this->createHandler('myToken', 'myUser', 'Backup finished - SQL1', Logger::EMERGENCY); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/title=Backup\+finished\+-\+SQL1/', $content); + } + + public function testWriteWithComplexMessage() + { + $this->createHandler(); + $this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Backup of database "example" finished in 16 minutes.')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content); + } + + public function testWriteWithTooLongMessage() + { + $message = str_pad('test', 520, 'a'); + $this->createHandler(); + $this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications + $this->handler->handle($this->getRecord(Logger::CRITICAL, $message)); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $expectedMessage = substr($message, 0, 505); + + $this->assertRegexp('/message=' . $expectedMessage . '&title/', $content); + } + + public function testWriteWithHighPriority() + { + $this->createHandler(); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog&timestamp=\d{10}&priority=1$/', $content); + } + + public function testWriteWithEmergencyPriority() + { + $this->createHandler(); + $this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog&timestamp=\d{10}&priority=2&retry=30&expire=25200$/', $content); + } + + public function testWriteToMultipleUsers() + { + $this->createHandler('myToken', array('userA', 'userB')); + $this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/token=myToken&user=userA&message=test1&title=Monolog&timestamp=\d{10}&priority=2&retry=30&expire=25200POST/', $content); + $this->assertRegexp('/token=myToken&user=userB&message=test1&title=Monolog&timestamp=\d{10}&priority=2&retry=30&expire=25200$/', $content); + } + + private function createHandler($token = 'myToken', $user = 'myUser', $title = 'Monolog') + { + $constructorArgs = array($token, $user, $title); + $this->res = fopen('php://memory', 'a'); + $this->handler = $this->getMock( + '\Monolog\Handler\PushoverHandler', + array('fsockopen', 'streamSetTimeout', 'closeSocket'), + $constructorArgs + ); + + $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->handler, 'localhost:1234'); + + $this->handler->expects($this->any()) + ->method('fsockopen') + ->will($this->returnValue($this->res)); + $this->handler->expects($this->any()) + ->method('streamSetTimeout') + ->will($this->returnValue(true)); + $this->handler->expects($this->any()) + ->method('closeSocket') + ->will($this->returnValue(true)); + + $this->handler->setFormatter($this->getIdentityFormatter()); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/RavenHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/RavenHandlerTest.php @@ -0,0 +1,150 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; +use Monolog\Formatter\LineFormatter; + +class RavenHandlerTest extends TestCase +{ + public function setUp() + { + if (!class_exists("Raven_Client")) { + $this->markTestSkipped("raven/raven not installed"); + } + + require_once __DIR__ . '/MockRavenClient.php'; + } + + /** + * @covers Monolog\Handler\RavenHandler::__construct + */ + public function testConstruct() + { + $handler = new RavenHandler($this->getRavenClient()); + $this->assertInstanceOf('Monolog\Handler\RavenHandler', $handler); + } + + protected function getHandler($ravenClient) + { + $handler = new RavenHandler($ravenClient); + + return $handler; + } + + protected function getRavenClient() + { + $dsn = 'http://43f6017361224d098402974103bfc53d:a6a0538fc2934ba2bed32e08741b2cd3@marca.python.live.cheggnet.com:9000/1'; + + return new MockRavenClient($dsn); + } + + public function testDebug() + { + $ravenClient = $this->getRavenClient(); + $handler = $this->getHandler($ravenClient); + + $record = $this->getRecord(Logger::DEBUG, "A test debug message"); + $handler->handle($record); + + $this->assertEquals($ravenClient::DEBUG, $ravenClient->lastData['level']); + $this->assertContains($record['message'], $ravenClient->lastData['message']); + } + + public function testWarning() + { + $ravenClient = $this->getRavenClient(); + $handler = $this->getHandler($ravenClient); + + $record = $this->getRecord(Logger::WARNING, "A test warning message"); + $handler->handle($record); + + $this->assertEquals($ravenClient::WARNING, $ravenClient->lastData['level']); + $this->assertContains($record['message'], $ravenClient->lastData['message']); + } + + public function testTag() + { + $ravenClient = $this->getRavenClient(); + $handler = $this->getHandler($ravenClient); + + $tags = array(1, 2, 'foo'); + $record = $this->getRecord(Logger::INFO, "test", array('tags' => $tags)); + $handler->handle($record); + + $this->assertEquals($tags, $ravenClient->lastData['tags']); + } + + public function testException() + { + $ravenClient = $this->getRavenClient(); + $handler = $this->getHandler($ravenClient); + + try { + $this->methodThatThrowsAnException(); + } catch (\Exception $e) { + $record = $this->getRecord(Logger::ERROR, $e->getMessage(), array('exception' => $e)); + $handler->handle($record); + } + + $this->assertEquals($record['message'], $ravenClient->lastData['message']); + } + + public function testHandleBatch() + { + $records = $this->getMultipleRecords(); + $records[] = $this->getRecord(Logger::WARNING, 'warning'); + $records[] = $this->getRecord(Logger::WARNING, 'warning'); + + $logFormatter = $this->getMock('Monolog\\Formatter\\FormatterInterface'); + $logFormatter->expects($this->once())->method('formatBatch'); + + $formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface'); + $formatter->expects($this->once())->method('format')->with($this->callback(function ($record) { + return $record['level'] == 400; + })); + + $handler = $this->getHandler($this->getRavenClient()); + $handler->setBatchFormatter($logFormatter); + $handler->setFormatter($formatter); + $handler->handleBatch($records); + } + + public function testHandleBatchDoNothingIfRecordsAreBelowLevel() + { + $records = array( + $this->getRecord(Logger::DEBUG, 'debug message 1'), + $this->getRecord(Logger::DEBUG, 'debug message 2'), + $this->getRecord(Logger::INFO, 'information'), + ); + + $handler = $this->getMock('Monolog\Handler\RavenHandler', null, array($this->getRavenClient())); + $handler->expects($this->never())->method('handle'); + $handler->setLevel(Logger::ERROR); + $handler->handleBatch($records); + } + + public function testGetSetBatchFormatter() + { + $ravenClient = $this->getRavenClient(); + $handler = $this->getHandler($ravenClient); + + $handler->setBatchFormatter($formatter = new LineFormatter()); + $this->assertSame($formatter, $handler->getBatchFormatter()); + } + + private function methodThatThrowsAnException() + { + throw new \Exception('This is an exception'); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/RedisHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/RedisHandlerTest.php @@ -0,0 +1,71 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; +use Monolog\Formatter\LineFormatter; + +class RedisHandlerTest extends TestCase +{ + /** + * @expectedException InvalidArgumentException + */ + public function testConstructorShouldThrowExceptionForInvalidRedis() + { + new RedisHandler(new \stdClass(), 'key'); + } + + public function testConstructorShouldWorkWithPredis() + { + $redis = $this->getMock('Predis\Client'); + $this->assertInstanceof('Monolog\Handler\RedisHandler', new RedisHandler($redis, 'key')); + } + + public function testConstructorShouldWorkWithRedis() + { + $redis = $this->getMock('Redis'); + $this->assertInstanceof('Monolog\Handler\RedisHandler', new RedisHandler($redis, 'key')); + } + + public function testPredisHandle() + { + $redis = $this->getMock('Predis\Client', array('rpush')); + + // Predis\Client uses rpush + $redis->expects($this->once()) + ->method('rpush') + ->with('key', 'test'); + + $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); + + $handler = new RedisHandler($redis, 'key'); + $handler->setFormatter(new LineFormatter("%message%")); + $handler->handle($record); + } + + public function testRedisHandle() + { + $redis = $this->getMock('Redis', array('rpush')); + + // Redis uses rPush + $redis->expects($this->once()) + ->method('rPush') + ->with('key', 'test'); + + $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); + + $handler = new RedisHandler($redis, 'key'); + $handler->setFormatter(new LineFormatter("%message%")); + $handler->handle($record); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/RotatingFileHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/RotatingFileHandlerTest.php @@ -0,0 +1,99 @@ +<?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 Monolog\TestCase; + +/** + * @covers Monolog\Handler\RotatingFileHandler + */ +class RotatingFileHandlerTest extends TestCase +{ + public function setUp() + { + $dir = __DIR__.'/Fixtures'; + chmod($dir, 0777); + if (!is_writable($dir)) { + $this->markTestSkipped($dir.' must be writeable to test the RotatingFileHandler.'); + } + } + + public function testRotationCreatesNewFile() + { + touch(__DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400).'.rot'); + + $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot'); + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord()); + + $log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot'; + $this->assertTrue(file_exists($log)); + $this->assertEquals('test', file_get_contents($log)); + } + + /** + * @dataProvider rotationTests + */ + public function testRotation($createFile) + { + touch($old1 = __DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400).'.rot'); + touch($old2 = __DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400 * 2).'.rot'); + touch($old3 = __DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400 * 3).'.rot'); + touch($old4 = __DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400 * 4).'.rot'); + + $log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot'; + + if ($createFile) { + touch($log); + } + + $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot', 2); + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord()); + + $handler->close(); + + $this->assertTrue(file_exists($log)); + $this->assertTrue(file_exists($old1)); + $this->assertEquals($createFile, file_exists($old2)); + $this->assertEquals($createFile, file_exists($old3)); + $this->assertEquals($createFile, file_exists($old4)); + $this->assertEquals('test', file_get_contents($log)); + } + + public function rotationTests() + { + return array( + 'Rotation is triggered when the file of the current day is not present' + => array(true), + 'Rotation is not triggered when the file is already present' + => array(false), + ); + } + + public function testReuseCurrentFile() + { + $log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot'; + file_put_contents($log, "foo"); + $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot'); + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord()); + $this->assertEquals('footest', file_get_contents($log)); + } + + public function tearDown() + { + foreach (glob(__DIR__.'/Fixtures/*.rot') as $file) { + unlink($file); + } + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/SamplingHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/SamplingHandlerTest.php @@ -0,0 +1,33 @@ +<?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 Monolog\TestCase; + +/** + * @covers Monolog\Handler\SamplingHandler::handle + */ +class SamplingHandlerTest extends TestCase +{ + public function testHandle() + { + $testHandler = new TestHandler(); + $handler = new SamplingHandler($testHandler, 2); + for ($i = 0; $i < 10000; $i++) { + $handler->handle($this->getRecord()); + } + $count = count($testHandler->getRecords()); + // $count should be half of 10k, so between 4k and 6k + $this->assertLessThan(6000, $count); + $this->assertGreaterThan(4000, $count); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/SlackHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/SlackHandlerTest.php @@ -0,0 +1,133 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +/** + * @author Greg Kedzierski <greg@gregkedzierski.com> + * @see https://api.slack.com/ + */ +class SlackHandlerTest extends TestCase +{ + /** + * @var resource + */ + private $res; + + /** + * @var SlackHandler + */ + private $handler; + + public function setUp() + { + if (!extension_loaded('openssl')) { + $this->markTestSkipped('This test requires openssl to run'); + } + } + + public function testWriteHeader() + { + $this->createHandler(); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/POST \/api\/chat.postMessage HTTP\/1.1\\r\\nHost: slack.com\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); + } + + public function testWriteContent() + { + $this->createHandler(); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/token=myToken&channel=channel1&username=Monolog&text=&attachments=.*$/', $content); + } + + public function testWriteContentWithEmoji() + { + $this->createHandler('myToken', 'channel1', 'Monolog', true, 'alien'); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/icon_emoji=%3Aalien%3A$/', $content); + } + + /** + * @dataProvider provideLevelColors + */ + public function testWriteContentWithColors($level, $expectedColor) + { + $this->createHandler(); + $this->handler->handle($this->getRecord($level, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/color%22%3A%22'.$expectedColor.'/', $content); + } + + public function testWriteContentWithPlainTextMessage() + { + $this->createHandler('myToken', 'channel1', 'Monolog', false); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + fseek($this->res, 0); + $content = fread($this->res, 1024); + + $this->assertRegexp('/text=test1/', $content); + } + + public function provideLevelColors() + { + return array( + array(Logger::DEBUG, '%23e3e4e6'), // escaped #e3e4e6 + array(Logger::INFO, 'good'), + array(Logger::NOTICE, 'good'), + array(Logger::WARNING, 'warning'), + array(Logger::ERROR, 'danger'), + array(Logger::CRITICAL, 'danger'), + array(Logger::ALERT, 'danger'), + array(Logger::EMERGENCY,'danger'), + ); + } + + private function createHandler($token = 'myToken', $channel = 'channel1', $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $useShortAttachment = false, $includeExtra = false) + { + $constructorArgs = array($token, $channel, $username, $useAttachment, $iconEmoji, Logger::DEBUG, true, $useShortAttachment, $includeExtra); + $this->res = fopen('php://memory', 'a'); + $this->handler = $this->getMock( + '\Monolog\Handler\SlackHandler', + array('fsockopen', 'streamSetTimeout', 'closeSocket'), + $constructorArgs + ); + + $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->handler, 'localhost:1234'); + + $this->handler->expects($this->any()) + ->method('fsockopen') + ->will($this->returnValue($this->res)); + $this->handler->expects($this->any()) + ->method('streamSetTimeout') + ->will($this->returnValue(true)); + $this->handler->expects($this->any()) + ->method('closeSocket') + ->will($this->returnValue(true)); + + $this->handler->setFormatter($this->getIdentityFormatter()); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/SocketHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/SocketHandlerTest.php @@ -0,0 +1,282 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +/** + * @author Pablo de Leon Belloc <pablolb@gmail.com> + */ +class SocketHandlerTest extends TestCase +{ + /** + * @var Monolog\Handler\SocketHandler + */ + private $handler; + + /** + * @var resource + */ + private $res; + + /** + * @expectedException UnexpectedValueException + */ + public function testInvalidHostname() + { + $this->createHandler('garbage://here'); + $this->writeRecord('data'); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testBadConnectionTimeout() + { + $this->createHandler('localhost:1234'); + $this->handler->setConnectionTimeout(-1); + } + + public function testSetConnectionTimeout() + { + $this->createHandler('localhost:1234'); + $this->handler->setConnectionTimeout(10.1); + $this->assertEquals(10.1, $this->handler->getConnectionTimeout()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testBadTimeout() + { + $this->createHandler('localhost:1234'); + $this->handler->setTimeout(-1); + } + + public function testSetTimeout() + { + $this->createHandler('localhost:1234'); + $this->handler->setTimeout(10.25); + $this->assertEquals(10.25, $this->handler->getTimeout()); + } + + public function testSetConnectionString() + { + $this->createHandler('tcp://localhost:9090'); + $this->assertEquals('tcp://localhost:9090', $this->handler->getConnectionString()); + } + + /** + * @expectedException UnexpectedValueException + */ + public function testExceptionIsThrownOnFsockopenError() + { + $this->setMockHandler(array('fsockopen')); + $this->handler->expects($this->once()) + ->method('fsockopen') + ->will($this->returnValue(false)); + $this->writeRecord('Hello world'); + } + + /** + * @expectedException UnexpectedValueException + */ + public function testExceptionIsThrownOnPfsockopenError() + { + $this->setMockHandler(array('pfsockopen')); + $this->handler->expects($this->once()) + ->method('pfsockopen') + ->will($this->returnValue(false)); + $this->handler->setPersistent(true); + $this->writeRecord('Hello world'); + } + + /** + * @expectedException UnexpectedValueException + */ + public function testExceptionIsThrownIfCannotSetTimeout() + { + $this->setMockHandler(array('streamSetTimeout')); + $this->handler->expects($this->once()) + ->method('streamSetTimeout') + ->will($this->returnValue(false)); + $this->writeRecord('Hello world'); + } + + /** + * @expectedException RuntimeException + */ + public function testWriteFailsOnIfFwriteReturnsFalse() + { + $this->setMockHandler(array('fwrite')); + + $callback = function ($arg) { + $map = array( + 'Hello world' => 6, + 'world' => false, + ); + + return $map[$arg]; + }; + + $this->handler->expects($this->exactly(2)) + ->method('fwrite') + ->will($this->returnCallback($callback)); + + $this->writeRecord('Hello world'); + } + + /** + * @expectedException RuntimeException + */ + public function testWriteFailsIfStreamTimesOut() + { + $this->setMockHandler(array('fwrite', 'streamGetMetadata')); + + $callback = function ($arg) { + $map = array( + 'Hello world' => 6, + 'world' => 5, + ); + + return $map[$arg]; + }; + + $this->handler->expects($this->exactly(1)) + ->method('fwrite') + ->will($this->returnCallback($callback)); + $this->handler->expects($this->exactly(1)) + ->method('streamGetMetadata') + ->will($this->returnValue(array('timed_out' => true))); + + $this->writeRecord('Hello world'); + } + + /** + * @expectedException RuntimeException + */ + public function testWriteFailsOnIncompleteWrite() + { + $this->setMockHandler(array('fwrite', 'streamGetMetadata')); + + $res = $this->res; + $callback = function ($string) use ($res) { + fclose($res); + + return strlen('Hello'); + }; + + $this->handler->expects($this->exactly(1)) + ->method('fwrite') + ->will($this->returnCallback($callback)); + $this->handler->expects($this->exactly(1)) + ->method('streamGetMetadata') + ->will($this->returnValue(array('timed_out' => false))); + + $this->writeRecord('Hello world'); + } + + public function testWriteWithMemoryFile() + { + $this->setMockHandler(); + $this->writeRecord('test1'); + $this->writeRecord('test2'); + $this->writeRecord('test3'); + fseek($this->res, 0); + $this->assertEquals('test1test2test3', fread($this->res, 1024)); + } + + public function testWriteWithMock() + { + $this->setMockHandler(array('fwrite')); + + $callback = function ($arg) { + $map = array( + 'Hello world' => 6, + 'world' => 5, + ); + + return $map[$arg]; + }; + + $this->handler->expects($this->exactly(2)) + ->method('fwrite') + ->will($this->returnCallback($callback)); + + $this->writeRecord('Hello world'); + } + + public function testClose() + { + $this->setMockHandler(); + $this->writeRecord('Hello world'); + $this->assertInternalType('resource', $this->res); + $this->handler->close(); + $this->assertFalse(is_resource($this->res), "Expected resource to be closed after closing handler"); + } + + public function testCloseDoesNotClosePersistentSocket() + { + $this->setMockHandler(); + $this->handler->setPersistent(true); + $this->writeRecord('Hello world'); + $this->assertTrue(is_resource($this->res)); + $this->handler->close(); + $this->assertTrue(is_resource($this->res)); + } + + private function createHandler($connectionString) + { + $this->handler = new SocketHandler($connectionString); + $this->handler->setFormatter($this->getIdentityFormatter()); + } + + private function writeRecord($string) + { + $this->handler->handle($this->getRecord(Logger::WARNING, $string)); + } + + private function setMockHandler(array $methods = array()) + { + $this->res = fopen('php://memory', 'a'); + + $defaultMethods = array('fsockopen', 'pfsockopen', 'streamSetTimeout'); + $newMethods = array_diff($methods, $defaultMethods); + + $finalMethods = array_merge($defaultMethods, $newMethods); + + $this->handler = $this->getMock( + '\Monolog\Handler\SocketHandler', $finalMethods, array('localhost:1234') + ); + + if (!in_array('fsockopen', $methods)) { + $this->handler->expects($this->any()) + ->method('fsockopen') + ->will($this->returnValue($this->res)); + } + + if (!in_array('pfsockopen', $methods)) { + $this->handler->expects($this->any()) + ->method('pfsockopen') + ->will($this->returnValue($this->res)); + } + + if (!in_array('streamSetTimeout', $methods)) { + $this->handler->expects($this->any()) + ->method('streamSetTimeout') + ->will($this->returnValue(true)); + } + + $this->handler->setFormatter($this->getIdentityFormatter()); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/StreamHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/StreamHandlerTest.php @@ -0,0 +1,118 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +class StreamHandlerTest extends TestCase +{ + /** + * @covers Monolog\Handler\StreamHandler::__construct + * @covers Monolog\Handler\StreamHandler::write + */ + public function testWrite() + { + $handle = fopen('php://memory', 'a+'); + $handler = new StreamHandler($handle); + $handler->setFormatter($this->getIdentityFormatter()); + $handler->handle($this->getRecord(Logger::WARNING, 'test')); + $handler->handle($this->getRecord(Logger::WARNING, 'test2')); + $handler->handle($this->getRecord(Logger::WARNING, 'test3')); + fseek($handle, 0); + $this->assertEquals('testtest2test3', fread($handle, 100)); + } + + /** + * @covers Monolog\Handler\StreamHandler::close + */ + public function testClose() + { + $handle = fopen('php://memory', 'a+'); + $handler = new StreamHandler($handle); + $this->assertTrue(is_resource($handle)); + $handler->close(); + $this->assertFalse(is_resource($handle)); + } + + /** + * @covers Monolog\Handler\StreamHandler::write + */ + public function testWriteCreatesTheStreamResource() + { + $handler = new StreamHandler('php://memory'); + $handler->handle($this->getRecord()); + } + + /** + * @covers Monolog\Handler\StreamHandler::__construct + * @covers Monolog\Handler\StreamHandler::write + */ + public function testWriteLocking() + { + $temp = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'monolog_locked_log'; + $handler = new StreamHandler($temp, Logger::DEBUG, true, null, true); + $handler->handle($this->getRecord()); + } + + /** + * @expectedException LogicException + * @covers Monolog\Handler\StreamHandler::__construct + * @covers Monolog\Handler\StreamHandler::write + */ + public function testWriteMissingResource() + { + $handler = new StreamHandler(null); + $handler->handle($this->getRecord()); + } + + public function invalidArgumentProvider() + { + return array( + array(1), + array(array()), + array(array('bogus://url')), + ); + } + + /** + * @dataProvider invalidArgumentProvider + * @expectedException InvalidArgumentException + * @covers Monolog\Handler\StreamHandler::__construct + */ + public function testWriteInvalidArgument($invalidArgument) + { + $handler = new StreamHandler($invalidArgument); + } + + /** + * @expectedException UnexpectedValueException + * @covers Monolog\Handler\StreamHandler::__construct + * @covers Monolog\Handler\StreamHandler::write + */ + public function testWriteInvalidResource() + { + $handler = new StreamHandler('bogus://url'); + $handler->handle($this->getRecord()); + } + + /** + * @expectedException UnexpectedValueException + * @covers Monolog\Handler\StreamHandler::__construct + * @covers Monolog\Handler\StreamHandler::write + */ + public function testWriteNonExistingResource() + { + $handler = new StreamHandler('/foo/bar/baz/'.rand(0, 10000)); + $handler->handle($this->getRecord()); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/SyslogHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/SyslogHandlerTest.php @@ -0,0 +1,44 @@ +<?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 Monolog\Logger; + +class SyslogHandlerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Monolog\Handler\SyslogHandler::__construct + */ + public function testConstruct() + { + $handler = new SyslogHandler('test'); + $this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler); + + $handler = new SyslogHandler('test', LOG_USER); + $this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler); + + $handler = new SyslogHandler('test', 'user'); + $this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler); + + $handler = new SyslogHandler('test', LOG_USER, Logger::DEBUG, true, LOG_PERROR); + $this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler); + } + + /** + * @covers Monolog\Handler\SyslogHandler::__construct + */ + public function testConstructInvalidFacility() + { + $this->setExpectedException('UnexpectedValueException'); + $handler = new SyslogHandler('test', 'unknown'); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/SyslogUdpHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/SyslogUdpHandlerTest.php @@ -0,0 +1,49 @@ +<?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; + +/** + * @requires extension sockets + */ +class SyslogUdpHandlerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @expectedException UnexpectedValueException + */ + public function testWeValidateFacilities() + { + $handler = new SyslogUdpHandler("ip", null, "invalidFacility"); + } + + public function testWeSplitIntoLines() + { + $handler = new SyslogUdpHandler("127.0.0.1", 514, "authpriv"); + $handler->setFormatter(new \Monolog\Formatter\ChromePHPFormatter()); + + $socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('write'), array('lol', 'lol')); + $socket->expects($this->at(0)) + ->method('write') + ->with("lol", "<".(LOG_AUTHPRIV + LOG_WARNING).">1 "); + $socket->expects($this->at(1)) + ->method('write') + ->with("hej", "<".(LOG_AUTHPRIV + LOG_WARNING).">1 "); + + $handler->setSocket($socket); + + $handler->handle($this->getRecordWithMessage("hej\nlol")); + } + + protected function getRecordWithMessage($msg) + { + return array('message' => $msg, 'level' => \Monolog\Logger::WARNING, 'context' => null, 'extra' => array(), 'channel' => 'lol'); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/TestHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/TestHandlerTest.php @@ -0,0 +1,56 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +/** + * @covers Monolog\Handler\TestHandler + */ +class TestHandlerTest extends TestCase +{ + /** + * @dataProvider methodProvider + */ + public function testHandler($method, $level) + { + $handler = new TestHandler; + $record = $this->getRecord($level, 'test'.$method); + $this->assertFalse($handler->{'has'.$method}($record)); + $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.'Records'}()); + + $records = $handler->getRecords(); + unset($records[0]['formatted']); + $this->assertEquals(array($record), $records); + } + + public function methodProvider() + { + return array( + array('Emergency', Logger::EMERGENCY), + array('Alert' , Logger::ALERT), + array('Critical' , Logger::CRITICAL), + array('Error' , Logger::ERROR), + array('Warning' , Logger::WARNING), + array('Info' , Logger::INFO), + array('Notice' , Logger::NOTICE), + array('Debug' , Logger::DEBUG), + ); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/UdpSocketTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/UdpSocketTest.php @@ -0,0 +1,46 @@ +<?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 Monolog\TestCase; + +/** + * @requires extension sockets + */ +class UdpSocketTest extends TestCase +{ + public function testWeDoNotTruncateShortMessages() + { + $socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('send'), array('lol', 'lol')); + + $socket->expects($this->at(0)) + ->method('send') + ->with("HEADER: The quick brown fox jumps over the lazy dog"); + + $socket->write("The quick brown fox jumps over the lazy dog", "HEADER: "); + } + + public function testLongMessagesAreTruncated() + { + $socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('send'), array('lol', 'lol')); + + $truncatedString = str_repeat("derp", 16254).'d'; + + $socket->expects($this->exactly(1)) + ->method('send') + ->with("HEADER" . $truncatedString); + + $longString = str_repeat("derp", 20000); + + $socket->write($longString, "HEADER"); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/WhatFailureGroupHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/WhatFailureGroupHandlerTest.php @@ -0,0 +1,121 @@ +<?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 Monolog\TestCase; +use Monolog\Logger; + +class WhatFailureGroupHandlerTest extends TestCase +{ + /** + * @covers Monolog\Handler\WhatFailureGroupHandler::__construct + * @expectedException InvalidArgumentException + */ + public function testConstructorOnlyTakesHandler() + { + new WhatFailureGroupHandler(array(new TestHandler(), "foo")); + } + + /** + * @covers Monolog\Handler\WhatFailureGroupHandler::__construct + * @covers Monolog\Handler\WhatFailureGroupHandler::handle + */ + public function testHandle() + { + $testHandlers = array(new TestHandler(), new TestHandler()); + $handler = new WhatFailureGroupHandler($testHandlers); + $handler->handle($this->getRecord(Logger::DEBUG)); + $handler->handle($this->getRecord(Logger::INFO)); + foreach ($testHandlers as $test) { + $this->assertTrue($test->hasDebugRecords()); + $this->assertTrue($test->hasInfoRecords()); + $this->assertTrue(count($test->getRecords()) === 2); + } + } + + /** + * @covers Monolog\Handler\WhatFailureGroupHandler::handleBatch + */ + public function testHandleBatch() + { + $testHandlers = array(new TestHandler(), new TestHandler()); + $handler = new WhatFailureGroupHandler($testHandlers); + $handler->handleBatch(array($this->getRecord(Logger::DEBUG), $this->getRecord(Logger::INFO))); + foreach ($testHandlers as $test) { + $this->assertTrue($test->hasDebugRecords()); + $this->assertTrue($test->hasInfoRecords()); + $this->assertTrue(count($test->getRecords()) === 2); + } + } + + /** + * @covers Monolog\Handler\WhatFailureGroupHandler::isHandling + */ + public function testIsHandling() + { + $testHandlers = array(new TestHandler(Logger::ERROR), new TestHandler(Logger::WARNING)); + $handler = new WhatFailureGroupHandler($testHandlers); + $this->assertTrue($handler->isHandling($this->getRecord(Logger::ERROR))); + $this->assertTrue($handler->isHandling($this->getRecord(Logger::WARNING))); + $this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG))); + } + + /** + * @covers Monolog\Handler\WhatFailureGroupHandler::handle + */ + public function testHandleUsesProcessors() + { + $test = new TestHandler(); + $handler = new WhatFailureGroupHandler(array($test)); + $handler->pushProcessor(function ($record) { + $record['extra']['foo'] = true; + + return $record; + }); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasWarningRecords()); + $records = $test->getRecords(); + $this->assertTrue($records[0]['extra']['foo']); + } + + /** + * @covers Monolog\Handler\WhatFailureGroupHandler::handle + */ + public function testHandleException() + { + $test = new TestHandler(); + $exception = new ExceptionTestHandler(); + $handler = new WhatFailureGroupHandler(array($exception, $test, $exception)); + $handler->pushProcessor(function ($record) { + $record['extra']['foo'] = true; + + return $record; + }); + $handler->handle($this->getRecord(Logger::WARNING)); + $this->assertTrue($test->hasWarningRecords()); + $records = $test->getRecords(); + $this->assertTrue($records[0]['extra']['foo']); + } +} + +class ExceptionTestHandler extends TestHandler +{ + /** + * {@inheritdoc} + */ + public function handle(array $record) + { + parent::handle($record); + + throw new \Exception("ExceptionTestHandler::handle"); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/ZendMonitorHandlerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Handler/ZendMonitorHandlerTest.php @@ -0,0 +1,69 @@ +<?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 Monolog\TestCase; + +class ZendMonitorHandlerTest extends TestCase +{ + protected $zendMonitorHandler; + + public function setUp() + { + if (!function_exists('zend_monitor_custom_event')) { + $this->markTestSkipped('ZendServer is not installed'); + } + } + + /** + * @covers Monolog\Handler\ZendMonitorHandler::write + */ + public function testWrite() + { + $record = $this->getRecord(); + $formatterResult = array( + 'message' => $record['message'] + ); + + $zendMonitor = $this->getMockBuilder('Monolog\Handler\ZendMonitorHandler') + ->setMethods(array('writeZendMonitorCustomEvent', 'getDefaultFormatter')) + ->getMock(); + + $formatterMock = $this->getMockBuilder('Monolog\Formatter\NormalizerFormatter') + ->disableOriginalConstructor() + ->getMock(); + + $formatterMock->expects($this->once()) + ->method('format') + ->will($this->returnValue($formatterResult)); + + $zendMonitor->expects($this->once()) + ->method('getDefaultFormatter') + ->will($this->returnValue($formatterMock)); + + $levelMap = $zendMonitor->getLevelMap(); + + $zendMonitor->expects($this->once()) + ->method('writeZendMonitorCustomEvent') + ->with($levelMap[$record['level']], $record['message'], $formatterResult); + + $zendMonitor->handle($record); + } + + /** + * @covers Monolog\Handler\ZendMonitorHandler::getDefaultFormatter + */ + public function testGetDefaultFormatterReturnsNormalizerFormatter() + { + $zendMonitor = new ZendMonitorHandler(); + $this->assertInstanceOf('Monolog\Formatter\NormalizerFormatter', $zendMonitor->getDefaultFormatter()); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/LoggerTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/LoggerTest.php @@ -0,0 +1,409 @@ +<?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; + +use Monolog\Processor\WebProcessor; +use Monolog\Handler\TestHandler; + +class LoggerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @covers Monolog\Logger::getName + */ + public function testGetName() + { + $logger = new Logger('foo'); + $this->assertEquals('foo', $logger->getName()); + } + + /** + * @covers Monolog\Logger::getLevelName + */ + public function testGetLevelName() + { + $this->assertEquals('ERROR', Logger::getLevelName(Logger::ERROR)); + } + + /** + * @covers Monolog\Logger::getLevelName + * @expectedException InvalidArgumentException + */ + public function testGetLevelNameThrows() + { + Logger::getLevelName(5); + } + + /** + * @covers Monolog\Logger::__construct + */ + public function testChannel() + { + $logger = new Logger('foo'); + $handler = new TestHandler; + $logger->pushHandler($handler); + $logger->addWarning('test'); + list($record) = $handler->getRecords(); + $this->assertEquals('foo', $record['channel']); + } + + /** + * @covers Monolog\Logger::addRecord + */ + public function testLog() + { + $logger = new Logger(__METHOD__); + + $handler = $this->getMock('Monolog\Handler\NullHandler', array('handle')); + $handler->expects($this->once()) + ->method('handle'); + $logger->pushHandler($handler); + + $this->assertTrue($logger->addWarning('test')); + } + + /** + * @covers Monolog\Logger::addRecord + */ + public function testLogNotHandled() + { + $logger = new Logger(__METHOD__); + + $handler = $this->getMock('Monolog\Handler\NullHandler', array('handle'), array(Logger::ERROR)); + $handler->expects($this->never()) + ->method('handle'); + $logger->pushHandler($handler); + + $this->assertFalse($logger->addWarning('test')); + } + + public function testHandlersInCtor() + { + $handler1 = new TestHandler; + $handler2 = new TestHandler; + $logger = new Logger(__METHOD__, array($handler1, $handler2)); + + $this->assertEquals($handler1, $logger->popHandler()); + $this->assertEquals($handler2, $logger->popHandler()); + } + + public function testProcessorsInCtor() + { + $processor1 = new WebProcessor; + $processor2 = new WebProcessor; + $logger = new Logger(__METHOD__, array(), array($processor1, $processor2)); + + $this->assertEquals($processor1, $logger->popProcessor()); + $this->assertEquals($processor2, $logger->popProcessor()); + } + + /** + * @covers Monolog\Logger::pushHandler + * @covers Monolog\Logger::popHandler + * @expectedException LogicException + */ + public function testPushPopHandler() + { + $logger = new Logger(__METHOD__); + $handler1 = new TestHandler; + $handler2 = new TestHandler; + + $logger->pushHandler($handler1); + $logger->pushHandler($handler2); + + $this->assertEquals($handler2, $logger->popHandler()); + $this->assertEquals($handler1, $logger->popHandler()); + $logger->popHandler(); + } + + /** + * @covers Monolog\Logger::pushProcessor + * @covers Monolog\Logger::popProcessor + * @expectedException LogicException + */ + public function testPushPopProcessor() + { + $logger = new Logger(__METHOD__); + $processor1 = new WebProcessor; + $processor2 = new WebProcessor; + + $logger->pushProcessor($processor1); + $logger->pushProcessor($processor2); + + $this->assertEquals($processor2, $logger->popProcessor()); + $this->assertEquals($processor1, $logger->popProcessor()); + $logger->popProcessor(); + } + + /** + * @covers Monolog\Logger::pushProcessor + * @expectedException InvalidArgumentException + */ + public function testPushProcessorWithNonCallable() + { + $logger = new Logger(__METHOD__); + + $logger->pushProcessor(new \stdClass()); + } + + /** + * @covers Monolog\Logger::addRecord + */ + public function testProcessorsAreExecuted() + { + $logger = new Logger(__METHOD__); + $handler = new TestHandler; + $logger->pushHandler($handler); + $logger->pushProcessor(function ($record) { + $record['extra']['win'] = true; + + return $record; + }); + $logger->addError('test'); + list($record) = $handler->getRecords(); + $this->assertTrue($record['extra']['win']); + } + + /** + * @covers Monolog\Logger::addRecord + */ + public function testProcessorsAreCalledOnlyOnce() + { + $logger = new Logger(__METHOD__); + $handler = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler->expects($this->any()) + ->method('isHandling') + ->will($this->returnValue(true)) + ; + $handler->expects($this->any()) + ->method('handle') + ->will($this->returnValue(true)) + ; + $logger->pushHandler($handler); + + $processor = $this->getMockBuilder('Monolog\Processor\WebProcessor') + ->disableOriginalConstructor() + ->setMethods(array('__invoke')) + ->getMock() + ; + $processor->expects($this->once()) + ->method('__invoke') + ->will($this->returnArgument(0)) + ; + $logger->pushProcessor($processor); + + $logger->addError('test'); + } + + /** + * @covers Monolog\Logger::addRecord + */ + public function testProcessorsNotCalledWhenNotHandled() + { + $logger = new Logger(__METHOD__); + $handler = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler->expects($this->once()) + ->method('isHandling') + ->will($this->returnValue(false)) + ; + $logger->pushHandler($handler); + $that = $this; + $logger->pushProcessor(function ($record) use ($that) { + $that->fail('The processor should not be called'); + }); + $logger->addAlert('test'); + } + + /** + * @covers Monolog\Logger::addRecord + */ + public function testHandlersNotCalledBeforeFirstHandling() + { + $logger = new Logger(__METHOD__); + + $handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler1->expects($this->never()) + ->method('isHandling') + ->will($this->returnValue(false)) + ; + $handler1->expects($this->once()) + ->method('handle') + ->will($this->returnValue(false)) + ; + $logger->pushHandler($handler1); + + $handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler2->expects($this->once()) + ->method('isHandling') + ->will($this->returnValue(true)) + ; + $handler2->expects($this->once()) + ->method('handle') + ->will($this->returnValue(false)) + ; + $logger->pushHandler($handler2); + + $handler3 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler3->expects($this->once()) + ->method('isHandling') + ->will($this->returnValue(false)) + ; + $handler3->expects($this->never()) + ->method('handle') + ; + $logger->pushHandler($handler3); + + $logger->debug('test'); + } + + /** + * @covers Monolog\Logger::addRecord + */ + public function testBubblingWhenTheHandlerReturnsFalse() + { + $logger = new Logger(__METHOD__); + + $handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler1->expects($this->any()) + ->method('isHandling') + ->will($this->returnValue(true)) + ; + $handler1->expects($this->once()) + ->method('handle') + ->will($this->returnValue(false)) + ; + $logger->pushHandler($handler1); + + $handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler2->expects($this->any()) + ->method('isHandling') + ->will($this->returnValue(true)) + ; + $handler2->expects($this->once()) + ->method('handle') + ->will($this->returnValue(false)) + ; + $logger->pushHandler($handler2); + + $logger->debug('test'); + } + + /** + * @covers Monolog\Logger::addRecord + */ + public function testNotBubblingWhenTheHandlerReturnsTrue() + { + $logger = new Logger(__METHOD__); + + $handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler1->expects($this->any()) + ->method('isHandling') + ->will($this->returnValue(true)) + ; + $handler1->expects($this->never()) + ->method('handle') + ; + $logger->pushHandler($handler1); + + $handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler2->expects($this->any()) + ->method('isHandling') + ->will($this->returnValue(true)) + ; + $handler2->expects($this->once()) + ->method('handle') + ->will($this->returnValue(true)) + ; + $logger->pushHandler($handler2); + + $logger->debug('test'); + } + + /** + * @covers Monolog\Logger::isHandling + */ + public function testIsHandling() + { + $logger = new Logger(__METHOD__); + + $handler1 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler1->expects($this->any()) + ->method('isHandling') + ->will($this->returnValue(false)) + ; + + $logger->pushHandler($handler1); + $this->assertFalse($logger->isHandling(Logger::DEBUG)); + + $handler2 = $this->getMock('Monolog\Handler\HandlerInterface'); + $handler2->expects($this->any()) + ->method('isHandling') + ->will($this->returnValue(true)) + ; + + $logger->pushHandler($handler2); + $this->assertTrue($logger->isHandling(Logger::DEBUG)); + } + + /** + * @dataProvider logMethodProvider + * @covers Monolog\Logger::addDebug + * @covers Monolog\Logger::addInfo + * @covers Monolog\Logger::addNotice + * @covers Monolog\Logger::addWarning + * @covers Monolog\Logger::addError + * @covers Monolog\Logger::addCritical + * @covers Monolog\Logger::addAlert + * @covers Monolog\Logger::addEmergency + * @covers Monolog\Logger::debug + * @covers Monolog\Logger::info + * @covers Monolog\Logger::notice + * @covers Monolog\Logger::warn + * @covers Monolog\Logger::err + * @covers Monolog\Logger::crit + * @covers Monolog\Logger::alert + * @covers Monolog\Logger::emerg + */ + public function testLogMethods($method, $expectedLevel) + { + $logger = new Logger('foo'); + $handler = new TestHandler; + $logger->pushHandler($handler); + $logger->{$method}('test'); + list($record) = $handler->getRecords(); + $this->assertEquals($expectedLevel, $record['level']); + } + + public function logMethodProvider() + { + return array( + // monolog methods + array('addDebug', Logger::DEBUG), + array('addInfo', Logger::INFO), + array('addNotice', Logger::NOTICE), + array('addWarning', Logger::WARNING), + array('addError', Logger::ERROR), + array('addCritical', Logger::CRITICAL), + array('addAlert', Logger::ALERT), + array('addEmergency', Logger::EMERGENCY), + + // ZF/Sf2 compat methods + array('debug', Logger::DEBUG), + array('info', Logger::INFO), + array('notice', Logger::NOTICE), + array('warn', Logger::WARNING), + array('err', Logger::ERROR), + array('crit', Logger::CRITICAL), + array('alert', Logger::ALERT), + array('emerg', Logger::EMERGENCY), + ); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/GitProcessorTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/GitProcessorTest.php @@ -0,0 +1,29 @@ +<?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\Processor; + +use Monolog\TestCase; + +class GitProcessorTest extends TestCase +{ + /** + * @covers Monolog\Processor\GitProcessor::__invoke + */ + public function testProcessor() + { + $processor = new GitProcessor(); + $record = $processor($this->getRecord()); + + $this->assertArrayHasKey('git', $record['extra']); + $this->assertTrue(!is_array($record['extra']['git']['branch'])); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/IntrospectionProcessorTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/IntrospectionProcessorTest.php @@ -0,0 +1,123 @@ +<?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 Acme; + +class Tester +{ + public function test($handler, $record) + { + $handler->handle($record); + } +} + +function tester($handler, $record) +{ + $handler->handle($record); +} + +namespace Monolog\Processor; + +use Monolog\Logger; +use Monolog\TestCase; +use Monolog\Handler\TestHandler; + +class IntrospectionProcessorTest extends TestCase +{ + public function getHandler() + { + $processor = new IntrospectionProcessor(); + $handler = new TestHandler(); + $handler->pushProcessor($processor); + + return $handler; + } + + public function testProcessorFromClass() + { + $handler = $this->getHandler(); + $tester = new \Acme\Tester; + $tester->test($handler, $this->getRecord()); + list($record) = $handler->getRecords(); + $this->assertEquals(__FILE__, $record['extra']['file']); + $this->assertEquals(18, $record['extra']['line']); + $this->assertEquals('Acme\Tester', $record['extra']['class']); + $this->assertEquals('test', $record['extra']['function']); + } + + public function testProcessorFromFunc() + { + $handler = $this->getHandler(); + \Acme\tester($handler, $this->getRecord()); + list($record) = $handler->getRecords(); + $this->assertEquals(__FILE__, $record['extra']['file']); + $this->assertEquals(24, $record['extra']['line']); + $this->assertEquals(null, $record['extra']['class']); + $this->assertEquals('Acme\tester', $record['extra']['function']); + } + + public function testLevelTooLow() + { + $input = array( + 'level' => Logger::DEBUG, + 'extra' => array(), + ); + + $expected = $input; + + $processor = new IntrospectionProcessor(Logger::CRITICAL); + $actual = $processor($input); + + $this->assertEquals($expected, $actual); + } + + public function testLevelEqual() + { + $input = array( + 'level' => Logger::CRITICAL, + 'extra' => array(), + ); + + $expected = $input; + $expected['extra'] = array( + 'file' => null, + 'line' => null, + 'class' => 'ReflectionMethod', + 'function' => 'invokeArgs', + ); + + $processor = new IntrospectionProcessor(Logger::CRITICAL); + $actual = $processor($input); + + $this->assertEquals($expected, $actual); + } + + public function testLevelHigher() + { + $input = array( + 'level' => Logger::EMERGENCY, + 'extra' => array(), + ); + + $expected = $input; + $expected['extra'] = array( + 'file' => null, + 'line' => null, + 'class' => 'ReflectionMethod', + 'function' => 'invokeArgs', + ); + + $processor = new IntrospectionProcessor(Logger::CRITICAL); + $actual = $processor($input); + + $this->assertEquals($expected, $actual); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/MemoryPeakUsageProcessorTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/MemoryPeakUsageProcessorTest.php @@ -0,0 +1,42 @@ +<?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\Processor; + +use Monolog\TestCase; + +class MemoryPeakUsageProcessorTest extends TestCase +{ + /** + * @covers Monolog\Processor\MemoryPeakUsageProcessor::__invoke + * @covers Monolog\Processor\MemoryProcessor::formatBytes + */ + public function testProcessor() + { + $processor = new MemoryPeakUsageProcessor(); + $record = $processor($this->getRecord()); + $this->assertArrayHasKey('memory_peak_usage', $record['extra']); + $this->assertRegExp('#[0-9.]+ (M|K)?B$#', $record['extra']['memory_peak_usage']); + } + + /** + * @covers Monolog\Processor\MemoryPeakUsageProcessor::__invoke + * @covers Monolog\Processor\MemoryProcessor::formatBytes + */ + public function testProcessorWithoutFormatting() + { + $processor = new MemoryPeakUsageProcessor(true, false); + $record = $processor($this->getRecord()); + $this->assertArrayHasKey('memory_peak_usage', $record['extra']); + $this->assertInternalType('int', $record['extra']['memory_peak_usage']); + $this->assertGreaterThan(0, $record['extra']['memory_peak_usage']); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/MemoryUsageProcessorTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/MemoryUsageProcessorTest.php @@ -0,0 +1,42 @@ +<?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\Processor; + +use Monolog\TestCase; + +class MemoryUsageProcessorTest extends TestCase +{ + /** + * @covers Monolog\Processor\MemoryUsageProcessor::__invoke + * @covers Monolog\Processor\MemoryProcessor::formatBytes + */ + public function testProcessor() + { + $processor = new MemoryUsageProcessor(); + $record = $processor($this->getRecord()); + $this->assertArrayHasKey('memory_usage', $record['extra']); + $this->assertRegExp('#[0-9.]+ (M|K)?B$#', $record['extra']['memory_usage']); + } + + /** + * @covers Monolog\Processor\MemoryUsageProcessor::__invoke + * @covers Monolog\Processor\MemoryProcessor::formatBytes + */ + public function testProcessorWithoutFormatting() + { + $processor = new MemoryUsageProcessor(true, false); + $record = $processor($this->getRecord()); + $this->assertArrayHasKey('memory_usage', $record['extra']); + $this->assertInternalType('int', $record['extra']['memory_usage']); + $this->assertGreaterThan(0, $record['extra']['memory_usage']); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/ProcessIdProcessorTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/ProcessIdProcessorTest.php @@ -0,0 +1,30 @@ +<?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\Processor; + +use Monolog\TestCase; + +class ProcessIdProcessorTest extends TestCase +{ + /** + * @covers Monolog\Processor\ProcessIdProcessor::__invoke + */ + public function testProcessor() + { + $processor = new ProcessIdProcessor(); + $record = $processor($this->getRecord()); + $this->assertArrayHasKey('process_id', $record['extra']); + $this->assertInternalType('int', $record['extra']['process_id']); + $this->assertGreaterThan(0, $record['extra']['process_id']); + $this->assertEquals(getmypid(), $record['extra']['process_id']); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/PsrLogMessageProcessorTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/PsrLogMessageProcessorTest.php @@ -0,0 +1,43 @@ +<?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\Processor; + +class PsrLogMessageProcessorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @dataProvider getPairs + */ + public function testReplacement($val, $expected) + { + $proc = new PsrLogMessageProcessor; + + $message = $proc(array( + 'message' => '{foo}', + 'context' => array('foo' => $val) + )); + $this->assertEquals($expected, $message['message']); + } + + public function getPairs() + { + return array( + array('foo', 'foo'), + array('3', '3'), + array(3, '3'), + array(null, ''), + array(true, '1'), + array(false, ''), + array(new \stdClass, '[object stdClass]'), + array(array(), '[array]'), + ); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/TagProcessorTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/TagProcessorTest.php @@ -0,0 +1,29 @@ +<?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\Processor; + +use Monolog\TestCase; + +class TagProcessorTest extends TestCase +{ + /** + * @covers Monolog\Processor\TagProcessor::__invoke + */ + public function testProcessor() + { + $tags = array(1, 2, 3); + $processor = new TagProcessor($tags); + $record = $processor($this->getRecord()); + + $this->assertEquals($tags, $record['extra']['tags']); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/UidProcessorTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/UidProcessorTest.php @@ -0,0 +1,27 @@ +<?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\Processor; + +use Monolog\TestCase; + +class UidProcessorTest extends TestCase +{ + /** + * @covers Monolog\Processor\UidProcessor::__invoke + */ + public function testProcessor() + { + $processor = new UidProcessor(); + $record = $processor($this->getRecord()); + $this->assertArrayHasKey('uid', $record['extra']); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/WebProcessorTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/Processor/WebProcessorTest.php @@ -0,0 +1,98 @@ +<?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\Processor; + +use Monolog\TestCase; + +class WebProcessorTest extends TestCase +{ + public function testProcessor() + { + $server = array( + 'REQUEST_URI' => 'A', + 'REMOTE_ADDR' => 'B', + 'REQUEST_METHOD' => 'C', + 'HTTP_REFERER' => 'D', + 'SERVER_NAME' => 'F', + 'UNIQUE_ID' => 'G', + ); + + $processor = new WebProcessor($server); + $record = $processor($this->getRecord()); + $this->assertEquals($server['REQUEST_URI'], $record['extra']['url']); + $this->assertEquals($server['REMOTE_ADDR'], $record['extra']['ip']); + $this->assertEquals($server['REQUEST_METHOD'], $record['extra']['http_method']); + $this->assertEquals($server['HTTP_REFERER'], $record['extra']['referrer']); + $this->assertEquals($server['SERVER_NAME'], $record['extra']['server']); + $this->assertEquals($server['UNIQUE_ID'], $record['extra']['unique_id']); + } + + public function testProcessorDoNothingIfNoRequestUri() + { + $server = array( + 'REMOTE_ADDR' => 'B', + 'REQUEST_METHOD' => 'C', + ); + $processor = new WebProcessor($server); + $record = $processor($this->getRecord()); + $this->assertEmpty($record['extra']); + } + + public function testProcessorReturnNullIfNoHttpReferer() + { + $server = array( + 'REQUEST_URI' => 'A', + 'REMOTE_ADDR' => 'B', + 'REQUEST_METHOD' => 'C', + 'SERVER_NAME' => 'F', + ); + $processor = new WebProcessor($server); + $record = $processor($this->getRecord()); + $this->assertNull($record['extra']['referrer']); + } + + public function testProcessorDoesNotAddUniqueIdIfNotPresent() + { + $server = array( + 'REQUEST_URI' => 'A', + 'REMOTE_ADDR' => 'B', + 'REQUEST_METHOD' => 'C', + 'SERVER_NAME' => 'F', + ); + $processor = new WebProcessor($server); + $record = $processor($this->getRecord()); + $this->assertFalse(isset($record['extra']['unique_id'])); + } + + public function testProcessorAddsOnlyRequestedExtraFields() + { + $server = array( + 'REQUEST_URI' => 'A', + 'REMOTE_ADDR' => 'B', + 'REQUEST_METHOD' => 'C', + 'SERVER_NAME' => 'F', + ); + + $processor = new WebProcessor($server, array('url', 'http_method')); + $record = $processor($this->getRecord()); + + $this->assertSame(array('url' => 'A', 'http_method' => 'C'), $record['extra']); + } + + /** + * @expectedException UnexpectedValueException + */ + public function testInvalidData() + { + new WebProcessor(new \stdClass); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/PsrLogCompatTest.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/PsrLogCompatTest.php @@ -0,0 +1,47 @@ +<?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; + +use Monolog\Handler\TestHandler; +use Monolog\Formatter\LineFormatter; +use Monolog\Processor\PsrLogMessageProcessor; +use Psr\Log\Test\LoggerInterfaceTest; + +class PsrLogCompatTest extends LoggerInterfaceTest +{ + private $handler; + + public function getLogger() + { + $logger = new Logger('foo'); + $logger->pushHandler($handler = new TestHandler); + $logger->pushProcessor(new PsrLogMessageProcessor); + $handler->setFormatter(new LineFormatter('%level_name% %message%')); + + $this->handler = $handler; + + return $logger; + } + + public function getLogs() + { + $convert = function ($record) { + $lower = function ($match) { + return strtolower($match[0]); + }; + + return preg_replace_callback('{^[A-Z]+}', $lower, $record['formatted']); + }; + + return array_map($convert, $this->handler->getRecords()); + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/Monolog/TestCase.php b/core/update/update/vendor/monolog/monolog/tests/Monolog/TestCase.php @@ -0,0 +1,58 @@ +<?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 TestCase extends \PHPUnit_Framework_TestCase +{ + /** + * @return array Record + */ + protected function getRecord($level = Logger::WARNING, $message = 'test', $context = array()) + { + return array( + 'message' => $message, + 'context' => $context, + 'level' => $level, + 'level_name' => Logger::getLevelName($level), + 'channel' => 'test', + 'datetime' => \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true))), + 'extra' => array(), + ); + } + + /** + * @return array + */ + protected function getMultipleRecords() + { + return array( + $this->getRecord(Logger::DEBUG, 'debug message 1'), + $this->getRecord(Logger::DEBUG, 'debug message 2'), + $this->getRecord(Logger::INFO, 'information'), + $this->getRecord(Logger::WARNING, 'warning'), + $this->getRecord(Logger::ERROR, 'error') + ); + } + + /** + * @return Monolog\Formatter\FormatterInterface + */ + protected function getIdentityFormatter() + { + $formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface'); + $formatter->expects($this->any()) + ->method('format') + ->will($this->returnCallback(function ($record) { return $record['message']; })); + + return $formatter; + } +} diff --git a/core/update/update/vendor/monolog/monolog/tests/bootstrap.php b/core/update/update/vendor/monolog/monolog/tests/bootstrap.php @@ -0,0 +1,15 @@ +<?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'); diff --git a/core/update/update/vendor/psr/log/.gitignore b/core/update/update/vendor/psr/log/.gitignore @@ -0,0 +1 @@ +vendor diff --git a/core/update/update/vendor/psr/log/LICENSE b/core/update/update/vendor/psr/log/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012 PHP Framework Interoperability Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/core/update/update/vendor/psr/log/Psr/Log/AbstractLogger.php b/core/update/update/vendor/psr/log/Psr/Log/AbstractLogger.php @@ -0,0 +1,120 @@ +<?php + +namespace Psr\Log; + +/** + * This is a simple Logger implementation that other Loggers can inherit from. + * + * It simply delegates all log-level-specific methods to the `log` method to + * reduce boilerplate code that a simple Logger that does the same thing with + * messages regardless of the error level has to implement. + */ +abstract class AbstractLogger implements LoggerInterface +{ + /** + * System is unusable. + * + * @param string $message + * @param array $context + * @return null + */ + public function emergency($message, array $context = array()) + { + $this->log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * @return null + */ + public function alert($message, array $context = array()) + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * @return null + */ + public function critical($message, array $context = array()) + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * @return null + */ + public function error($message, array $context = array()) + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * @return null + */ + public function warning($message, array $context = array()) + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * @return null + */ + public function notice($message, array $context = array()) + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * @return null + */ + public function info($message, array $context = array()) + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * @return null + */ + public function debug($message, array $context = array()) + { + $this->log(LogLevel::DEBUG, $message, $context); + } +} diff --git a/core/update/update/vendor/psr/log/Psr/Log/InvalidArgumentException.php b/core/update/update/vendor/psr/log/Psr/Log/InvalidArgumentException.php @@ -0,0 +1,7 @@ +<?php + +namespace Psr\Log; + +class InvalidArgumentException extends \InvalidArgumentException +{ +} diff --git a/core/update/update/vendor/psr/log/Psr/Log/LogLevel.php b/core/update/update/vendor/psr/log/Psr/Log/LogLevel.php @@ -0,0 +1,18 @@ +<?php + +namespace Psr\Log; + +/** + * Describes log levels + */ +class LogLevel +{ + const EMERGENCY = 'emergency'; + const ALERT = 'alert'; + const CRITICAL = 'critical'; + const ERROR = 'error'; + const WARNING = 'warning'; + const NOTICE = 'notice'; + const INFO = 'info'; + const DEBUG = 'debug'; +} diff --git a/core/update/update/vendor/psr/log/Psr/Log/LoggerAwareInterface.php b/core/update/update/vendor/psr/log/Psr/Log/LoggerAwareInterface.php @@ -0,0 +1,17 @@ +<?php + +namespace Psr\Log; + +/** + * Describes a logger-aware instance + */ +interface LoggerAwareInterface +{ + /** + * Sets a logger instance on the object + * + * @param LoggerInterface $logger + * @return null + */ + public function setLogger(LoggerInterface $logger); +} diff --git a/core/update/update/vendor/psr/log/Psr/Log/LoggerAwareTrait.php b/core/update/update/vendor/psr/log/Psr/Log/LoggerAwareTrait.php @@ -0,0 +1,22 @@ +<?php + +namespace Psr\Log; + +/** + * Basic Implementation of LoggerAwareInterface. + */ +trait LoggerAwareTrait +{ + /** @var LoggerInterface */ + protected $logger; + + /** + * Sets a logger. + * + * @param LoggerInterface $logger + */ + public function setLogger(LoggerInterface $logger) + { + $this->logger = $logger; + } +} diff --git a/core/update/update/vendor/psr/log/Psr/Log/LoggerInterface.php b/core/update/update/vendor/psr/log/Psr/Log/LoggerInterface.php @@ -0,0 +1,114 @@ +<?php + +namespace Psr\Log; + +/** + * Describes a logger instance + * + * The message MUST be a string or object implementing __toString(). + * + * The message MAY contain placeholders in the form: {foo} where foo + * will be replaced by the context data in key "foo". + * + * The context array can contain arbitrary data, the only assumption that + * can be made by implementors is that if an Exception instance is given + * to produce a stack trace, it MUST be in a key named "exception". + * + * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md + * for the full interface specification. + */ +interface LoggerInterface +{ + /** + * System is unusable. + * + * @param string $message + * @param array $context + * @return null + */ + public function emergency($message, array $context = array()); + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * @return null + */ + public function alert($message, array $context = array()); + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * @return null + */ + public function critical($message, array $context = array()); + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * @return null + */ + public function error($message, array $context = array()); + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * @return null + */ + public function warning($message, array $context = array()); + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * @return null + */ + public function notice($message, array $context = array()); + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * @return null + */ + public function info($message, array $context = array()); + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * @return null + */ + public function debug($message, array $context = array()); + + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * @return null + */ + public function log($level, $message, array $context = array()); +} diff --git a/core/update/update/vendor/psr/log/Psr/Log/LoggerTrait.php b/core/update/update/vendor/psr/log/Psr/Log/LoggerTrait.php @@ -0,0 +1,131 @@ +<?php + +namespace Psr\Log; + +/** + * This is a simple Logger trait that classes unable to extend AbstractLogger + * (because they extend another class, etc) can include. + * + * It simply delegates all log-level-specific methods to the `log` method to + * reduce boilerplate code that a simple Logger that does the same thing with + * messages regardless of the error level has to implement. + */ +trait LoggerTrait +{ + /** + * System is unusable. + * + * @param string $message + * @param array $context + * @return null + */ + public function emergency($message, array $context = array()) + { + $this->log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * @return null + */ + public function alert($message, array $context = array()) + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * @return null + */ + public function critical($message, array $context = array()) + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * @return null + */ + public function error($message, array $context = array()) + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * @return null + */ + public function warning($message, array $context = array()) + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * @return null + */ + public function notice($message, array $context = array()) + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * @return null + */ + public function info($message, array $context = array()) + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * @return null + */ + public function debug($message, array $context = array()) + { + $this->log(LogLevel::DEBUG, $message, $context); + } + + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * @return null + */ + abstract public function log($level, $message, array $context = array()); +} diff --git a/core/update/update/vendor/psr/log/Psr/Log/NullLogger.php b/core/update/update/vendor/psr/log/Psr/Log/NullLogger.php @@ -0,0 +1,27 @@ +<?php + +namespace Psr\Log; + +/** + * This Logger can be used to avoid conditional log calls + * + * Logging should always be optional, and if no logger is provided to your + * library creating a NullLogger instance to have something to throw logs at + * is a good way to avoid littering your code with `if ($this->logger) { }` + * blocks. + */ +class NullLogger extends AbstractLogger +{ + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * @return null + */ + public function log($level, $message, array $context = array()) + { + // noop + } +} diff --git a/core/update/update/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php b/core/update/update/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php @@ -0,0 +1,116 @@ +<?php + +namespace Psr\Log\Test; + +use Psr\Log\LogLevel; + +/** + * Provides a base test class for ensuring compliance with the LoggerInterface + * + * Implementors can extend the class and implement abstract methods to run this as part of their test suite + */ +abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase +{ + /** + * @return LoggerInterface + */ + abstract function getLogger(); + + /** + * This must return the log messages in order with a simple formatting: "<LOG LEVEL> <MESSAGE>" + * + * Example ->error('Foo') would yield "error Foo" + * + * @return string[] + */ + abstract function getLogs(); + + public function testImplements() + { + $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger()); + } + + /** + * @dataProvider provideLevelsAndMessages + */ + public function testLogsAtAllLevels($level, $message) + { + $logger = $this->getLogger(); + $logger->{$level}($message, array('user' => 'Bob')); + $logger->log($level, $message, array('user' => 'Bob')); + + $expected = array( + $level.' message of level '.$level.' with context: Bob', + $level.' message of level '.$level.' with context: Bob', + ); + $this->assertEquals($expected, $this->getLogs()); + } + + public function provideLevelsAndMessages() + { + return array( + LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'), + LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'), + LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'), + LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'), + LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'), + LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'), + LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'), + LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'), + ); + } + + /** + * @expectedException Psr\Log\InvalidArgumentException + */ + public function testThrowsOnInvalidLevel() + { + $logger = $this->getLogger(); + $logger->log('invalid level', 'Foo'); + } + + public function testContextReplacement() + { + $logger = $this->getLogger(); + $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar')); + + $expected = array('info {Message {nothing} Bob Bar a}'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testObjectCastToString() + { + $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString')); + $dummy->expects($this->once()) + ->method('__toString') + ->will($this->returnValue('DUMMY')); + + $this->getLogger()->warning($dummy); + } + + public function testContextCanContainAnything() + { + $context = array( + 'bool' => true, + 'null' => null, + 'string' => 'Foo', + 'int' => 0, + 'float' => 0.5, + 'nested' => array('with object' => new DummyTest), + 'object' => new \DateTime, + 'resource' => fopen('php://memory', 'r'), + ); + + $this->getLogger()->warning('Crazy context data', $context); + } + + public function testContextExceptionKeyCanBeExceptionOrOtherValues() + { + $this->getLogger()->warning('Random message', array('exception' => 'oops')); + $this->getLogger()->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail'))); + } +} + +class DummyTest +{ +} +\ No newline at end of file diff --git a/core/update/update/vendor/psr/log/README.md b/core/update/update/vendor/psr/log/README.md @@ -0,0 +1,45 @@ +PSR Log +======= + +This repository holds all interfaces/classes/traits related to +[PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md). + +Note that this is not a logger of its own. It is merely an interface that +describes a logger. See the specification for more details. + +Usage +----- + +If you need a logger, you can use the interface like this: + +```php +<?php + +use Psr\Log\LoggerInterface; + +class Foo +{ + private $logger; + + public function __construct(LoggerInterface $logger = null) + { + $this->logger = $logger; + } + + public function doSomething() + { + if ($this->logger) { + $this->logger->info('Doing work'); + } + + // do something useful + } +} +``` + +You can then pick one of the implementations of the interface to get a logger. + +If you want to implement the interface, you can require this package and +implement `Psr\Log\LoggerInterface` in your code. Please read the +[specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) +for details. diff --git a/core/update/update/vendor/psr/log/composer.json b/core/update/update/vendor/psr/log/composer.json @@ -0,0 +1,17 @@ +{ + "name": "psr/log", + "description": "Common interface for logging libraries", + "keywords": ["psr", "psr-3", "log"], + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "autoload": { + "psr-0": { + "Psr\\Log\\": "" + } + } +} diff --git a/core/update/update/vendor/vierbergenlars/php-semver/.travis.yml b/core/update/update/vendor/vierbergenlars/php-semver/.travis.yml @@ -0,0 +1,6 @@ +language: php +php: + - 5.3 + - 5.4 +before_script: composer install --dev --prefer-source +script: php tests/all_tests.php diff --git a/core/update/update/vendor/vierbergenlars/php-semver/README.md b/core/update/update/vendor/vierbergenlars/php-semver/README.md @@ -0,0 +1,129 @@ +# php-semver -- The semantic versioner for npm ported to PHP + +Ported from [node-semver 1.1.2](https://github.com/isaacs/node-semver/tree/v1.1.2) to PHP + +[![Build Status](https://secure.travis-ci.org/vierbergenlars/php-semver.png?branch=master)](http://travis-ci.org/vierbergenlars/php-semver) +[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/vierbergenlars/php-semver/badges/quality-score.png?s=89ff49019cde97e70228ae14d2dc08b727e72157)](https://scrutinizer-ci.com/g/vierbergenlars/php-semver/) +[![Latest Stable Version](https://poser.pugx.org/vierbergenlars/php-semver/v/stable.png)](https://packagist.org/packages/vierbergenlars/php-semver) +[![Total Downloads](https://poser.pugx.org/vierbergenlars/php-semver/downloads.png)](https://packagist.org/packages/vierbergenlars/php-semver) + +## Usage + +```php +<?php + +use vierbergenlars\SemVer\version; +use vierbergenlars\SemVer\expression; +use vierbergenlars\SemVer\SemVerException; + +// Check if a version is valid +$semver = new version('1.2.3'); +$semver = new version('a.b.c'); //SemVerException thrown + +//Get a clean version string +$semver = new version('=v1.2.3'); +$semver->getVersion(); //'1.2.3' + +//Check if a version satisfies a range +$semver = new version('1.2.3'); +$semver->satisfies(new expression('1.x || >=2.5.0 || 5.0.0 - 7.2.3')); //true +# OR +$range = new expression('1.x || >=2.5.0 || 5.0.0 - 7.2.3'); +$range->satisfiedBy(new version('1.2.3')); //true + +//Compare two versions +version::gt('1.2.3', '9.8.7'); //false +version::lt('1.2.3', '9.8.7'); //true +``` + +## Versions + +A version is the following things, in this order: + +* a number (Major) +* a period +* a number (minor) +* a period +* a number (patch) +* OPTIONAL: a hyphen, followed by a number (build) +* OPTIONAL: a collection of pretty much any non-whitespace characters + (tag) + +A leading `"="` or `"v"` character is stripped off and ignored. + +## Comparisons + +The ordering of versions is done using the following algorithm, given +two versions and asked to find the greater of the two: + +* If the majors are numerically different, then take the one + with a bigger major number. `2.3.4 > 1.3.4` +* If the minors are numerically different, then take the one + with the bigger minor number. `2.3.4 > 2.2.4` +* If the patches are numerically different, then take the one with the + bigger patch number. `2.3.4 > 2.3.3` +* If only one of them has a build number, then take the one with the + build number. `2.3.4-0 > 2.3.4` +* If they both have build numbers, and the build numbers are numerically + different, then take the one with the bigger build number. + `2.3.4-10 > 2.3.4-9` +* If only one of them has a tag, then take the one without the tag. + `2.3.4 > 2.3.4-beta` +* If they both have tags, then take the one with the lexicographically + larger tag. `2.3.4-beta > 2.3.4-alpha` +* At this point, they're equal. + +## Ranges + +The following range styles are supported: + +* `>1.2.3` Greater than a specific version. +* `<1.2.3` Less than +* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4` +* `~1.2.3` := `>=1.2.3 <1.3.0` +* `~1.2` := `>=1.2.0 <2.0.0` +* `~1` := `>=1.0.0 <2.0.0` +* `1.2.x` := `>=1.2.0 <1.3.0` +* `1.x` := `>=1.0.0 <2.0.0` + +Ranges can be joined with either a space (which implies "and") or a +`||` (which implies "or"). + +## Functions + +* `$version->valid()`: Return the parsed version, or null if it's not valid. +* `$version->inc($type)`: Return the version incremented by the release type + (major, minor, patch, or build), or null if an invalid release type is provided. + +### Comparison + +* `version::gt($v1, $v2)`: `v1 > v2` +* `version::gte($v1, $v2)`: `v1 >= v2` +* `version::lt($v1, $v2)`: `v1 < v2` +* `version::lte($v1, $v2)`: `v1 <= v2` +* `version::eq($v1, $v2)`: `v1 == v2` This is true if they're logically equivalent, + even if they're not the exact same string. You already know how to + compare strings. +* `version::neq($v1, $v2)`: `v1 != v2` The opposite of eq. +* `version::cmp($v1, $comparator, $v2)`: Pass in a comparison string, and it'll call + the corresponding function above. `"==="` and `"!=="` do simple + string comparison, but are included for completeness. Throws if an + invalid comparison string is provided. +* `version::compare($v1, $v2)`: Return 0 if `v1 == v2`, 1 if `v1 > v2`, or -1 if + `v1 < v2`. Sorts in ascending order if passed to [`usort()`](http://php.net/manual/en/function.usort.php) +* `version::rcompare($v1, $v2)`: The reverse of compare. Sorts an array of versions + in descending order when passed to [`usort()`](http://php.net/manual/en/function.usort.php). + + +### Ranges + +* `$expression->validRange()`: Return the valid range or `null` if it's not valid +* `$version->satisfies($range)`: Return `true` if the version satisfies the range. +* `$expression->maxSatisfying($versions)`: Return the highest version in the array + that satisfies the range, or `null` if none of them do. + +## Thanks to + +All contributors (https://github.com/vierbergenlars/php-semver/graphs/contributors) + +[@isaacs](https://github.com/isaacs) and other contributors to [node-semver](https://github.com/isaacs/node-semver) diff --git a/core/update/update/vendor/vierbergenlars/php-semver/bin/semver b/core/update/update/vendor/vierbergenlars/php-semver/bin/semver @@ -0,0 +1,128 @@ +#!/usr/bin/env php +<?php + +namespace vierbergenlars\SemVer\Application\SemVer; + +require __DIR__ . '/../vendor/autoload.php'; + +use vierbergenlars\SemVer\version; +use vierbergenlars\SemVer\expression; +use vierbergenlars\SemVer\SemVerException; + +$version = false; +$range = array(); +$increment = false; + +// Get all arguments +while (\count($argv) > 0) { + $arg = \array_shift($argv); + switch ($arg) { + case '-v': + case '--version': + $version[] = \array_shift($argv); + break; + case '-r': + case '--range': + $range[] = \array_shift($argv); + break; + case '-i': + case '--increment': + $increment = \array_shift($argv); + break; + case '-?': + case '-h': + case '--help': + help(); + break; + } +} +main(); + +function help() { + $e = array( + 'Usage: semver -v|--version <version> [options]' + , '' + , ' -r <range> Test if version satisfies the supplied range.' + , ' --range <range>' + , ' -i [major|minor|patch|build] Increment the given version number.' + , ' --increment [major|minor|patch|build]' + , '' + , 'Multiple versions or ranges may be supplied.' + , '' + , 'Program exits successfully if any valid version satisfies' + , 'all supplied ranges, and prints all satisfying versions.' + , '' + , 'If no versions are valid, or ranges are not satisfied,' + , 'then exits failure.' + , '' + , 'Versions are printed in ascending order, so supplying' + , 'multiple versions to the utility will just sort them.' + ); + echo \implode(PHP_EOL, $e); + exit; +} + +function main() { + global $version, $range, $increment; + if ($increment !== false) { + increment($version[0], $increment); + } + if ($version !== false) { + filter($version, $range); + } + help(); +} + +function fail($message = '') { + fwrite(STDERR, $message); + exit(1); +} + +function increment($version, $what) { + if (\file_exists($version)) + $version = \file_get_contents($version); + if ($version == '-') + $version = \fgets(STDIN); + try { + $v = new version($version); + echo $v->inc($what); + exit; + } catch (SemVerException $e) { + fail($e->getMessage()); + } +} + +function filter($versions, $ranges) { + if (\file_exists($versions[0])) + $versions = \file($versions[0], \FILE_IGNORE_NEW_LINES | \FILE_SKIP_EMPTY_LINES); + if ($versions[0] == '-') { + unset($versions[0]); + while ($version = \fgets(\STDIN)) { + $versions[] = $version; + } + } + $matching_versions = array(); + foreach ($versions as $version) { + $ok = true; + try { + $v = new version($version); + foreach ($ranges as $range) { + if ($v->satisfies(new versionExpression($range))) + continue; + $ok = false; + break; + } + if ($ok) + $matching_versions[] = $v; + } catch (SemVerException $e) { + + } + } + \usort($matching_versions, '\\vierbergenlars\\SemVer\\version::compare'); + foreach ($matching_versions as $version) { + echo $version . PHP_EOL; + } + if (\count($matching_versions) == 0) + fail(); + exit; +} diff --git a/core/update/update/vendor/vierbergenlars/php-semver/bin/update-versions b/core/update/update/vendor/vierbergenlars/php-semver/bin/update-versions @@ -0,0 +1,134 @@ +#!/usr/bin/env php +<?php + +namespace vierbergenlars\SemVer\Application\UpdateVersions; + +require __DIR__ . '/../vendor/autoload.php'; + +use vierbergenlars\SemVer\version; +use vierbergenlars\SemVer\expression; +use vierbergenlars\SemVer\SemVerException; + +//Defaults +/** + * Input file containing the version + * @var string + */ +$input = 'composer.json'; +/** + * Array of paths to write to + * @var array + */ +$writeto = array(); +/** + * Root directory + * @var string + */ +$root = '.'; +/** + * Do not do anything + * @var bool + */ +$dry_run = false; +/** + * Shell command to execute for each updated file + * @var string + */ +$shell = NULL; +// Get all arguments +while (\count($argv) > 0) { + $arg = \array_shift($argv); + switch ($arg) { + case '-p': + case '--package': + $input = \array_shift($argv); + break; + case '-s': + case '--source': + $writeto[] = \array_shift($argv); + break; + case '-b': + case '--base': + $root = \array_shift($argv); + break; + case '--dry-run': + $dry_run = true; + break; + case '--shell': + $shell = \array_shift($argv); + break; + case '-h': + case '--help': + help(); + } +} +//Defaults writeto +if ($writeto === array()) { + $writeto = array('src', 'bin'); +} +//Add root paths +$input = $root . '/' . $input; +foreach ($writeto as &$write) { + $write = $root . '/' . $write; +} +//Read those JSON files +if (!\file_exists($input)) + fail('Package file does not exist'); +$input = \json_decode(\file_get_contents($input), true); +if (!$input) { + fail('Invalid JSON file!'); +} +//Initialize the version from package file +try { + $version = new version($input['version']); +} catch (SemVerException $e) { + fail($e->getMessage()); +} +$version = $version->getString(); +foreach ($writeto as $output) { + $dir = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($output)); + foreach ($dir as $file) { + if (\preg_match('/[\\\\\\/]\\./', $file)) + continue; //Ignore . directories + $contents1 = \file_get_contents($file); + $contents2 = \str_replace(array('2.0.0--', '{{{' . 'version}}}'), $version, $contents1); + if ($contents1 != $contents2) { + fwrite(\STDOUT, 'Writing version information to file ' . $file . \PHP_EOL); + if ($shell !== null) { + \system($shell . ' "' . $file . '"', $exit_code); + if ($exit_code != 0) + fail('Subshell exited ' . $exit_code); + } + if ($dry_run) { + \fwrite(\STDOUT, '\\_Not writing to disk' . \PHP_EOL); + } else { + \file_put_contents($file, $contents2); + } + } + } +} + +function help() { + $e = array( + 'Usage: update-versions [options]' + , '' + , ' -p <composerfile> Use this file as composer.json file' + , ' --package <composerfile>' + , ' -s <dir> Add directory to sources to scan. May be repeated.' + , ' --source <dir>' + , ' -b <dir> Use this directory as base directory.' + , ' --base <dir>' + , ' --shell <command> Execute <command> for each changed file.' + , ' --dry-run Do not write files.' + , '' + , 'This program exits 0 on success or 1 on failure.' + , 'Defaults to "--package composer.json --source src --source bin --base ."' + ); + echo \implode(PHP_EOL, $e); + exit; +} + +function fail($message = '') { + \fwrite(\STDERR, $message . \PHP_EOL); + exit(1); +} diff --git a/core/update/update/vendor/vierbergenlars/php-semver/composer.json b/core/update/update/vendor/vierbergenlars/php-semver/composer.json @@ -0,0 +1,32 @@ +{ + "name":"vierbergenlars/php-semver", + "description":"The Semantic Versioner for PHP", + "keywords": ["semver", "versioning", "semantic"], + "type":"library", + "license": "MIT", + "authors": [ + { + "name":"Lars Vierbergen", + "email":"vierbergenlars@gmail.com" + } + ], + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "simpletest/simpletest":"1.1.*" + }, + "autoload": { + "psr-0": { + "vierbergenlars\\SemVer\\":"src/", + "vierbergenlars\\LibJs\\": "src/" + }, + "classmap": [ + "src/vierbergenlars/SemVer/internal.php" + ] + }, + "bin": [ + "bin/semver", + "bin/update-versions" + ] +} diff --git a/core/update/update/vendor/vierbergenlars/php-semver/definitions b/core/update/update/vendor/vierbergenlars/php-semver/definitions @@ -0,0 +1,30 @@ +RemoteCP Versioning format +========================== +##x.y.z format + +1. x is the major version number for backwards incompatible changes (e.g. removed functions) +2. y is the minor version number for backwards compatible changes (e.g. added functions) +3. z is the patch number, for bug fixes + +##Comparators +Lower version: < +Higher version: > +Lower or equal version: <= +Higher or equal version: >= +x or * as a wildcard + e.g.: 1.x.x >= 1.0.0 < 2.0.0 + 1.2.* >= 1.2.0 < 1.3.0 +A range can be expressed with - + e.g.: 1.0.0 - 1.2.3 >=1.0.0 <1.2.3 + 1.2.0 - 2.0.0 >=1.2.0 <2.0.0 +A range can be expressed by omitting lower order numbers + e.g.: 1 >=1.0.0 <2.0.0 + 1.2 >=1.2.0 <1.3.0 +A range can be expressed with ~ + e.g.: ~1 >=1.0.0 <2.0.0 + ~1.2 >=1.2.0 <1.3.0 + ~1.2.3 >=1.2.3 <1.3.0 + +##Logic +Two or more comparators in one string with only spaces between them: AND +||: OR +\ No newline at end of file diff --git a/core/update/update/vendor/vierbergenlars/php-semver/license.md b/core/update/update/vendor/vierbergenlars/php-semver/license.md @@ -0,0 +1,24 @@ +# The MIT License (MIT) + +``` +Copyright (c) 2013 Lars Vierbergen + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +``` diff --git a/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/JSArray.php b/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/JSArray.php @@ -0,0 +1,204 @@ +<?php + +/** + * Copyright (c) 2013 Lars Vierbergen + * MIT licensed + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +namespace vierbergenlars\LibJs; + +class JSArray extends Object implements \ArrayAccess, \Iterator +{ + /** + * + * @var array + */ + private $array; + + /** + * + * @var int + * @public + */ + private $length = null; + + /** + * + * @param array $arr + */ + public function __construct(array $arr = array()) + { + $this->array = $arr; + } + + /** + * + * @param \Closure $func + * @return JSArray + */ + public function filter(\Closure $func) + { + $finalArray = new JSArray(); + foreach($this->array as $key => $value) { + $key = $this->_convert($key); + $value = $this->_convert($value); + $ret = $func($value, $key, $this); + if($ret) + $finalArray->push($value); + } + return $finalArray; + } + + public function JSforEach(\Closure $func) + { + $a = $this->array; + foreach($this->array as $key=>$val) { + $func($this->_convert($val), $this->_convert($key), $this); + } + } + + /** + * + * @param String $c + * @return String + */ + public function join($c) + { + return new String(implode($c, $this->array)); + } + + /** + * + * @return JSArray + */ + public function reverse() + { + return new self(array_reverse($this->array)); + } + + /** + * + * @param \Closure $compareFunction + * @return JSArray + */ + public function sort(\Closure $compareFunction = null) + { + $a = $this->array; + if($compareFunction) { + usort($a, $compareFunction); + } else { + sort($a); + } + + return new self($a); + } + + /** + * + * @param \Closure $func + * @return JSArray + */ + public function map(\Closure $func) + { + $that = $this; + $wrap = function($str) use($func, $that) { + $str = $that->_convert($str); + return $func($str); + }; + return new self(array_map($wrap, $this->array)); + } + + /** + * @return int + */ + public function push() + { + foreach(func_get_args() as $arg) + { + $this->array[] = $arg; + } + return $this->length = count($this->array); + } + + public function __get($name) + { + switch($name) { + case 'length': + if($this->length !== null) + return $this->length; + return $this->length = count($this->array); + } + } + + + public function current() + { + return $this->_convert(current($this->array)); + } + + public function key() + { + return $this->_convert(key($this->array)); + } + + public function next() + { + return $this->_convert(next($this->array)); + } + + public function offsetExists($offset) + { + return isset($this->array[$offset]); + } + + public function offsetGet($offset) + { + if(!$this->offsetExists($offset)) + return null; + return $this->_convert($this->array[$offset]); + } + + public function offsetSet($offset, $value) + { + $this->array[$offset] = $value; + } + + public function offsetUnset($offset) + { + unset($this->array[$offset]); + } + + public function rewind() + { + return reset($this->array); + } + + public function valid() + { + return each($this->array)!== false; + } + + public function valueOf() + { + return $this->array; + } +} +\ No newline at end of file diff --git a/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/Object.php b/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/Object.php @@ -0,0 +1,57 @@ +<?php + +/** + * Copyright (c) 2013 Lars Vierbergen + * MIT licensed + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +namespace vierbergenlars\LibJs; + +class Object +{ + /** + * + * @param type $something + * @return \vierbergenlars\LibJs\String|\vierbergenlars\LibJs\JSArray + * @private + */ + public function _convert($something) + { + if(is_string($something)) { + return new String($something); + } elseif(is_array($something)) { + return new JSArray($something); + } else { + return $something; + } + } + + public function toString() + { + return new String((string)$this); + } + + public function valueOf() + { + return (string)$this; + } +} +\ No newline at end of file diff --git a/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/RegExp.php b/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/RegExp.php @@ -0,0 +1,96 @@ +<?php + +/** + * Copyright (c) 2013 Lars Vierbergen + * MIT licensed + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +namespace vierbergenlars\LibJs; + +class RegExp extends Object +{ + /** + * + * @var string + */ + private $regex; + + /** + * + * @var string + * @internal + */ + public $_pregSource = null; + + /** + * + * @var boolean + */ + public $global = false; + + /** + * + * @param string $regex + * @param string $flags + */ + public function __construct($regex, $flags = '') + { + $this->regex = '/'.$regex.'/'.$flags; + $this->_pregSource = '/'.$regex.'/'; + if(strpos($flags, 's') !== false) + $this->global = true; + } + + /** + * + * @param string|String $str + */ + public function exec($str) + { + if($this->global) { + if(!preg_match_all($this->_pregSource, (string)$src, $matches)) + return null; + } else { + if(!preg_match($this->_pregSource, (string)$str, $matches)) + return null; + } + return new JSArray($matches); + } + + /** + * + * @param string|String $str + */ + public function test($str) + { + if($this->global) { + return preg_match_all($this->_pregSource, (string)$str); + } else { + return preg_match($this->_pregSource, (string)$str); + } + } + + public function valueOf() + { + return $this->regex; + } +} +\ No newline at end of file diff --git a/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/String.php b/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/String.php @@ -0,0 +1,230 @@ +<?php + +/** + * Copyright (c) 2013 Lars Vierbergen + * MIT licensed + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +namespace vierbergenlars\LibJs; + +class String extends Object implements \ArrayAccess +{ + /** + * Wrapped string + * @var string + */ + private $str; + + /** + * + * @param string $str + */ + public function __construct($str) + { + $this->str = (string)$str; + } + + /** + * + * @param int $pos + * @return string + */ + public function charAt($pos) + { + if(isset($this->str[$pos])) + return $this->str[$pos]; + return ''; + } + + /** + * + * @param int $pos + * @return int + */ + public function charCodeAt($pos) + { + if(!isset($this->str[$pos])) + return NAN; + return (int)ord($this->charAt($pos)); + } + + /** + * + * @return String + */ + public function concat() + { + $concat = $this->str; + $strings = func_get_args(); + foreach($strings as $str) { + $concat.=$str; + } + return new self($concat); + } + + /** + * + * @param string|RegExp $regex + * @return JSArray + */ + public function match($regex) + { + if(!$regex instanceof RegExp) + $regex = new RegExp((string)$regex); + $ret = $regex->exec($this); + if($ret&&!$regex->global) { + $ret->input = $this; + } + return $ret; + } + + /** + * + * @param RegExp|string $regexOrSubstr + * @param \Closure|string $newSubstrOrFunction + * @return String + */ + public function replace($regexOrSubstr, $newSubstrOrFunction) + { + if($regexOrSubstr instanceof RegExp) { + if($newSubstrOrFunction instanceof \Closure) { + $wrap = function($matches)use($newSubstrOrFunction) { + $matches = array_map(function($s) { + return new String($s); + }, $matches); + return call_user_func_array($newSubstrOrFunction, $matches); + }; + return new self(preg_replace_callback( + $regexOrSubstr->_pregSource, + $wrap, + (string)$this + )); + } else { + return new self(preg_replace( + $regexOrSubstr->_pregSource, + $newSubstrOrFunction, + (string)$this + )); + } + } else { + return new self(str_replace($regexOrSubstr, $newSubstrOrFunction, (string)$this)); + } + } + + /** + * + * @param string|String|RegExp $c + * @return JSArray + */ + public function split($c) + { + if($c instanceof RegExp) { + $ret = preg_split($c->_pregSource, (string)$this); + } else { + $ret = explode((string)$c,(string)$this); + } + return new JSArray($ret); + } + + /** + * + * @return String + */ + public function toLowerCase() + { + return new self(strtolower((string)$this)); + } + + /** + * + * @return String + */ + public function toString() + { + return $this; + } + + /** + * + * @return String + */ + public function toUpperCase() + { + return new self(strtoupper((string)$this)); + } + + /** + * + * @return String + */ + public function trim() + { + return new self(trim((string)$this)); + } + + /** + * + * @return string + */ + public function valueOf() + { + return (string)$this; + } + + /** + * + * @return string + */ + public function __toString() + { + return $this->str; + } + + public function __get($name) + { + switch($name) { + case 'length': + return strlen($this->str); + } + } + + public function offsetExists($offset) + { + return isset($this->str[$offset]); + } + + public function offsetGet($offset) + { + return $this->str[$offset]; + } + + public function offsetSet($offset, $value) + { + $this->str[$offset] = $value; + } + + public function offsetUnset($offset) + { + throw new \LogicException('Cannot unset a position in a string'); + } + +} +\ No newline at end of file diff --git a/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/Util.php b/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/LibJs/Util.php @@ -0,0 +1,46 @@ +<?php + +/** + * Copyright (c) 2013 Lars Vierbergen + * MIT licensed + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +namespace vierbergenlars\LibJs; + +class Util +{ + private function __construct() + { + + } + + public static function JSor() + { + foreach(func_get_args() as $arg) { + if($arg instanceof String) + $arg = $arg->valueOf(); + if($arg) + return $arg; + } + return 0; + } +} +\ No newline at end of file diff --git a/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/SemVer/SemVerException.php b/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/SemVer/SemVerException.php @@ -0,0 +1,19 @@ +<?php + +namespace vierbergenlars\SemVer; + +class SemVerException extends \RuntimeException +{ + protected $version = null; + + public function __construct($message, $version = null) + { + $this->version = $version; + parent::__construct($message . ' [[' . $version . ']]'); + } + + public function getVersion() + { + return $this->version; + } +} diff --git a/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/SemVer/expression.php b/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/SemVer/expression.php @@ -0,0 +1,77 @@ +<?php + +namespace vierbergenlars\SemVer; +use vierbergenlars\SemVer\Internal\Range; +use vierbergenlars\SemVer\Internal\G; +use vierbergenlars\LibJs\JSArray; + +class expression +{ + /** + * + * @var Range + */ + private $range; + + /** + * standardizes the comparator/range/whatever-string to chunks + * @param string $versions + */ + public function __construct($versions, $loose = false) + { + try { + $this->range = new Range($versions, $loose); + } catch(\Exception $e) { + throw new SemVerException($e->getMessage(), $e->getCode(), $e); + } + } + + /** + * Checks ifthis range is satisfied by the given version + * @param version $version + * @return boolean + */ + public function satisfiedBy(version $version) + { + return $this->range->test($version); + } + + /** + * Get the whole or object as a string + * @return string + */ + public function getString() + { + return (string)$this->range->toString(); + } + + /** + * Get the object as an expression + * @return string + */ + public function __toString() + { + return $this->getString(); + } + + /** + * Get the object as a range expression + * @return string + */ + public function validRange() + { + return $this->getString(); + } + + /** + * Find the maximum satisfying version + * @param array|string $versions An array of version objects or version strings, one version string + * @return \vierbergenlars\SemVer\version|null + */ + public function maxSatisfying($versions, $loose = false) + { + if(!is_array($versions)) + $versions = array($versions); + return new version((string)G::maxSatisfying(new JSArray($versions), $this->range, $loose)); + } +} diff --git a/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php b/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/SemVer/internal.php @@ -0,0 +1,1114 @@ +<?php + +namespace vierbergenlars\SemVer\Internal; +use vierbergenlars\LibJs\JSArray; +use vierbergenlars\LibJs\String; +use vierbergenlars\LibJs\RegExp; +use vierbergenlars\LibJs\Object; +use vierbergenlars\LibJs\Util; + +class G +{ + public static function __callStatic($name, $arguments) + { + return call_user_func_array(__NAMESPACE__.'\\'.$name, $arguments); + } +} + +class Exports +{ + static public $re = array(); + static public $src = array(); + const SEMVER_SPEC_VERSION = '2.0.0'; +} + +$R = 0; + +// The following Regular Expressions can be used for tokenizing, +// validating, and parsing SemVer version strings. + +// ## Numeric Identifier +// A single `0`, or a non-zero digit followed by zero or more digits. + +define(__NAMESPACE__.'\\NUMERICIDENTIFIER', $R++); +Exports::$src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; +define(__NAMESPACE__.'\\NUMERICIDENTIFIERLOOSE', $R++); +Exports::$src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; + + +// ## Non-numeric Identifier +// Zero or more digits, followed by a letter or hyphen, and then zero or +// more letters, digits, or hyphens. + +define(__NAMESPACE__.'\\NONNUMERICIDENTIFIER', $R++); +Exports::$src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; + + +// ## Main Version +// Three dot-separated numeric identifiers. + +define(__NAMESPACE__.'\\MAINVERSION', $R++); +Exports::$src[MAINVERSION] = '(' . Exports::$src[NUMERICIDENTIFIER] . ')\\.' . + '(' . Exports::$src[NUMERICIDENTIFIER] . ')\\.' . + '(' . Exports::$src[NUMERICIDENTIFIER] . ')'; + +define(__NAMESPACE__.'\\MAINVERSIONLOOSE', $R++); +Exports::$src[MAINVERSIONLOOSE] = '(' . Exports::$src[NUMERICIDENTIFIERLOOSE] . ')\\.' . + '(' . Exports::$src[NUMERICIDENTIFIERLOOSE] . ')\\.' . + '(' . Exports::$src[NUMERICIDENTIFIERLOOSE] . ')'; + +// ## Pre-release Version Identifier +// A numeric identifier, or a non-numeric identifier. + +define(__NAMESPACE__.'\\PRERELEASEIDENTIFIER', $R++); +Exports::$src[PRERELEASEIDENTIFIER] = '(?:' . Exports::$src[NUMERICIDENTIFIER] . + '|' . Exports::$src[NONNUMERICIDENTIFIER] . ')'; + +define(__NAMESPACE__.'\\PRERELEASEIDENTIFIERLOOSE', $R++); +Exports::$src[PRERELEASEIDENTIFIERLOOSE] = '(?:' . Exports::$src[NUMERICIDENTIFIERLOOSE] . + '|' . Exports::$src[NONNUMERICIDENTIFIER] . ')'; + + +// ## Pre-release Version +// Hyphen, followed by one or more dot-separated pre-release version +// identifiers. + +define(__NAMESPACE__.'\\PRERELEASE', $R++); +Exports::$src[PRERELEASE] = '(?:-(' . Exports::$src[PRERELEASEIDENTIFIER] . + '(?:\\.' . Exports::$src[PRERELEASEIDENTIFIER] . ')*))'; + +define(__NAMESPACE__.'\\PRERELEASELOOSE', $R++); +Exports::$src[PRERELEASELOOSE] = '(?:-?(' . Exports::$src[PRERELEASEIDENTIFIERLOOSE] . + '(?:\\.' . Exports::$src[PRERELEASEIDENTIFIERLOOSE] . ')*))'; + +// ## Build Metadata Identifier +// Any combination of digits, letters, or hyphens. + +define(__NAMESPACE__.'\\BUILDIDENTIFIER', $R++); +Exports::$src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'; + +// ## Build Metadata +// Plus sign, followed by one or more period-separated build metadata +// identifiers. + +define(__NAMESPACE__.'\\BUILD', $R++); +Exports::$src[BUILD] = '(?:\\+(' . Exports::$src[BUILDIDENTIFIER] . + '(?:\\.' . Exports::$src[BUILDIDENTIFIER] . ')*))'; + + +// ## Full Version String +// A main version, followed optionally by a pre-release version and +// build metadata. + +// Note that the only major, minor, patch, and pre-release sections of +// the version string are capturing groups. The build metadata is not a +// capturing group, because it should not ever be used in version +// comparison. + +define(__NAMESPACE__.'\\FULL', $R++); +define(__NAMESPACE__.'\\FULLPLAIN','v?' . Exports::$src[MAINVERSION] . + Exports::$src[PRERELEASE] . '?' . + Exports::$src[BUILD] . '?'); + +Exports::$src[FULL] = '^' . FULLPLAIN . '$'; + +// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. +// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty +// common in the npm registry. +define(__NAMESPACE__.'\\LOOSEPLAIN', '[v=\\s]*' . Exports::$src[MAINVERSIONLOOSE] . + Exports::$src[PRERELEASELOOSE] . '?' . + Exports::$src[BUILD] . '?'); + +define(__NAMESPACE__.'\\LOOSE', $R++); +Exports::$src[LOOSE] = '^' . LOOSEPLAIN . '$'; + +define(__NAMESPACE__.'\\GTLT', $R++); +Exports::$src[GTLT] = '((?:<|>)?=?)'; + +// Something like "2.*" or "1.2.x". +// Note that "x.x" is a valid xRange identifer, meaning "any version" +// Only the first item is strictly required. +define(__NAMESPACE__.'\\XRANGEIDENTIFIERLOOSE', $R++); +Exports::$src[XRANGEIDENTIFIERLOOSE] = Exports::$src[NUMERICIDENTIFIERLOOSE] . '|x|X|\\*'; +define(__NAMESPACE__.'\\XRANGEIDENTIFIER', $R++); +Exports::$src[XRANGEIDENTIFIER] = Exports::$src[NUMERICIDENTIFIER] . '|x|X|\\*'; + +define(__NAMESPACE__.'\\XRANGEPLAIN', $R++); +Exports::$src[XRANGEPLAIN] = '[v=\\s]*(' . Exports::$src[XRANGEIDENTIFIER] . ')' . + '(?:\\.(' . Exports::$src[XRANGEIDENTIFIER] . ')' . + '(?:\\.(' . Exports::$src[XRANGEIDENTIFIER] . ')' . + '(?:(' . Exports::$src[PRERELEASE] . ')' . + ')?)?)?'; + +define(__NAMESPACE__.'\\XRANGEPLAINLOOSE', $R++); +Exports::$src[XRANGEPLAINLOOSE] = '[v=\\s]*(' . Exports::$src[XRANGEIDENTIFIERLOOSE] . ')' . + '(?:\\.(' . Exports::$src[XRANGEIDENTIFIERLOOSE] . ')' . + '(?:\\.(' . Exports::$src[XRANGEIDENTIFIERLOOSE] . ')' . + '(?:(' . Exports::$src[PRERELEASELOOSE] . ')' . + ')?)?)?'; + +// >=2.x, for example, means >=2.0.0-0 +// <1.x would be the same as "<1.0.0-0", though. +define(__NAMESPACE__.'\\XRANGE', $R++); +Exports::$src[XRANGE] = '^' . Exports::$src[GTLT] . '\\s*' . Exports::$src[XRANGEPLAIN] . '$'; +define(__NAMESPACE__.'\\XRANGELOOSE', $R++); +Exports::$src[XRANGELOOSE] = '^' . Exports::$src[GTLT] . '\\s*' . Exports::$src[XRANGEPLAINLOOSE] . '$'; + +// Tilde ranges. +// Meaning is "reasonably at or greater than" +define(__NAMESPACE__.'\\LONETILDE', $R++); +Exports::$src[LONETILDE] = '(?:~>?)'; + +define(__NAMESPACE__.'\\TILDETRIM', $R++); +Exports::$src[TILDETRIM] = '(\\s*)' . Exports::$src[LONETILDE] . '\\s+'; +Exports::$re[TILDETRIM] = new RegExp(Exports::$src[TILDETRIM], 'g'); +define(__NAMESPACE__.'\\tildeTrimReplace', '$1~'); + +define(__NAMESPACE__.'\\TILDE', $R++); +Exports::$src[TILDE] = '^' . Exports::$src[LONETILDE] . Exports::$src[XRANGEPLAIN] . '$'; +define(__NAMESPACE__.'\\TILDELOOSE', $R++); +Exports::$src[TILDELOOSE] = '^' . Exports::$src[LONETILDE] . Exports::$src[XRANGEPLAINLOOSE] . '$'; + +// Caret ranges. +// Meaning is "at least and backwards compatible with" +define(__NAMESPACE__.'\\LONECARET', $R++); +Exports::$src[LONECARET] = '(?:\\^)'; + +define(__NAMESPACE__.'\\CARETTRIM', $R++); +Exports::$src[CARETTRIM] = '(\\s*)' . Exports::$src[LONECARET] . '\\s+'; +Exports::$re[CARETTRIM] = new RegExp(Exports::$src[CARETTRIM], 'g'); +define(__NAMESPACE__.'\\caretTrimReplace', '$1^'); + +define(__NAMESPACE__.'\\CARET', $R++); +Exports::$src[CARET] = '^' . Exports::$src[LONECARET] . Exports::$src[XRANGEPLAIN] . '$'; +define(__NAMESPACE__.'\\CARETLOOSE', $R++); +Exports::$src[CARETLOOSE] = '^' . Exports::$src[LONECARET] . Exports::$src[XRANGEPLAINLOOSE] . '$'; + +// A simple gt/lt/eq thing, or just "" to indicate "any version" +define(__NAMESPACE__.'\\COMPARATORLOOSE', $R++); +Exports::$src[COMPARATORLOOSE] = '^' . Exports::$src[GTLT] . '\\s*(' . LOOSEPLAIN . ')$|^$'; +define(__NAMESPACE__.'\\COMPARATOR', $R++); +Exports::$src[COMPARATOR] = '^' . Exports::$src[GTLT] . '\\s*(' . FULLPLAIN . ')$|^$'; + + +// An expression to strip any whitespace between the gtlt and the thing +// it modifies, so that `> 1.2.3` ==> `>1.2.3` +define(__NAMESPACE__.'\\COMPARATORTRIM', $R++); +Exports::$src[COMPARATORTRIM] = '(\\s*)' . Exports::$src[GTLT] . + '\\s*(' . LOOSEPLAIN . '|' . Exports::$src[XRANGEPLAIN] . ')'; + +// this one has to use the /g flag +Exports::$re[COMPARATORTRIM] = new RegExp(Exports::$src[COMPARATORTRIM], 'g'); +define(__NAMESPACE__.'\\comparatorTrimReplace', '$1$2$3'); + + +// Something like `1.2.3 - 1.2.4` +// Note that these all use the loose form, because they'll be +// checked against either the strict or loose comparator form +// later. +define(__NAMESPACE__.'\\HYPHENRANGE', $R++); +Exports::$src[HYPHENRANGE] = '^\\s*(' . Exports::$src[XRANGEPLAIN] . ')' . + '\\s+-\\s+' . + '(' . Exports::$src[XRANGEPLAIN] . ')' . + '\\s*$'; + +define(__NAMESPACE__.'\\HYPHENRANGELOOSE', $R++); +Exports::$src[HYPHENRANGELOOSE] = '^\\s*(' . Exports::$src[XRANGEPLAINLOOSE] . ')' . + '\\s+-\\s+' . + '(' . Exports::$src[XRANGEPLAINLOOSE] . ')' . + '\\s*$'; + +// Star ranges basically just allow anything at all. +define(__NAMESPACE__.'\\STAR', $R++); +Exports::$src[STAR] = '(<|>)?=?\\s*\\*'; + +for($i = 0; $i < $R; $i++) { + if(!isset(Exports::$re[$i])) + Exports::$re[$i] = new RegExp(Exports::$src[$i]); +} + +/** + * + * @param String $version + * @param bool $loose + * @return SemVer|null + */ +function parse(String $version, $loose = false) +{ + $r = $loose?Exports::$re[LOOSE]:Exports::$re[FULL]; + /* @var $r \vierbergenlars\LibJs\RexExp */ + return ($r->test($version))? new SemVer($version, $loose):null; +} + +/** + * @param String $version + * @param bool $loose + * @return String|null + */ +function valid(String $version, $loose = false) +{ + $v = parse($version, $loose); + return $v?$v->version:null; +} + +/** + * @param String $version + * @param bool $loose + * @return String|null + */ +function clean(String $version, $loose = false) +{ + $s = parse($version, $loose); + return $s?$s->version:null; +} + +class SemVer extends Object +{ + /** + * @var String + */ + public $version; + + /** + * @var bool + */ + public $loose; + + /** + * @var String + */ + public $raw; + + /** + * + * @var int + */ + public $major; + + /** + * + * @var int + */ + public $minor; + + /** + * + * @var int + */ + public $patch; + + /** + * + * @var JSArray + */ + public $prerelease; + + /** + * + * @var JSArray + */ + public $build; + + /** + * @param SemVer|String|string $version + * @param bool $loose + */ + public function __construct($version, $loose = false) + { + $this->loose = $loose; + if($version instanceof SemVer) { + $this->version = $version->version; + return; + } + + $version = new String($version); + + $m = $version->trim()->match($loose?Exports::$re[LOOSE]:Exports::$re[FULL]); + + if(!$m) + throw new \RuntimeException('Invalid Version: '.$version); + + $this->raw = $version; + + // these are actually numbers + $this->major = (int)$m[1]->valueOf(); + $this->minor = (int)$m[2]->valueOf(); + $this->patch = (int)$m[3]->valueOf(); + + // numberify any prerelease numeric ids + if (!$m[4]) + $this->prerelease = new JSArray(); + else + $this->prerelease = $m[4]->split('.')->map(function($id) { + return (is_numeric($id->valueOf())) ? (int)$id->valueOf() : $id; + }); + + $this->build = $m[5]?$m[5]->split('.') : new JSArray(); + + $this->format(); + } + + public function format() + { + $this->version = new String($this->major . '.' . $this->minor . '.' . $this->patch); + if ($this->prerelease->length) + $this->version = $this->version->concat('-', $this->prerelease->join('.')); + return $this->version; + } + + public function inspect() + { + return '<SemVer "'.$this.'">'; + } + + public function __toString() + { + return $this->version->valueOf(); + } + + public function compare($other) + { + if(!$other instanceof SemVer) + $other = new SemVer($other, $this->loose); + return Util::JSor($this->compareMain($other),$this->comparePre($other)); + } + + public function compareMain($other) + { + if(!$other instanceof SemVer) + $other = new SemVer($other, $this->loose); + return Util::JSor(compareIdentifiers($this->major, $other->major), + compareIdentifiers($this->minor, $other->minor), + compareIdentifiers($this->patch, $other->patch)); + } + + public function comparePre($other) + { + if(!$other instanceof SemVer) + $other = new SemVer($other, $this->loose); + + // NOT having a prerelease is > having one + if($this->prerelease->length && !$other->prerelease->length) + return -1; + else if(!$this->prerelease->length && $other->prerelease->length) + return 1; + else if(!$this->prerelease->length && !$other->prerelease->length) + return 0; + + $i = 0; + do { + $a = $this->prerelease[$i]; + if($a instanceof String) $a = $a->valueOf(); + $b = $other->prerelease[$i]; + if($b instanceof String) $b = $b->valueOf(); + + if ($a === null && $b === null) + return 0; + else if ($b === null) + return 1; + else if ($a === null) + return -1; + else if ($a === $b) + continue; + else + return compareIdentifiers($a, $b); + } while (++$i); + } + + /** + * @param string $release + * @return SemVer + */ + public function inc($release) + { + switch ($release) { + case 'major': + $this->major++; + $this->minor = -1; + case 'minor': + $this->minor++; + $this->patch = -1; + case 'patch': + $this->patch++; + $this->prerelease = new JSArray(); + break; + case 'prerelease': + if ($this->prerelease->length === 0) + $this->prerelease = new JSArray(array(0)); + else { + $i = $this->prerelease->length; + while (--$i >= 0) { + if (is_numeric($this->prerelease[$i])) { + $this->prerelease[$i] = $this->prerelease[$i] + 1; + $i = -2; + } + } + if ($i === -1) // didn't increment anything + $this->prerelease->push(0); + } + break; + + default: + throw new \LogicException('invalid increment argument: ' .$release); + } + $this->format(); + return $this; + } +} + +function inc($version, $release, $loose = false) +{ + try { + $s = new SemVer($version, $loose); + return (string)$s->inc($release)->version; + } catch(\Exception $e) { + return null; + } +} + +function compareIdentifiers($a, $b) +{ + $anum = is_numeric($a); + $bnum = is_numeric($b); + + if($anum && $bnum) { + $a = (int)$a; + $b = (int)$b; + } + + if($anum && !$bnum) + return -1; + elseif($bnum && !$anum) + return 1; + elseif($a < $b) + return -1; + elseif($a > $b) + return 1; + else + return 0; +} + +function rcompareIdentifiers($a, $b) +{ + return compareIdentifiers($b, $a); +} + +function compare($a, $b, $loose = false) +{ + $s = new SemVer($a, $loose); + return $s->compare($b); +} + +function compareLoose($a, $b) +{ + return compare($a, $b, true); +} + +function rcompare($a, $b, $loose = false) +{ + return compare($b, $a, $loose); +} + +function semver_sort(JSArray $list, $loose = false) +{ + return $list->sort(function ($a, $b) use($loose) { + return compare($a, $b, $loose); + }); +} + +function semver_rsort(JSArray $list, $loose = false) +{ + return $list->sort(function($a, $b)use($loose) { + return rcompare($a, $b, $loose); + }); +} + +function gt($a, $b, $loose = false) +{ + return compare($a, $b, $loose) > 0; +} + +function lt($a, $b, $loose = false) +{ + return compare($a, $b, $loose) < 0; +} + +function eq($a, $b, $loose = false) +{ + return compare($a, $b, $loose) === 0; +} + +function neq($a, $b, $loose = false) +{ + return compare($a, $b, $loose) !== 0; +} + +function gte($a, $b, $loose = false) +{ + return compare($a, $b, $loose) >= 0; +} + +function lte($a, $b, $loose = false) +{ + return compare($a, $b, $loose) <= 0; +} + +function cmp($a, $op, $b, $loose = false) +{ + if($op instanceof String) + $op = $op->valueOf(); + switch ($op) { + case '===': $ret = $a === $b; break; + case '!==': $ret = $a !== $b; break; + case '': case '=': case '==': $ret = eq($a, $b, $loose); break; + case '!=': $ret = neq($a, $b, $loose); break; + case '>': $ret = gt($a, $b, $loose); break; + case '>=': $ret = gte($a, $b, $loose); break; + case '<': $ret = lt($a, $b, $loose); break; + case '<=': $ret = lte($a, $b, $loose); break; + default: throw new \LogicException('Invalid operator: ' . $op); + } + return $ret; +} + +class Comparator extends Object +{ + /** + * @var String + */ + public $value; + + /** + * @var bool + */ + public $loose; + + /** + * @var SemVer|null + */ + public $semver; + + /** + * @var String + */ + public $operator; + + public function __construct($comp, $loose = false) + { + $this->loose = $loose; + if($comp instanceof Comparator) + $comp = $comp->value; + + $comp = new String($comp); + + $this->parse($comp); + + if(!$this->semver instanceof SemVer) + $this->value = new String(''); + else + $this->value = new String($this->operator.$this->semver->version); + } + + public function parse(String $comp) + { + $r = $this->loose?Exports::$re[COMPARATORLOOSE]:Exports::$re[COMPARATOR]; + $m = $comp->match($r); + + if(!$m) + throw new \RuntimeException('Invalid comparator: '.$comp); + + $this->operator = $m[1]; + if(!$m[2]) + $this->semver = null; + else { + $this->semver = new SemVer($m[2], $this->loose); + + // <1.2.3-rc DOES allow 1.2.3-beta (has prerelease) + // >=1.2.3 DOES NOT allow 1.2.3-beta + // <=1.2.3 DOES allow 1.2.3-beta + // However, <1.2.3 does NOT allow 1.2.3-beta, + // even though `1.2.3-beta < 1.2.3` + // The assumption is that the 1.2.3 version has something you + // *don't* want, so we push the prerelease down to the minimum. + if ($this->operator->valueOf() === '<' && !$this->semver->prerelease->length) { + $this->semver->prerelease = new JSArray(array(0)); + $this->semver->format(); + } + } + } + + public function inspect() + { + return '<SemVer Comparator "'.$this.'">'; + } + + public function __toString() + { + return $this->value->valueOf(); + } + + public function test($version) + { + return ($this->semver == null) ? true: + cmp($version, $this->operator, $this->semver, $this->loose); + } +} + +class Range extends Object +{ + /** + * @var bool + */ + public $loose; + + /** + * @var String + */ + public $raw; + + /** + * @var JSArray + */ + public $set; + + /** + * + * @var String + */ + public $range; + + public function __construct($range, $loose = false) + { + $this->loose = $loose; + if($range instanceof Range) + $range = $range->raw; + + $range = new String($range); + + $this->raw = $range; + + $that = $this; + // First, split based on boolean or || + $this->set = $range->split(new RegExp('\\s*\\|\\|\\s*'))->map(function($range)use($that) { + return $that->parseRange($range->trim()); + })->filter(function($c) { + return $c->length; + }); + + if(!$this->set->length) { + throw new \RuntimeException('Invalid SemVer Range: ' . $range); + } + + $this->format(); + } + + public function inspect() + { + return '<SemVer Range "'.$this->raw.'">'; + } + + public function format() + { + $this->range = $this->set->map(function($comps) { + return $comps->join(' ')->trim(); + })->join('||')->trim(); + return $this->range; + } + + public function __toString() + { + return $this->range->valueOf(); + } + + public function parseRange(String $range) + { + $loose = $this->loose; + $range = $range->trim(); + // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` + $hr = $loose?Exports::$re[HYPHENRANGELOOSE]:Exports::$re[HYPHENRANGE]; + $range = $range->replace($hr, function() { + return call_user_func_array(__NAMESPACE__.'\\hyphenReplace', func_get_args()); + }); + + // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` + $range = $range->replace(Exports::$re[COMPARATORTRIM], comparatorTrimReplace); + + // `~ 1.2.3` => `~1.2.3` + $range = $range->replace(Exports::$re[TILDETRIM], tildeTrimReplace); + + // `^ 1.2.3` => `^1.2.3` + $range = $range->replace(Exports::$re[CARETTRIM], caretTrimReplace); + + // normalize spaces + $range = $range->split(new RegExp('\\s+'))->join(' '); + + // At this point, the range is completely trimmed and + // ready to be split into comparators. + + $compRe = $loose ? Exports::$re[COMPARATORLOOSE] : Exports::$re[COMPARATOR]; + $set = $range->split(' ')->map(function($comp) use($loose) { + return parseComparator($comp, $loose); + })->join(' ')->split(new RegExp('\\s+')); + + if ($loose) { + // in loose mode, throw out any that are not valid comparators + $set = $set->filter(function($comp)use($compRe) { + return !!$comp->match($compRe); + }); + } + $set = $set->map(function($comp) use($loose) { + return new Comparator($comp, $loose); + }); + + + return $set; + } + + // Placed after hyphenReplace in JS source + public function test($version) + { + if(!$version) + return false; + for($i = 0; $i < $this->set->length; $i++) { + if(testSet($this->set[$i], $version)) + return true; + } + return false; + } +} + +function toComparators($range, $loose = false) +{ + $r = new Range($range, $loose); + return $r->set->map(function($comp) { + return $comp->map(function($c) { + return $c->value; + })->join(' ')->trim()->split(' '); + }); +} + +// comprised of xranges, tildes, stars, and gtlt's at this point. +// already replaced the hyphen ranges +// turn into a set of JUST comparators. +function parseComparator(String $comp, $loose = false) +{ + $comp = replaceCarets($comp, $loose); + $comp = replaceTildes($comp, $loose); + $comp = replaceXRanges($comp, $loose); + $comp = replaceStars($comp, $loose); + return $comp; +} + +function isX(String $id = null) +{ + return !$id || $id->toLowerCase()->valueOf() === 'x' || $id->valueOf() === '*'; +} + +// ~, ~> --> * (any, kinda silly) +// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 +// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 +// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 +// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 +// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 +function replaceTildes(String $comp, $loose = false) { + return $comp->trim()->split(new RegExp('\\s+'))->map(function($comp)use($loose) { + return replaceTilde($comp, $loose); + })->join(' '); +} + +function replaceTilde(String $comp, $loose = false) { + $r = $loose ? Exports::$re[TILDELOOSE] : Exports::$re[TILDE]; + return $comp->replace($r, function(String $_, String $M = null, String $m = null, String $p = null, String $pr = null) { + if (isX($M)) + $ret = ''; + else if (isX($m)) + $ret = '>=' . $M . '.0.0-0 <' . ((int)(string)$M + 1) . '.0.0-0'; + else if (isX($p)) + // ~1.2 == >=1.2.0- <1.3.0- + $ret = '>=' . $M . '.' . $m . '.0-0 <' . $M . '.' . ((int)(string)$m + 1) . '.0-0'; + else if ($pr) { + if ($pr->charAt(0) !== '-') + $pr = '-' . $pr; + $ret = '>=' . $M . '.' . $m . '.' . $p . $pr . + ' <' . $M . '.' . ((int)(string)$m + 1) . '.0-0'; + } else + // ~1.2.3 == >=1.2.3-0 <1.3.0-0 + $ret = '>=' . $M . '.' . $m . '.' . $p . '-0' . + ' <' . $M . '.' . ((int)(string)$m + 1) . '.0-0'; + + return $ret; + }); +} + +// ^ --> * (any, kinda silly) +// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 +// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 +// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 +// ^1.2.3 --> >=1.2.3 <2.0.0 +// ^1.2.0 --> >=1.2.0 <2.0.0 +function replaceCarets(String $comp, $loose = false) { + return $comp->trim()->split(new RegExp('\\s+'))->map(function($comp)use($loose) { + return replaceCaret($comp, $loose); + })->join(' '); +} + +function replaceCaret(String $comp, $loose = false) { + $r = $loose ? Exports::$re[CARETLOOSE] : Exports::$re[CARET]; + return $comp->replace($r, function(String $_, String $M = null, String $m = null, String $p = null, String $pr = null) { + if (isX($M)) + $ret = ''; + else if (isX($m)) + $ret = '>=' . $M . '.0.0-0 <' . ((int)(string)$M + 1) . '.0.0-0'; + else if (isX($p)) { + if ($M->valueOf() === '0') + $ret = '>=' . $M . '.' . $m . '.0-0 <' . $M . '.' . ((int)(string)$m + 1) . '.0-0'; + else + $ret = '>=' . $M . '.' . $m . '.0-0 <' . ((int)(string)$M + 1) . '.0.0-0'; + } else if ($pr) { + if ($pr->charAt(0) !== '-') + $pr = '-' . $pr; + if ($M->valueOf() === '0') { + if ($m->valueOf() === '0') + $ret = '=' . $M . '.' . $m . '.' . $p . $pr; + else + $ret = '>=' . $M . '.' . $m . '.' . $p . $pr . + ' <' . $M . '.' . ((int)(string)$m + 1) . '.0-0'; + } else + $ret = '>=' . $M . '.' . $m . '.' . $p . $pr . + ' <' . ((int)(string)$M + 1) . '.0.0-0'; + } else { + if ($M->valueOf() === '0') { + if ($m->valueOf() === '0') + $ret = '=' . $M . '.' . $m . '.' . $p; + else + $ret = '>=' . $M . '.' . $m . '.' . $p . '-0' . + ' <' . $M . '.' . ((int)(string)$m + 1) . '.0-0'; + } else + $ret = '>=' . $M . '.' . $m . '.' . $p . '-0' . + ' <' . ((int)(string)$M + 1) . '.0.0-0'; + } + + return $ret; + }); +} + +function replaceXRanges(String $comp, $loose = false) { + return $comp->split(new RegExp('\\s+'))->map(function($comp)use($loose) { + return replaceXRange($comp, $loose); + })->join(' '); +} + +function replaceXRange(String $comp, $loose = false) { + $comp = $comp->trim(); + $r = $loose ? Exports::$re[XRANGELOOSE] : Exports::$re[XRANGE]; + return $comp->replace($r, function(String $ret, String $gtlt, String $M = null, String $m = null, String $p = null, String $pr=null) { + $xM = isX($M); + $xm = $xM || isX($m); + $xp = $xm || isX($p); + $anyX = $xp; + $gtlt = (string)$gtlt; + + if ($gtlt === '=' && $anyX) + $gtlt = ''; + + if ($gtlt && $anyX) { + // replace X with 0, and then append the -0 min-prerelease + if ($xM) + $M = 0; + if ($xm) + $m = 0; + if ($xp) + $p = 0; + + if ($gtlt === '>') { + // >1 => >=2.0.0-0 + // >1.2 => >=1.3.0-0 + // >1.2.3 => >= 1.2.4-0 + $gtlt = '>='; + if ($xM) { + // no change + } else if ($xm) { + $M = (int)(string)$M + 1; + $m = 0; + $p = 0; + } else if ($xp) { + $m = (int)(string)$m + 1; + $p = 0; + } + } + + + $ret = $gtlt . $M . '.' . $m . '.' . $p . '-0'; + } else if ($xM) { + // allow any + $ret = '*'; + } else if ($xm) { + // append '-0' onto the version, otherwise + // '1.x.x' matches '2.0.0-beta', since the tag + // *lowers* the version value + $ret = '>=' . $M . '.0.0-0 <' . ((int)(string)$M + 1) . '.0.0-0'; + } else if ($xp) { + $ret = '>=' . $M . '.' . $m . '.0-0 <' . $M . '.' . ((int)(string)$m + 1) . '.0-0'; + } + + return $ret; + }); +} + +// Because * is AND-ed with everything else in the comparator, +// and '' means "any version", just remove the *s entirely. +function replaceStars(String $comp, $loose = false) { + // Looseness is ignored here. star is always as loose as it gets! + return $comp->trim()->replace(Exports::$re[STAR], ''); +} + +// This function is passed to string.replace(re[HYPHENRANGE]) +// M, m, patch, prerelease, build +// 1.2 - 3.4.5 => >=1.2.0-0 <=3.4.5 +// 1.2.3 - 3.4 => >=1.2.0-0 <3.5.0-0 Any 3.4.x will do +// 1.2 - 3.4 => >=1.2.0-0 <3.5.0-0 +function hyphenReplace(String $_, + String $from = null, String $fM = null, String $fm = null, String $fp = null, String $fpr = null, String $fb = null, + String $to = null, String $tM = null, String $tm = null, String $tp = null, String $tpr = null, String $tb = null) { + + if (isX($fM)) + $from = ''; + else if (isX($fm)) + $from = '>=' . $fM . '.0.0-0'; + else if (isX($fp)) + $from = '>=' . $fM . '.' . $fm . '.0-0'; + else + $from = '>=' . $from; + + if (isX($tM)) + $to = ''; + else if (isX($tm)) + $to = '<' . ((int)(string)$tM + 1) . '.0.0-0'; + else if (isX($tp)) + $to = '<' . $tM . '.' . ((int)(string)$tm + 1) . '.0-0'; + else if ($tpr) + $to = '<=' . $tM . '.' . $tm . '.' . $tp . '-' . $tpr; + else + $to = '<=' . $to; + + $s = new String($from.' '.$to); + return $s->trim(); +} + +// Range.prototype.test is moved to the Range object in PHP + +function testSet(JSArray $set, $version) { + for ($i = 0; $i < $set->length; $i++) { + if (!$set[$i]->test($version)) + return false; + } + return true; +} + +function satisfies($version, $range, $loose = false) +{ + try { + $range = new Range($range, $loose); + } catch(\Exception $e) { + return false; + } + return $range->test($version); +} + +function maxSatisfying(JSArray $versions, $range, $loose = false) +{ + return $versions->filter(function($version)use($range, $loose) { + return satisfies($version, $range, $loose); + })->sort(function($a, $b)use($loose) { + return rcompare($a, $b, $loose); + })->offsetGet(0); +} + +function validRange($range, $loose = false) { + try { + // Return '*' instead of '' so that truthiness works. + // This will throw if it's invalid anyway + $r = new Range($range, $loose); + return (string)Util::JSor($r->range, new String('*')); + } catch (\Exception $e) { + return null; + } +} + +// Determine if version is less than all the versions possible in the range +function ltr($version, $range, $loose = false) +{ + return outside($version, $range, '<', $loose); +} + +// Determine if version is greater than all the versions possible in the range. +function gtr($version, $range, $loose = false) +{ + return outside($version, $range, '>', $loose); +} + +function outside($version, $range, $hilo, $loose = false) +{ + $version = new SemVer($version, $loose); + $range = new Range($range, $loose); + + switch($hilo) { + case '>': + $gtfn = __NAMESPACE__.'\\gt'; + $ltefn = __NAMESPACE__.'\\lte'; + $ltfn = __NAMESPACE__.'\\lt'; + $comp = '>'; + $ecomp = '>='; + break; + case '<': + $gtfn = __NAMESPACE__.'\\lt'; + $ltefn = __NAMESPACE__.'\\gte'; + $ltfn = __NAMESPACE__.'\\gt'; + $comp = '<'; + $ecomp = '<='; + break; + default: + throw new \LogicException('Must provide a hilo val of "<" or ">"'); + } + + // If it satisifes the range it is not outside + if (satisfies($version, $range, $loose)) { + return false; + } + + // From now on, variable terms are as if we're in "gtr" mode. + // but note that everything is flipped for the "ltr" function. + + for ($i = 0; $i < $range->set->length; ++$i) { + $comparators = $range->set[$i]; + + $high = null; + $low = null; + + $comparators->JSforEach(function($comparator)use($loose,&$high,&$low) { + $high = Util::JSor($high, $comparator); + $low = Util::JSor($low, $comparator); + if (gtfn($comparator->semver, $high->semver, $loose)) { + $high = $comparator; + } else if (ltfn($comparator->semver, $low->semver, $loose)) { + $low = $comparator; + } + }); + + // If the edge version comparator has a operator then our version + // isn't outside it + if ($high->operator->valueOf() === $comp || $high->operator->valueOf() === $ecomp) { + return false; + } + + // If the lowest version comparator has an operator and our version + // is less than it then it isn't higher than the range + if ((!$low->operator->valueOf() || $low->operator->valueOf() === $comp) && + ltefn($version, $low->semver)) { + return false; + } else if ($low->operator->valueOf() === $ecomp && ltfn($version, $low->semver)) { + return false; + } + } + return true; +} diff --git a/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/SemVer/version.php b/core/update/update/vendor/vierbergenlars/php-semver/src/vierbergenlars/SemVer/version.php @@ -0,0 +1,263 @@ +<?php + +namespace vierbergenlars\SemVer; + +use vierbergenlars\SemVer\Internal\SemVer; +use vierbergenlars\SemVer\Internal\G; + +class version +{ + /** + * + * @var SemVer + */ + private $version; + + /** + * Initializes the version object with a simple version + * @param string $version A simple, single version string + * @param bool $loose + * @throws SemVerException + */ + public function __construct($version, $loose = false) + { + $this->version = new SemVer($version, $loose); + } + + /** + * Get the full version + * @return string + */ + public function getVersion() + { + return (string) $this->version; + } + + /** + * Get the major version number + * @return int + */ + public function getMajor() + { + return (int) $this->version->major; + } + + /** + * Get the minor version number + * @return int + */ + public function getMinor() + { + return (int) $this->version->minor; + } + + /** + * Get the patch version number + * @return int + */ + public function getPatch() + { + return (int) $this->version->patch; + } + + /** + * Get the build number + * @return array + */ + public function getBuild() + { + return (array) $this->version->build->valueOf(); + } + + /** + * Get the prerelease appended to the version + * @return array + */ + public function getPrerelease() + { + return (array) $this->version->prerelease->valueOf(); + } + + /** + * Returns a valid version + * @return string + * @see self::getVersion() + */ + public function valid() + { + return $this->getVersion(); + } + + /** + * Increment the version number + * @param string $what One of 'major', 'minor', 'patch' or 'prerelease' + * @return \vierbergenlars\SemVer\version + * @throws SemVerException When an invalid increment value is given + */ + public function inc($what) + { + $this->version->inc($what); + return $this; + } + + /** + * Checks whether this version satisfies an expression + * @param expression $versions The expression to check against + * @return bool + */ + public function satisfies(expression $versions) + { + return $versions->satisfiedBy($this); + } + + public function __toString() + { + return $this->getVersion(); + } + + /** + * Compare two versions + * @param string $v1 The first version + * @param string $cmp The comparator, one of '==', '!=', '>', '>=', '<', '<=', '===', '!==' + * @param string $v2 The second version + * @param bool $loose + * @return bool + * @throws UnexpectedValueException + */ + public static function cmp($v1, $cmp, $v2, $loose = false) + { + if($v1 instanceof self) + $v1 = $v1->getVersion(); + if($v2 instanceof self) + $v2 = $v2->getVersion(); + try { + return G::cmp($v1, $cmp, $v2, $loose); + } catch(\LogicException $e) { + throw new \UnexpectedValueException($e->getMessage(), $e->getCode(), $e); + } + } + + /** + * Checks ifa given string is greater than another + * @param string|version $v1 The first version + * @param string|version $v2 The second version + * @param bool $loose + * @return boolean + */ + public static function gt($v1, $v2, $loose = false) + { + if($v1 instanceof self) + $v1 = $v1->getVersion(); + if($v2 instanceof self) + $v2 = $v2->getVersion(); + return G::gt($v1, $v2, $loose); + } + + /** + * Checks ifa given string is greater than, or equal to another + * @param string|version $v1 The first version + * @param string|version $v2 The second version + * @param bool $loose + * @return boolean + */ + public static function gte($v1, $v2, $loose = false) + { + if($v1 instanceof self) + $v1 = $v1->getVersion(); + if($v2 instanceof self) + $v2 = $v2->getVersion(); + return G::gte($v1, $v2, $loose); + } + + /** + * Checks ifa given string is less than another + * @param string|version $v1 The first version + * @param string|version $v2 The second version + * @param bool $loose + * @return boolean + */ + public static function lt($v1, $v2, $loose = false) + { + if($v1 instanceof self) + $v1 = $v1->getVersion(); + if($v2 instanceof self) + $v2 = $v2->getVersion(); + return G::lt($v1, $v2, $loose); + } + + /** + * Checks ifa given string is less than, or equal to another + * @param string|version $v1 The first version + * @param string|version $v2 The second version + * @param bool $loose + * @return boolean + */ + public static function lte($v1, $v2, $loose = false) + { + if($v1 instanceof self) + $v1 = $v1->getVersion(); + if($v2 instanceof self) + $v2 = $v2->getVersion(); + return G::lte($v1, $v2, $loose); + } + + /** + * Checks ifa given string is equal to another + * @param string|version $v1 The first version + * @param string|version $v2 The second version + * @param bool $loose + * @return boolean + */ + public static function eq($v1, $v2, $loose = false) + { + if($v1 instanceof self) + $v1 = $v1->getVersion(); + if($v2 instanceof self) + $v2 = $v2->getVersion(); + return G::eq($v1, $v2, $loose); + } + + /** + * Checks ifa given string is not equal to another + * @param string|version $v1 The first version + * @param string|version $v2 The second version + * @param bool $loose + * @return boolean + */ + public static function neq($v1, $v2, $loose = false) + { + if($v1 instanceof self) + $v1 = $v1->getVersion(); + if($v2 instanceof self) + $v2 = $v2->getVersion(); + return G::neq($v1, $v2, $loose); + } + + /** + * Compares two versions, can be used with usort() + * @param string|version $v1 The first version + * @param string|version $v2 The second version + * @param bool $loose + * @return int 0 when they are equal, -1 ifthe second version is smaller, 1 ifthe second version is greater + */ + public static function compare($v1, $v2, $loose = false) + { + if($v1 instanceof self) + $v1 = $v1->getVersion(); + if($v2 instanceof self) + $v2 = $v2->getVersion(); + return G::compare($v1, $v2, $loose); + } + + /** + * Reverse compares two versions, can be used with usort() + * @param string|version $v1 The first version + * @param string|version $v2 The second version + * @param bool $loose + * @return int 0 when they are equal, 1 ifthe second version is smaller, -1 ifthe second version is greater + */ + public static function rcompare($v1, $v2, $loose = false) + { + return self::compare($v2, $v1, $loose); + } +} diff --git a/core/update/update/vendor/vierbergenlars/php-semver/tests/all_tests.php b/core/update/update/vendor/vierbergenlars/php-semver/tests/all_tests.php @@ -0,0 +1,14 @@ +<?php +namespace vierbergenlars\SemVer\Tests; +require_once __DIR__.'/../vendor/autoload.php'; +require_once __DIR__.'/../vendor/simpletest/simpletest/autorun.php'; +class RemoteCPVersioningTests extends \TestSuite +{ + public function __construct() + { + parent::__construct('RemoteCP Versioning System Tests'); + $this->addFile(__DIR__.'/base_test.php'); + $this->addFile(__DIR__.'/semver_test.php'); + $this->addFile(__DIR__.'/regression_test.php'); + } +} diff --git a/core/update/update/vendor/vierbergenlars/php-semver/tests/base_test.php b/core/update/update/vendor/vierbergenlars/php-semver/tests/base_test.php @@ -0,0 +1,259 @@ +<?php +namespace vierbergenlars\SemVer\Tests; +use vierbergenlars\SemVer; +require_once __DIR__.'/../vendor/autoload.php'; +require_once __DIR__.'/../vendor/simpletest/simpletest/autorun.php'; +class versioningTest extends \UnitTestCase +{ + public function testKeepSimpleversion() + { + $t=array( + '1.0.0', + '2.0.0', + '1.0.1', + '1.3.2', + '1.02.0'=>'1.2.0', + '0.2.5', + '01.2.6'=>'1.2.6', + '2.0.03'=>'2.0.3', + '0.0.0' + ); + foreach ($t as $original=>$result) { + if(!is_string($original)) $original=$result; + $v=new SemVer\version($original, true); + $this->assertEqual($v->__toString(),$result,'['.$original.'] %s'); + } + } + public function testKeepSimpleversionComparator() + { + $t=array( + '>1.0.0', + '>1.1.0', + '>1.2.3', + '>0.5.6', + '>0.025.6'=>'>0.25.6', + '>=1.0.0', + '>=1.2.0', + '>=1.4.5', + '>=0.9.3', + '>=05.3.6'=>'>=5.3.6', + '<2.0.0-0', + '<5.6.0-0', + '<2.3.5-0', + '<0.2.3-0', + '<0.2.05'=>'<0.2.5-0', + '<=7.0.0', + '<=1.3.0', + '<=1.4.3', + '<=0.2.6', + '<=00.05.6'=>'<=0.5.6' + ); + foreach ($t as $original=>$result) { + if(!is_string($original)) $original=$result; + $v=new SemVer\expression($original, true); + $this->assertEqual($v->getString(),$result,'['.$original.'] %s'); + } + } + public function testShortSimpleversion() + { + $t=array( + '1'=>'>=1.0.0-0 <2.0.0-0', + '1.2'=>'>=1.2.0-0 <1.3.0-0', + '1.0'=>'>=1.0.0-0 <1.1.0-0', + '501'=>'>=501.0.0-0 <502.0.0-0' + ); + foreach ($t as $original=>$result) { + $v=new SemVer\expression($original, true); + $this->assertEqual($v->getString(),$result,'['.$original.'] %s'); + } + } + public function testShortSimpleversionComparator() + { + $t=array( + '>1.0.0'=>'>1.0.0', + '<2.0.0'=>'<2.0.0-0', + '<=5.2'=>'<=5.2.0-0', + '>=3'=>'>=3.0.0-0' + ); + foreach ($t as $original=>$result) { + $v=new SemVer\expression($original, true); + $this->assertEqual($v->getString(),$result,'['.$original.'] %s'); + } + } + public function testSimpleversionWildcard() + { + $t=array( + '1.x.x'=>'>=1.0.0-0 <2.0.0-0', + '1.x'=>'>=1.0.0-0 <2.0.0-0', + '1.x.5'=>'>=1.0.0-0 <2.0.0-0', + '3.x'=>'>=3.0.0-0 <4.0.0-0', + '1.X.X'=>'>=1.0.0-0 <2.0.0-0', + '1.*.*'=>'>=1.0.0-0 <2.0.0-0', + '2.X.x'=>'>=2.0.0-0 <3.0.0-0', + '5.*.x'=>'>=5.0.0-0 <6.0.0-0', + 'x'=>'' + ); + foreach ($t as $original=>$result) { + $v=new SemVer\expression($original, true); + $this->assertEqual($v->getString(),$result,'['.$original.'] %s'); + } + } + public function testSimpleversionRange() + { + $t=array( + '1.0.0 - 2.0.0'=>'>=1.0.0 <=2.0.0', + '1.2.3 - 1.3.0'=>'>=1.2.3 <=1.3.0', + '4.3.0 - 4.3.1'=> '>=4.3.0 <=4.3.1' + ); + foreach ($t as $original=>$result) { + $v=new SemVer\expression($original, true); + $this->assertEqual($v->getString(),$result,'['.$original.'] %s'); + } + } + public function testShortversionRange() + { + $t=array( + '1 - 2'=>'>=1.0.0-0 <3.0.0-0', + '1.2 - 2.1'=>'>=1.2.0-0 <2.2.0-0' + ); + foreach ($t as $original=>$result) { + $v=new SemVer\expression($original, true); + $this->assertEqual($v->getString(),$result,'['.$original.'] %s'); + } + } + public function testSpermies() + { + $t=array( + '~1'=>'>=1.0.0-0 <2.0.0-0', + '~2.3'=>'>=2.3.0-0 <2.4.0-0', + '~3.7.2'=>'>=3.7.2-0 <3.8.0-0', + '~1.x'=>'>=1.0.0-0 <2.0.0-0', + '~1.2.x'=>'>=1.2.0-0 <1.3.0-0', + ); + foreach ($t as $original=>$result) { + $v=new SemVer\expression($original, true); + $this->assertEqual($v->getString(),$result,'['.$original.'] %s'); + } + } + public function testInvalidVersion() + { + $t=array( + '3.x2', + 'xx', + '2.xx', + '**.2', + 'Xx*', + '.2.2', + '1..2', + '1.5.6.x', + '1.5.6.7' + ); + foreach ($t as $original) { + $ex = false; + try { + $v=new SemVer\expression($original); + } catch(SemVer\SemVerException $e) { + $ex = true; + } + $this->assertTrue($ex); + } + } + public function testComplexExpessions() + { + $t=array( + '1.x || 2.0 - 2.3 || >4.x.x'=>'>=1.0.0-0 <2.0.0-0||>=2.0.0-0 <2.4.0-0||>=5.0.0-0', + '2.0.x || 2.1 - 4 || 4 - 4.5' => '>=2.0.0-0 <2.1.0-0||>=2.1.0-0 <5.0.0-0||>=4.0.0-0 <4.6.0-0' + ); + foreach ($t as $original=>$result) { + $v=new SemVer\expression($original, true); + $this->assertEqual($v->getString(),$result,'['.$original.'] %s'); + } + } + public function testSatisfiedBy() + { + $t=array( + '1.0.0'=>'1.0.0', + '1.2.3'=>'1.2.3', + '>=1.0.1'=>array('1.0.1','1.0.2','1.2.0','2.0.0'), + '>=2'=>array('2.0.0','2.0.1','2.1.5','3.0.0'), + '<=2.4'=>array('1.2.0','2.0.0','2.3.999999999999'), + '3.x'=>array('3.0.1','3.2.0','3.1.5'), + '1.5.6 - 2.3.4'=>array('1.5.6','1.5.7','1.6.0','2.1.0','2.3.0','2.3.3','2.3.4'), + '1 - 2 || >=2.0.5'=>array('1.0.0','2.1.0','1.4.0','1.0.2','3.0.4','2.0.6','3.0.0'), + '>4.0.0 <=4.2.3'=>array('4.0.1','4.1.2','4.2.3','4.1.0') + ); + foreach ($t as $range=>$satisfies) { + $e=new SemVer\expression($range, true); + if (!is_array($satisfies)) { + $satisfies=array($satisfies); + } + foreach ($satisfies as $version) { + $v=new SemVer\version($version, true); + $this->assertTrue($e->satisfiedBy($v), '['.$range.' :: '.$version.'] %s'); + $this->assertTrue($v->satisfies($e), '['.$range.' :: '.$version.'] %s'); + } + } + } + public function testNotSatisfiedBy() + { + $t=array( + '1.0.0'=>'1.0.1', + '1.2.3'=>'2.0.0', + '<1.0.1'=>array('1.0.1','1.0.2','1.2.0','2.0.0'), + '<=2'=>array('2.0.1','2.1.5','3.0.0'), + '>=2.4'=>array('1.2.0','2.0.0'), + '3.x'=>array('1.0.0','1.9.9','2.999.9999','4.0.0'), + '<1.5.6 || >=2.3.4 <3.0.0'=>array('1.5.6','1.5.7','1.6.0','2.1.0','2.3.0','2.3.3','3.0.0','3.2.1'), + '1.2.0 - 2.1.2'=>array('1.1.2','2.2.0'), + '>4.0.0 <=4.2.3'=>array('4.0.0','4.2.4','4.5.0','3.2.2') + ); + foreach ($t as $range=>$satisfies) { + $e=new SemVer\expression($range, true); + if (!is_array($satisfies)) { + $satisfies=array($satisfies); + } + foreach ($satisfies as $version) { + $v=new SemVer\version($version, true); + $this->assertFalse($e->satisfiedBy($v), '['.$range.' :: '.$version.'] %s'); + $this->assertFalse($v->satisfies($e), '['.$range.' :: '.$version.'] %s'); + } + } + } + function testNoShitAsVersion() + { + $t=array ( + 'ce16575adbf06e5771b4bb4d5ac9609a685c1504', + 'faeih178.58498uinv-dibqo', + '1.2.vqosbie', + 'vce16575adbf06e5771b4bb4d5ac9609a685.c1504' + ); + foreach ($t as $version) { + $this->expectException(); + new SemVer\expression($version); + $this->expectException(); + new SemVer\version($version); + } + } + + function testVersionFunctions() + { + $t = array( + '1.0.0-alpha' => array('M'=>1, 'm'=>0, 'p'=>0, 'pr'=>array('alpha'), 'b'=>array()), + '1.0.0-alpha.1' => array('M'=>1, 'm'=>0, 'p'=>0, 'pr'=>array('alpha', 1), 'b'=>array()), + '1.0.0-0.3.7' => array('M'=>1, 'm'=>0, 'p'=>0, 'pr'=>array(0, 3, 7), 'b'=>array()), + '1.0.0-x.7.z.92' => array('M'=>1, 'm'=>0, 'p'=>0, 'pr'=>array('x', 7, 'z', 92), 'b'=>array()), + '1.0.0-alpha+001' => array('M'=>1, 'm'=>0, 'p'=>0, 'pr'=>array('alpha'), 'b'=>array('001')), + '1.2.3-alpha.2+02' => array('M'=>1, 'm'=>2, 'p'=>3, 'pr'=>array('alpha', 2), 'b'=>array('02')), + '1.2.3-a.3+02.5.a' => array('M'=>1, 'm'=>2, 'p'=>3, 'pr'=>array('a', 3), 'b'=>array('02', 5, 'a')), + + ); + foreach($t as $version => $parts) { + $v=new SemVer\version($version); + $this->assertEqual($v->getMajor(), $parts['M']); + $this->assertEqual($v->getMinor(), $parts['m']); + $this->assertEqual($v->getPatch(), $parts['p']); + $this->assertEqual($v->getPrerelease(), $parts['pr']); + $this->assertEqual($v->getBuild(), $parts['b']); + } + } +} diff --git a/core/update/update/vendor/vierbergenlars/php-semver/tests/regression_test.php b/core/update/update/vendor/vierbergenlars/php-semver/tests/regression_test.php @@ -0,0 +1,18 @@ +<?php +namespace vierbergenlars\SemVer\Tests; +use vierbergenlars\SemVer; +require_once __DIR__.'/../vendor/autoload.php'; +require_once __DIR__.'/../vendor/simpletest/simpletest/autorun.php'; +class regressionTest extends \UnitTestCase +{ + public function testBug23() + { + $this->assertTrue(SemVer\version::lt('3.0.0', '4.0.0-beta.1'), '3.0.0 < 4.0.0-beta.1 (Bug #23)'); + } + + public function testBug24() + { + $this->assertFalse(SemVer\version::gt('4.0.0-beta.9', '4.0.0-beta.10'), '4.0.0-beta.9 < 4.0.0-beta.10 (Bug #24)'); + } + +} diff --git a/core/update/update/vendor/vierbergenlars/php-semver/tests/semver_test.php b/core/update/update/vendor/vierbergenlars/php-semver/tests/semver_test.php @@ -0,0 +1,431 @@ +<?php +namespace vierbergenlars\SemVer\Tests\Internal; +use vierbergenlars\SemVer\Internal as SemVer; +require_once __DIR__.'/../vendor/autoload.php'; +require_once __DIR__.'/../vendor/simpletest/simpletest/autorun.php'; + +class SemVerTest extends \UnitTestCase +{ + public function testComparison() + { + $compare=array( + array("0.0.0","0.0.0-foo") + , array("0.0.1","0.0.0") + , array("1.0.0","0.9.9") + , array("0.10.0","0.9.0") + , array("0.99.0","0.10.0") + , array("2.0.0","1.2.3") + , array("v0.0.0","0.0.0-foo", true) + , array("v0.0.1","0.0.0", true) + , array("v1.0.0","0.9.9", true) + , array("v0.10.0","0.9.0", true) + , array("v0.99.0","0.10.0", true) + , array("v2.0.0","1.2.3", true) + , array("0.0.0","v0.0.0-foo", true) + , array("0.0.1","v0.0.0", true) + , array("1.0.0","v0.9.9", true) + , array("0.10.0","v0.9.0", true) + , array("0.99.0","v0.10.0", true) + , array("2.0.0","v1.2.3", true) + , array("1.2.3","1.2.3-asdf") + , array("1.2.3","1.2.3-4") + , array("1.2.3","1.2.3-4-foo") + , array("1.2.3-5-foo","1.2.3-5") + , array("1.2.3-5","1.2.3-4") + , array("1.2.3-5-foo","1.2.3-5-Foo") +// , array('1.2.3-0','1.2.3') + , array('3.0.0', '2.7.2+asdf') + , array('1.2.3-a.10', '1.2.3-a.5') + , array('1.2.3-a.b', '1.2.3-a.5') + , array('1.2.3-a.b', '1.2.3-a') + , array('1.2.3-a.b.c.10.d.5', '1.2.3-a.b.c.5.d.100') + ); + foreach ($compare as $set) { + $a=$set[0]; + $b=$set[1]; + $loose = isset($set[2])&&$set[2]; + $this->assertTrue(SemVer\G::gt($a, $b, $loose), "%s > gt('".$a."', '".$b."')"); + $this->assertTrue(SemVer\G::lt($b, $a, $loose), "%s > lt('".$b."', '".$a."')"); + $this->assertFalse(SemVer\G::gt($b, $a, $loose), "%s > !gt('".$b."', '".$a."')"); + $this->assertFalse(SemVer\G::lt($a, $b, $loose), "%s > !lt('".$a."', '".$b."')"); + $this->assertTrue(SemVer\G::eq($a, $a, $loose), "%s > eq('".$a."', '".$a."')"); + $this->assertTrue(SemVer\G::eq($b, $b, $loose), "%s > eq('".$b."', '".$b."')"); + $this->assertTrue(SemVer\G::neq($a, $b, $loose), "%s > neq('".$a."', '".$b."')"); + $this->assertTrue(SemVer\G::cmp($b, "==", $b, $loose), "%s > cmp('".$b."' == '".$b."')"); + $this->assertTrue(SemVer\G::cmp($a, ">=", $b, $loose), "%s > cmp('".$a."' >= '".$b."')"); + $this->assertTrue(SemVer\G::cmp($b, "<=", $a, $loose), "%s > cmp('".$b."' <= '".$a."')"); + $this->assertTrue(SemVer\G::cmp($a, "!=", $b, $loose), "%s > cmp('".$a."' != '".$b."')"); + } + } + public function testEquality() + { + $compare=array( + array("1.2.3","v1.2.3", true) + , array("1.2.3","=1.2.3", true) + , array("1.2.3","v 1.2.3", true) + , array("1.2.3","= 1.2.3", true) + , array("1.2.3"," v1.2.3", true) + , array("1.2.3"," =1.2.3", true) + , array("1.2.3"," v 1.2.3", true) + , array("1.2.3"," = 1.2.3", true) + , array("1.2.3-0","v1.2.3-0", true) + , array("1.2.3-0","=1.2.3-0", true) + , array("1.2.3-0","v 1.2.3-0", true) + , array("1.2.3-0","= 1.2.3-0", true) + , array("1.2.3-0"," v1.2.3-0", true) + , array("1.2.3-0"," =1.2.3-0", true) + , array("1.2.3-0"," v 1.2.3-0", true) + , array("1.2.3-0"," = 1.2.3-0", true) + , array("1.2.3-01","v1.2.3-1", true) + , array("1.2.3-01","=1.2.3-1", true) + , array("1.2.3-01","v 1.2.3-1", true) + , array("1.2.3-01","= 1.2.3-1", true) + , array("1.2.3-01"," v1.2.3-1", true) + , array("1.2.3-01"," =1.2.3-1", true) + , array("1.2.3-01"," v 1.2.3-1", true) + , array("1.2.3-01"," = 1.2.3-1", true) + , array("1.2.3-beta","v1.2.3-beta", true) + , array("1.2.3-beta","=1.2.3-beta", true) + , array("1.2.3-beta","v 1.2.3-beta", true) + , array("1.2.3-beta","= 1.2.3-beta", true) + , array("1.2.3-beta"," v1.2.3-beta", true) + , array("1.2.3-beta"," =1.2.3-beta", true) + , array("1.2.3-beta"," v 1.2.3-beta", true) + , array("1.2.3-beta"," = 1.2.3-beta", true) + , array("1.2.3-beta+build"," = 1.2.3-beta+otherbuild", true) + , array("1.2.3+build", " = 1.2.3+otherbuild", true) + , array("1.2.3-beta+build", "1.2.3-beta+otherbuild", true) + , array("1.2.3+build", "1.2.3+otherbuild") + , array("1.2.3+build", '1.2.3+otherbuild') + , array(" v1.2.3+build", "1.2.3+otherbuild") + + ); + foreach ($compare as $set) { + $a=$set[0]; + $b=$set[1]; + $loose = isset($set[2])&&$set[2]; + try { + $this->assertTrue(SemVer\G::eq($a, $b, $loose), "%s > eq('".$a."', '".$b."')"); + $this->assertFalse(SemVer\G::neq($a, $b, $loose), "%s > !neq('".$a."', '".$b."')"); + $this->assertTrue(SemVer\G::cmp($a, "==", $b, $loose), "%s > cmp(".$a."==".$b.")"); + $this->assertFalse(SemVer\G::cmp($a, "!=", $b, $loose), "%s > !cmp(".$a."!=".$b.")"); + $this->assertFalse(SemVer\G::cmp($a, "===", $b, $loose), "%s > !cmp(".$a."===".$b.")"); + $this->assertTrue(SemVer\G::cmp($a, "!==", $b, $loose), "%s > cmp(".$a."!==".$b.")"); + $this->assertFalse(SemVer\G::gt($a, $b, $loose), "%s > !gt('".$a."', '".$b."')"); + $this->assertTrue(SemVer\G::gte($a, $b, $loose), "%s > gte('".$a."', '".$b."')"); + $this->assertFalse(SemVer\G::lt($a, $b, $loose), "%s > !lt('".$a."', '".$b."')"); + $this->assertTrue(SemVer\G::lte($a, $b, $loose), "%s > lte('".$a."', '".$b."')"); + } catch(\Exception $e) { + $this->fail("Exception while comparing $set[0] and $set[1]"); + } + } + } + public function testRange() + { + $compare=array( + array("1.0.0 - 2.0.0","1.2.3") + , array("1.0.0","1.0.0") + , array(">=*","0.2.4") + , array("", "1.0.0") + , array("*","1.2.3") + , array('*', 'v1.2.3-foo', true) + , array(">=1.0.0","1.0.0") + , array(">=1.0.0","1.0.1") + , array(">=1.0.0","1.1.0") + , array(">1.0.0","1.0.1") + , array(">1.0.0","1.1.0") + , array("<=2.0.0","2.0.0") + , array("<=2.0.0","1.9999.9999") + , array("<=2.0.0","0.2.9") + , array("<2.0.0","1.9999.9999") + , array("<2.0.0","0.2.9") + , array(">= 1.0.0","1.0.0") + , array(">= 1.0.0","1.0.1") + , array(">= 1.0.0","1.1.0") + , array("> 1.0.0","1.0.1") + , array("> 1.0.0","1.1.0") + , array("<= 2.0.0","2.0.0") + , array("<= 2.0.0","1.9999.9999") + , array("<= 2.0.0","0.2.9") + , array("< 2.0.0","1.9999.9999") + , array("<\t2.0.0","0.2.9") + , array(">=0.1.97","v0.1.97", true) + , array(">=0.1.97","0.1.97") + , array("0.1.20 || 1.2.4","1.2.4") + , array(">=0.2.3 || <0.0.1","0.0.0") + , array(">=0.2.3 || <0.0.1","0.2.3") + , array(">=0.2.3 || <0.0.1","0.2.4") + , array("||","1.3.4") + , array("2.x.x","2.1.3") + , array("1.2.x","1.2.3") + , array("1.2.x || 2.x","2.1.3") + , array("1.2.x || 2.x","1.2.3") + , array("x","1.2.3") + , array("2.*.*","2.1.3") + , array("1.2.*","1.2.3") + , array("1.2.* || 2.*","2.1.3") + , array("1.2.* || 2.*","1.2.3") + , array("*","1.2.3") + , array("2","2.1.2") + , array("2.3","2.3.1") + , array("~2.4","2.4.0") // >=2.4.0 <2.5.0 + , array("~2.4","2.4.5") + , array("~>3.2.1","3.2.2") // >=3.2.1 <3.3.0 + , array("~1","1.2.3") // >=1.0.0 <2.0.0 + , array("~>1","1.2.3") + , array("~> 1","1.2.3") + , array("~1.0","1.0.2") // >=1.0.0 <1.1.0 + , array("~ 1.0","1.0.2") + , array("~1.0.3", "1.0.12") + , array(">=1","1.0.0") + , array(">= 1","1.0.0") + , array("<1.2","1.1.1") + , array("< 1.2","1.1.1") + , array("1","1.0.0beta", true) + , array("~v0.5.4-pre","0.5.5") + , array("~v0.5.4-pre","0.5.4") + , array('=0.7.x', '0.7.2') + , array('>=0.7.x', '0.7.2') + , array('=0.7.x', '0.7.0-asdf') + , array('>=0.7.x', '0.7.0-asdf') + , array('<=0.7.x', '0.6.2') + , array('~1.2.1 >=1.2.3', '1.2.3') + , array('~1.2.1 =1.2.3', '1.2.3') + , array('~1.2.1 1.2.3', '1.2.3') + , array('~1.2.1 >=1.2.3 1.2.3', '1.2.3') + , array('~1.2.1 1.2.3 >=1.2.3', '1.2.3') + , array('~1.2.1 1.2.3', '1.2.3') + , array('>=1.2.1 1.2.3', '1.2.3') + , array('1.2.3 >=1.2.1', '1.2.3') + , array('>=1.2.3 >=1.2.1', '1.2.3') + , array('>=1.2.1 >=1.2.3', '1.2.3') + , array('<=1.2.3', '1.2.3-beta') + , array('>1.2', '1.3.0-beta') + , array('>=1.2', '1.2.8') + , array('^1.2.3', '1.8.1') + , array('^1.2.3', '1.2.3-beta') + , array('^0.1.2', '0.1.2') + , array('^0.1', '0.1.2') + , array('^1.2', '1.4.2') + , array('^1.2 ^1', '1.4.2') + , array('^1.2', '1.2.0-pre') + , array('^1.2.3', '1.2.3-pre') + ); + foreach ($compare as $set) { + $loose = isset($set[2])&&$set[2]; + + $this->assertTrue(SemVer\G::satisfies($set[1], $set[0], $loose), "%s > $set[0] should be satisfied by $set[1]"); + } + + } + public function testNegativeRange() + { + $compare=array( + array("1.0.0 - 2.0.0","2.2.3") + , array("1.0.0","1.0.1") + , array(">=1.0.0","0.0.0") + , array(">=1.0.0","0.0.1") + , array(">=1.0.0","0.1.0") + , array(">1.0.0","0.0.1") + , array(">1.0.0","0.1.0") + , array("<=2.0.0","3.0.0") + , array("<=2.0.0","2.9999.9999") + , array("<=2.0.0","2.2.9") + , array("<2.0.0","2.9999.9999") + , array("<2.0.0","2.2.9") + , array(">=0.1.97","v0.1.93", true) + , array(">=0.1.97","0.1.93") + , array("0.1.20 || 1.2.4","1.2.3") + , array(">=0.2.3 || <0.0.1","0.0.3") + , array(">=0.2.3 || <0.0.1","0.2.2") + , array("2.x.x","1.1.3") + , array("2.x.x","3.1.3") + , array("1.2.x","1.3.3") + , array("1.2.x || 2.x","3.1.3") + , array("1.2.x || 2.x","1.1.3") + , array("2.*.*","1.1.3") + , array("2.*.*","3.1.3") + , array("1.2.*","1.3.3") + , array("1.2.* || 2.*","3.1.3") + , array("1.2.* || 2.*","1.1.3") + , array("2","1.1.2") + , array("2.3","2.4.1") + , array("~2.4","2.5.0") // >=2.4.0 <2.5.0 + , array("~2.4","2.3.9") + , array("~>3.2.1","3.3.2") // >=3.2.1 <3.3.0 + , array("~>3.2.1","3.2.0") // >=3.2.1 <3.3.0 + , array("~1","0.2.3") // >=1.0.0 <2.0.0 + , array("~>1","2.2.3") + , array("~1.0","1.1.0") // >=1.0.0 <1.1.0 + , array("<1","1.0.0") + , array(">=1.2","1.1.1") + , array("1","2.0.0beta", true) + , array("~v0.5.4-beta","0.5.4-alpha") + , array('<1', '1.0.0beta', true) + , array('< 1', '1.0.0beta', true) + , array('=0.7.x', '0.8.2') + , array('>=0.7.x', '0.6.2') + , array('<=0.7.x', '0.7.2') + , array('<1.2.3', '1.2.3-beta') + , array('=1.2.3', '1.2.3-beta') + , array('>1.2', '1.2.8') + , array('^1.2.3', '2.0.0-alpha') + , array('^1.2.3', '1.2.2') + , array('^1.2', '1.1.9') + // Invalid ranges are never satisfied + , array('blerg', '1.2.3') + , array('git+https://user:password0123@github.com/foo', '123.0.0', true) + , array('^1.2.3', '2.0.0-pre') + ); + foreach ($compare as $set) { + $loose = isset($set[2])&&$set[2]; + $this->assertFalse(SemVer\G::satisfies($set[1], $set[0], $loose), "%s > $set[0] should not be satisfied by $set[1]"); + } + } + public function testIncrementVersions() + { + $compare=array( + array("1.2.3","major","2.0.0") + , array("1.2.3","minor","1.3.0") + , array("1.2.3","patch","1.2.4") + , array("1.2.3tag", "major", "2.0.0", true) + , array("1.2.3-tag", "major", "2.0.0") + , array("1.2.3","fake",null) + , array("fake","major",null) + , array("1.2.3", "prerelease", "1.2.3-0") + , array("1.2.3-0", "prerelease", "1.2.3-1") + , array("1.2.3-alpha.0.beta", "prerelease", "1.2.3-alpha.1.beta") + , array("1.2.3-alpha.1.beta", "prerelease", "1.2.3-alpha.2.beta") + , array("1.2.3-alpha.2.beta", "prerelease", "1.2.3-alpha.3.beta") + , array("1.2.3-alpha.10.0.beta", "prerelease", "1.2.3-alpha.10.1.beta") + , array("1.2.3-alpha.10.1.beta", "prerelease", "1.2.3-alpha.10.2.beta") + , array("1.2.3-alpha.10.2.beta", "prerelease", "1.2.3-alpha.10.3.beta") + , array("1.2.3-alpha.10.beta.0", "prerelease", "1.2.3-alpha.10.beta.1") + , array("1.2.3-alpha.10.beta.1", "prerelease", "1.2.3-alpha.10.beta.2") + , array("1.2.3-alpha.10.beta.2", "prerelease", "1.2.3-alpha.10.beta.3") + , array("1.2.3-alpha.9.beta", "prerelease", "1.2.3-alpha.10.beta") + , array("1.2.3-alpha.10.beta", "prerelease", "1.2.3-alpha.11.beta") + , array("1.2.3-alpha.12.beta", "prerelease", "1.2.3-alpha.13.beta") + ); + foreach ($compare as $set) { + $s=$set[0]; + $loose = isset($set[3])&&$set[3]; + + $found = SemVer\G::inc($set[0],$set[1], $loose); + $this->assertEqual($found, $set[2]); + } + } + public function testValidRange() + { + $compare=array( + array("1.0.0 - 2.0.0",">=1.0.0 <=2.0.0") + , array("1.0.0","1.0.0") + , array(">=*",">=0.0.0-0") + , array("","*") + , array("*", "*") + , array(">=1.0.0",">=1.0.0") + , array(">1.0.0",">1.0.0") + , array("<=2.0.0","<=2.0.0") + , array("1",">=1.0.0-0 <2.0.0-0") + , array("<=2.0.0","<=2.0.0") + , array("<2.0.0","<2.0.0-0") + , array(">= 1.0.0",">=1.0.0") + , array(">= 1.0.0",">=1.0.0") + , array(">= 1.0.0",">=1.0.0") + , array("> 1.0.0",">1.0.0") + , array("> 1.0.0",">1.0.0") + , array("<= 2.0.0","<=2.0.0") + , array("<= 2.0.0","<=2.0.0") + , array("<= 2.0.0","<=2.0.0") + , array("< 2.0.0","<2.0.0-0") + , array("< 2.0.0","<2.0.0-0") + , array(">=0.1.97",">=0.1.97") + , array(">=0.1.97",">=0.1.97") + , array("0.1.20 || 1.2.4","0.1.20||1.2.4") + , array(">=0.2.3 || <0.0.1",">=0.2.3||<0.0.1-0") + , array(">=0.2.3 || <0.0.1",">=0.2.3||<0.0.1-0") + , array(">=0.2.3 || <0.0.1",">=0.2.3||<0.0.1-0") + , array("||","||") + , array("2.x.x",">=2.0.0-0 <3.0.0-0") + , array("1.2.x",">=1.2.0-0 <1.3.0-0") + , array("1.2.x || 2.x",">=1.2.0-0 <1.3.0-0||>=2.0.0-0 <3.0.0-0") + , array("x","*") + , array("2.*.*",'>=2.0.0-0 <3.0.0-0') + , array("1.2.*",'>=1.2.0-0 <1.3.0-0') + , array("1.2.* || 2.*",'>=1.2.0-0 <1.3.0-0||>=2.0.0-0 <3.0.0-0') + , array("*","*") + , array("2",">=2.0.0-0 <3.0.0-0") + , array("2.3",">=2.3.0-0 <2.4.0-0") + , array("~2.4",">=2.4.0-0 <2.5.0-0") + , array("~>3.2.1",">=3.2.1-0 <3.3.0-0") + , array("~1",">=1.0.0-0 <2.0.0-0") + , array("~>1",">=1.0.0-0 <2.0.0-0") + , array("~> 1",">=1.0.0-0 <2.0.0-0") + , array("~1.0",">=1.0.0-0 <1.1.0-0") + , array("~ 1.0",">=1.0.0-0 <1.1.0-0") + , array("^0", ">=0.0.0-0 <1.0.0-0") + , array("^ 1", ">=1.0.0-0 <2.0.0-0") + , array("^0.1", ">=0.1.0-0 <0.2.0-0") + , array("^1.0", ">=1.0.0-0 <2.0.0-0") + , array("^1.2", ">=1.2.0-0 <2.0.0-0") + , array("^0.0.1", "=0.0.1") + , array("^0.0.1-beta", "=0.0.1-beta") + , array("^0.1.2", ">=0.1.2-0 <0.2.0-0") + , array("^1.2.3", ">=1.2.3-0 <2.0.0-0") + , array("^1.2.3-beta.4", ">=1.2.3-beta.4 <2.0.0-0") + , array("<1","<1.0.0-0") + , array("< 1","<1.0.0-0") + , array(">=1",">=1.0.0-0") + , array(">= 1",">=1.0.0-0") + , array("<1.2","<1.2.0-0") + , array("< 1.2","<1.2.0-0") + , array("1", ">=1.0.0-0 <2.0.0-0") + , array(">01.02.03", ">1.2.3", true) + , array(">01.02.03", null) + , array("~1.2.3beta", ">=1.2.3-beta <1.3.0-0", true) + , array("~1.2.3beta", null) + , array("^ 1.2 ^ 1", ">=1.2.0-0 <2.0.0-0 >=1.0.0-0 <2.0.0-0") + ); + foreach ($compare as $set) { + $loose = isset($set[2])&&$set[2]; + + $this->assertEqual(SemVer\G::validRange($set[0], $loose), $set[1]); + } + } + + public function testStrictVsLoose() + { + $compare=array( + array('=1.2.3', '1.2.3') + , array('01.02.03', '1.2.3') + , array('1.2.3-beta.01', '1.2.3-beta.1') + , array(' =1.2.3', '1.2.3') + , array('1.2.3foo', '1.2.3-foo') + ); + + foreach($compare as $set) { + $ex = false; + try { + new SemVer\SemVer($set[0]); + } catch(\Exception $e) { + $ex = true; + } + $this->assertTrue($ex,"%s > Creating version with loose version $set[0], without loose flag set should throw exception."); + + $vers = new SemVer\SemVer($set[0], true); + + $this->assertEqual($vers->version->valueOf(), $set[1], "%s > (new version($set[0], true))->getVersion() == $set[1]"); + $this->assertTrue(SemVer\G::eq($set[0], $set[1], true), "%s > eq($set[0], $set[1], true)"); + + $ex = false; + try { + SemVer\G::eq($set[0], $set[1]); + } catch(\Exception $e) { + $ex = true; + } + $this->assertTrue($ex, "%s > eq($set[0], $set[1]) should throw"); + + } + + } +} diff --git a/themes/jumbotron/update.php b/themes/jumbotron/update.php @@ -4,10 +4,11 @@ ####################### header("Cache-Control: no-cache, must-revalidate, no-store"); -if(isset($_GET['update']) && function_exists($_GET['update'])) -call_user_func($_GET['update']); -else -echo "Function not found or wrong input"; +if(isset($_GET['update']) && function_exists($_GET['update'])){ + call_user_func($_GET['update']); +}else{ + echo "Function not found or wrong input"; +} function update(){ ############################### @@ -23,8 +24,9 @@ if ($root_3[1] == 'core') { }else{ $root = $root_1 . '/' . $root_3[1]; } + include($root . '/core/config/variables.config.php'); -include($root . '/core/update/update/update.php'); +include($root . '/core/update/update/vendor/autoload.php'); use \VisualAppeal\AutoUpdate; $update = new AutoUpdate($root . '/temp/', $root . '/', 60);