├── src ├── ClientAwareInterface.php ├── PluginContainerInterface.php ├── EventQueueFactoryInterface.php ├── EventEmitterAwareInterface.php ├── EventQueuePriority.php ├── PluginInterface.php ├── EventQueueFactoryAwareInterface.php ├── EventQueueInterface.php ├── PluginProcessor │ ├── PluginProcessorInterface.php │ ├── LoggerInjector.php │ ├── ClientInjector.php │ ├── EventEmitterInjector.php │ ├── EventQueueFactoryInjector.php │ └── LoopInjector.php ├── EventQueueInternal.php ├── EventQueueFactory.php ├── AbstractPlugin.php ├── Bot.php └── EventQueue.php ├── bin └── phergie ├── config.sample.php ├── composer.json ├── README.md ├── LICENSE ├── CONTRIBUTING.md └── composer.lock /src/ClientAwareInterface.php: -------------------------------------------------------------------------------- 1 | setConfig($config); 28 | $bot->run(); 29 | -------------------------------------------------------------------------------- /src/EventQueueInterface.php: -------------------------------------------------------------------------------- 1 | array( 10 | 11 | // new \Vendor\Plugin\PluginName(array( 12 | // /* configuration goes here */ 13 | // )), 14 | 15 | ), 16 | 17 | 'connections' => array( 18 | 19 | new Connection(array( 20 | 21 | // Required settings 22 | 23 | 'serverHostname' => 'irc.freenode.net', 24 | 'username' => 'Elazar', 25 | 'realname' => 'Matthew Turland', 26 | 'nickname' => 'Phergie3', 27 | 28 | // Optional settings 29 | 30 | // 'hostname' => 'user server name goes here if needed', 31 | // 'serverport' => 6667, 32 | // 'password' => 'password goes here if needed', 33 | // 'options' => array( 34 | // 'transport' => 'ssl', 35 | // 'force-ipv4' => true, 36 | // ) 37 | 38 | )), 39 | 40 | ) 41 | 42 | ); 43 | -------------------------------------------------------------------------------- /src/PluginProcessor/PluginProcessorInterface.php: -------------------------------------------------------------------------------- 1 | =5.6.0", 15 | "phergie/phergie-irc-client-react": "~3.1", 16 | "phergie/phergie-irc-connection": "~2.0", 17 | "phergie/phergie-irc-event": "~1.0", 18 | "evenement/evenement": "^3.0 || ^2.0", 19 | "monolog/monolog": "~1.6" 20 | }, 21 | "require-dev": { 22 | "phergie/phergie-irc-bot-react-development": "~1.0", 23 | "friendsofphp/php-cs-fixer": "^1.0" 24 | }, 25 | "autoload": { 26 | "psr-4": { 27 | "Phergie\\Irc\\Bot\\React\\": "src" 28 | } 29 | }, 30 | "autoload-dev": { 31 | "psr-4": { 32 | "Phergie\\Irc\\Tests\\Bot\\React\\": "tests" 33 | } 34 | }, 35 | "bin": [ 36 | "bin/phergie" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This project is abandoned 2 | 3 | This repo is being kept for posterity and will be archived in a readonly state. 4 | If you're interested it can be forked under a new Composer namespace/GitHub organization. 5 | 6 | # phergie/phergie-irc-bot-react 7 | 8 | A PHP-based IRC bot built on [React](http://reactphp.org). 9 | 10 | For installation, configuration, and development details, see [phergie.org](http://www.phergie.org/users/). 11 | 12 | [![Build Status](https://secure.travis-ci.org/phergie/phergie-irc-bot-react.png?branch=master)](http://travis-ci.org/phergie/phergie-irc-bot-react) 13 | [![Coverage Status](https://img.shields.io/coveralls/phergie/phergie-irc-bot-react.svg)](https://coveralls.io/r/phergie/phergie-irc-bot-react) 14 | [![Code Climate](https://codeclimate.com/github/phergie/phergie-irc-bot-react/badges/gpa.svg)](https://codeclimate.com/github/phergie/phergie-irc-bot-react) 15 | 16 | ## Design goals 17 | 18 | * Easy installation with minimal configuration 19 | * Low-friction plugin development 20 | * Informative logging of events for debugging 21 | * Use of third-party libraries where feasible 22 | * Simple easy-to-understand API 23 | 24 | ## License 25 | 26 | Released under the BSD License. See `LICENSE`. 27 | 28 | ## Community 29 | 30 | Check out #phergie on irc.freenode.net. 31 | -------------------------------------------------------------------------------- /src/PluginProcessor/LoggerInjector.php: -------------------------------------------------------------------------------- 1 | setLogger($bot->getLogger()); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Phergie Team 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /src/PluginProcessor/ClientInjector.php: -------------------------------------------------------------------------------- 1 | setClient($bot->getClient()); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/EventQueueInternal.php: -------------------------------------------------------------------------------- 1 | value - $priority2->value; 35 | if (!$priority) { 36 | $priority = $priority2->timestamp - $priority1->timestamp; 37 | } 38 | return $priority; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/PluginProcessor/EventEmitterInjector.php: -------------------------------------------------------------------------------- 1 | setEventEmitter($bot->getClient()); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/PluginProcessor/EventQueueFactoryInjector.php: -------------------------------------------------------------------------------- 1 | setEventQueueFactory($bot->getEventQueueFactory()); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/EventQueueFactory.php: -------------------------------------------------------------------------------- 1 | queues = new \SplObjectStorage; 35 | } 36 | 37 | /** 38 | * Returns the event queue for a specified connection. 39 | * 40 | * @param \Phergie\Irc\ConnectionInterface $connection 41 | * @return \Phergie\Irc\Bot\React\EventQueueInterface 42 | */ 43 | public function getEventQueue(ConnectionInterface $connection) 44 | { 45 | if (!isset($this->queues[$connection])) { 46 | $this->queues[$connection] = new EventQueue; 47 | } 48 | return $this->queues[$connection]; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/PluginProcessor/LoopInjector.php: -------------------------------------------------------------------------------- 1 | getClient(); 37 | if ($plugin instanceof LoopAwareInterface 38 | && $client instanceof LoopAccessorInterface) { 39 | $plugin->setLoop($client->getLoop()); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Phergie 2 | 3 | We welcome contributions. 4 | 5 | ## Team members 6 | 7 | * [Matthew Turland](https://github.com/elazar) - original author and adviser 8 | * [Matthew Trask](https://github.com/rocketpastsix) - contributor, co-maintainer 9 | * [Joe Ferguson](https://github.com/svpernova09) - contributor, co-maintainer 10 | 11 | ## Communication Channels 12 | 13 | You can find help and discussion in the following places: 14 | 15 | * Website: 16 | * #phergie on Freenode: 17 | * Github Issues: 18 | 19 | ## Community 20 | 21 | The Phergie team believes heavily in the [PHP Mentoring](http://www.phpmentoring) project. 22 | We believe open source projects should be welcoming to newcomers and veteran contributors alike. 23 | We all actively work to provide a positive collaborative environment and to foster learning. 24 | 25 | ## Project Breakdown 26 | 27 | The Phergie project is broken into different repositories for parts of the application. 28 | The core bot is in this repo. Plugins are in their own repositories. 29 | 30 | The Phergie team maintains many plugins under the Phergie organization while other contributors maintain their own plugins. 31 | 32 | ## Have Questions? 33 | 34 | Feel free to open a issue on the appropriate repository, not sure? open an issue here. 35 | 36 | Join us on the Freenode IRC network in channel #phergie 37 | 38 | ## Code Style 39 | 40 | We have adopted [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) as the primary style guide. 41 | 42 | We have a `.php_cs` configuration file for [php-cs-fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer) 43 | 44 | We have also established a few style guidelines we strive for: 45 | 46 | * Four space indention 47 | * Methods, Properties, and Variables should be camelCase 48 | * Short array syntax 49 | * K&R braces (including elseif/else) 50 | * Chained method calls should be indented 51 | * See [Our Style Discussion](https://github.com/phergie/phergie-irc-bot-react/issues/20) For more. 52 | 53 | ## Reporting Bugs 54 | 55 | Bugs are tracked in our project's [issue tracker](https://github.com/ramsey/uuid/issues). 56 | 57 | When submitting a bug report, please include enough information for us to reproduce the bug. A good bug report includes the following sections: 58 | 59 | * Expected outcome 60 | * Actual outcome 61 | * Steps to reproduce, including sample code 62 | * Any other information that will help us debug and reproduce the issue, including stack traces, system/environment information, and screenshots 63 | 64 | **Please do not include passwords or any personally identifiable information in your bug report and sample code.** 65 | 66 | ## Fixing Bugs 67 | 68 | We welcome pull requests to fix bugs! 69 | 70 | If you see a bug report that you'd like to fix, please feel free to do so. Following the directions and guidelines described in the "Adding New Features" section below, you may create bugfix branches and send us pull requests. 71 | 72 | 73 | ## Credit 74 | 75 | Thanks to [Ben Ramsey](https://github.com/ramsey) for sharing the awesome [ramesey/uuid contributing](https://github.com/ramsey/uuid/blob/master/CONTRIBUTING.md) document (that we blatantly copied large portions of). 76 | -------------------------------------------------------------------------------- /src/AbstractPlugin.php: -------------------------------------------------------------------------------- 1 | client = $client; 79 | } 80 | 81 | /** 82 | * Returns the client in use by the plugin. 83 | * 84 | * @return ClientInterface|null 85 | */ 86 | public function getClient() 87 | { 88 | return $this->client; 89 | } 90 | 91 | /** 92 | * Sets the event emitter for the plugin to use. 93 | * 94 | * @param \Evenement\EventEmitterInterface $emitter 95 | */ 96 | public function setEventEmitter(EventEmitterInterface $emitter) 97 | { 98 | $this->emitter = $emitter; 99 | } 100 | 101 | /** 102 | * Returns the event emitter in use by the plugin. 103 | * 104 | * @return \Evenement\EventEmitterInterface|null 105 | */ 106 | public function getEventEmitter() 107 | { 108 | return $this->emitter; 109 | } 110 | 111 | /** 112 | * Sets the logger for the plugin to use. 113 | * 114 | * @param \Psr\Log\LoggerInterface $logger 115 | */ 116 | public function setLogger(LoggerInterface $logger) 117 | { 118 | $this->logger = $logger; 119 | } 120 | 121 | /** 122 | * Returns the logger in use by the plugin. 123 | * 124 | * @return \Psr\Log\LoggerInterface|null 125 | */ 126 | public function getLogger() 127 | { 128 | return $this->logger; 129 | } 130 | 131 | /** 132 | * Sets the event queue factory instance. 133 | * 134 | * @param \Phergie\Irc\Bot\React\EventQueueFactoryInterface $queueFactory 135 | */ 136 | public function setEventQueueFactory(EventQueueFactoryInterface $queueFactory) 137 | { 138 | $this->queueFactory = $queueFactory; 139 | } 140 | 141 | /** 142 | * Returns the event queue factory instance. 143 | * 144 | * @return \Phergie\Irc\Bot\React\EventQueueFactoryInterface 145 | */ 146 | public function getEventQueueFactory() 147 | { 148 | return $this->queueFactory; 149 | } 150 | 151 | /** 152 | * Sets the event loop instance. 153 | * 154 | * @param \React\EventLoop\LoopInterface $loop 155 | */ 156 | public function setLoop(LoopInterface $loop) 157 | { 158 | $this->eventLoop = $loop; 159 | } 160 | 161 | /** 162 | * Returns the event loop instance. 163 | * 164 | * @return \React\EventLoop\LoopInterface 165 | */ 166 | public function getLoop() 167 | { 168 | return $this->eventLoop; 169 | } 170 | 171 | /** 172 | * Replaces bytes in a string that might cause it to be truncated or 173 | * otherwise misinterpreted by the server. 174 | * 175 | * @param string $string 176 | * @return string 177 | */ 178 | public function escapeParam($string) 179 | { 180 | foreach ([ "\r\n", "\r", "\n" ] as $badBytes) { 181 | if (false !== strpos($string, $badBytes)) { 182 | $string = str_replace($badBytes, " ", $string); 183 | } 184 | } 185 | 186 | if (false !== strpos($string, "\0")) { 187 | $string = str_replace("\0", "", $string); 188 | } 189 | 190 | return $string; 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/Bot.php: -------------------------------------------------------------------------------- 1 | registerClientSubscribers($client); 94 | $this->client = $client; 95 | } 96 | 97 | /** 98 | * Returns the IRC client in use by the bot. 99 | * 100 | * @return \Phergie\Irc\Client\React\ClientInterface 101 | */ 102 | public function getClient() 103 | { 104 | if (!$this->client) { 105 | $this->setClient(new Client); 106 | } 107 | return $this->client; 108 | } 109 | 110 | /** 111 | * Sets the configuration to be used by the bot in its operations. 112 | * 113 | * See config.sample.php for an example configuration file. 114 | * 115 | * @param array $config Associative array keyed by setting name 116 | */ 117 | public function setConfig(array $config) 118 | { 119 | $this->config = $config; 120 | } 121 | 122 | /** 123 | * Returns the configuration in use by the bot. 124 | * 125 | * @return array Associative array keyed by setting name 126 | */ 127 | public function getConfig() 128 | { 129 | return $this->config; 130 | } 131 | 132 | /** 133 | * Sets the logger in use by the bot. 134 | * 135 | * @param \Psr\Log\LoggerInterface $logger 136 | */ 137 | public function setLogger(LoggerInterface $logger) 138 | { 139 | $this->logger = $logger; 140 | $this->getClient()->setLogger($logger); 141 | } 142 | 143 | /** 144 | * Returns the logger in use by the bot. 145 | * 146 | * @return \Psr\Log\LoggerInterface 147 | */ 148 | public function getLogger() 149 | { 150 | if (!$this->logger) { 151 | $this->logger = $this->getClient()->getLogger(); 152 | } 153 | return $this->logger; 154 | } 155 | 156 | /** 157 | * Sets the parser for generated event data in use by the bot. 158 | * 159 | * @param \Phergie\Irc\ParserInterface $parser 160 | */ 161 | public function setParser(ParserInterface $parser) 162 | { 163 | $this->parser = $parser; 164 | } 165 | 166 | /** 167 | * Returns the parser for generated event data in use by the bot. 168 | * 169 | * @return \Phergie\Irc\ParserInterface 170 | */ 171 | public function getParser() 172 | { 173 | if (!$this->parser) { 174 | $this->parser = new Parser; 175 | } 176 | return $this->parser; 177 | } 178 | 179 | /** 180 | * Sets the parser converter for event data in use by the bot. 181 | * 182 | * @param \Phergie\Irc\Event\ParserConverterInterface $converter 183 | */ 184 | public function setConverter(ParserConverterInterface $converter) 185 | { 186 | $this->converter = $converter; 187 | } 188 | 189 | /** 190 | * Returns the parser converter for event data in use by the bot. 191 | * 192 | * @return \Phergie\Irc\Event\ParserConverterInterface 193 | */ 194 | public function getConverter() 195 | { 196 | if (!$this->converter) { 197 | $this->converter = new ParserConverter; 198 | } 199 | return $this->converter; 200 | } 201 | 202 | /** 203 | * Sets the event queue factory for the bot to use. 204 | * 205 | * @param \Phergie\Irc\Bot\React\EventQueueFactoryInterface $queueFactory 206 | */ 207 | public function setEventQueueFactory(EventQueueFactoryInterface $queueFactory) 208 | { 209 | $this->queueFactory = $queueFactory; 210 | } 211 | 212 | /** 213 | * Returns the event queue factory in use by the bot. 214 | * 215 | * @return \Phergie\Irc\Bot\React\EventQueueFactoryInterface 216 | */ 217 | public function getEventQueueFactory() 218 | { 219 | if (!$this->queueFactory) { 220 | $this->queueFactory = new EventQueueFactory; 221 | } 222 | return $this->queueFactory; 223 | } 224 | 225 | /** 226 | * Initiates an event loop for the bot in which it will connect to servers 227 | * and monitor those connections for events to forward to plugins. 228 | * 229 | * @param bool $autorun 230 | * 231 | * @throws \RuntimeException if configuration is inconsistent with 232 | * expected structure 233 | */ 234 | public function run($autorun = true) 235 | { 236 | $this->setDependencyOverrides($this->config); 237 | $this->getPlugins($this->config); 238 | $connections = $this->getConnections($this->config); 239 | $this->getClient()->run($connections, $autorun); 240 | } 241 | 242 | /** 243 | * Sets dependencies from configuration. 244 | * 245 | * @param array $config 246 | */ 247 | protected function setDependencyOverrides(array $config) 248 | { 249 | if (isset($config['client'])) { 250 | $this->setClient($config['client']); 251 | } 252 | 253 | if (isset($config['logger'])) { 254 | $this->setLogger($config['logger']); 255 | } 256 | 257 | if (isset($config['parser'])) { 258 | $this->setParser($config['parser']); 259 | } 260 | 261 | if (isset($config['converter'])) { 262 | $this->setConverter($config['converter']); 263 | } 264 | 265 | if (isset($config['eventQueueFactory'])) { 266 | $this->setEventQueueFactory($config['eventQueueFactory']); 267 | } 268 | } 269 | 270 | /** 271 | * Extracts connections from configuration. 272 | * 273 | * @param array $config Associative array keyed by setting name 274 | * @return \Phergie\Irc\ConnectionInterface[] 275 | */ 276 | protected function getConnections(array $config) 277 | { 278 | if (!isset($config['connections'])) { 279 | throw new \RuntimeException('Configuration must contain a "connections" key'); 280 | } 281 | 282 | if (!is_array($config['connections']) || !$config['connections']) { 283 | throw new \RuntimeException('Configuration "connections" key must reference a non-empty array'); 284 | } 285 | 286 | $connections = array_filter( 287 | $config['connections'], 288 | function ($connection) { 289 | return $connection instanceof ConnectionInterface; 290 | } 291 | ); 292 | if (count($connections) != count($config['connections'])) { 293 | throw new \RuntimeException( 294 | 'All configuration "connections" array values must implement \Phergie\Irc\ConnectionInterface' 295 | ); 296 | } 297 | 298 | return $connections; 299 | } 300 | 301 | /** 302 | * Extracts plugins from configuration. 303 | * 304 | * @param array $config Associative array keyed by setting name 305 | * @throws \RuntimeException if any plugin event callback is invalid 306 | * @return \Phergie\Irc\Bot\React\PluginInterface[] 307 | */ 308 | protected function getPlugins(array $config) 309 | { 310 | if (!isset($config['plugins'])) { 311 | throw new \RuntimeException('Configuration must contain a "plugins" key'); 312 | } 313 | 314 | if (!is_array($config['plugins'])) { 315 | throw new \RuntimeException('Configuration "plugins" key must reference an array'); 316 | } 317 | 318 | $plugins = array_filter( 319 | $config['plugins'], 320 | function ($plugin) { 321 | return $plugin instanceof PluginInterface; 322 | } 323 | ); 324 | if (count($plugins) != count($config['plugins'])) { 325 | throw new \RuntimeException( 326 | 'All configuration "plugins" array values must implement \Phergie\Irc\Bot\React\PluginInterface' 327 | ); 328 | } 329 | 330 | $this->registerPluginSubscribers($plugins); 331 | 332 | $processors = $this->getPluginProcessors($config); 333 | $this->processPlugins($plugins, $processors); 334 | 335 | return $plugins; 336 | } 337 | 338 | /** 339 | * Processes a list of plugins for use. 340 | * 341 | * @param \Phergie\Irc\Bot\React\PluginInterface[] 342 | * @param \Phergie\Irc\Bot\React\PluginProcessor\PluginProcessorInterface[] 343 | * @param \SplObjectStorage $processedPlugins 344 | */ 345 | protected function processPlugins(array $plugins, array $processors, \SplObjectStorage $processedPlugins = null) 346 | { 347 | // Initialise store of already-processed plugins, to prevent container-based endless recursion 348 | if ($processedPlugins === null) { 349 | $processedPlugins = new \SplObjectStorage; 350 | } 351 | foreach ($plugins as $plugin) { 352 | if ($processedPlugins->contains($plugin)) { 353 | continue; 354 | } 355 | $processedPlugins->attach($plugin); 356 | foreach ($processors as $processor) { 357 | $processor->process($plugin, $this); 358 | } 359 | if ($plugin instanceof PluginContainerInterface) { 360 | $this->processPlugins($plugin->getPlugins(), $processors, $processedPlugins); 361 | } 362 | } 363 | } 364 | 365 | /** 366 | * Returns a list of processors for plugins. 367 | * 368 | * @param array $config Associative array keyed by setting name 369 | */ 370 | protected function getPluginProcessors(array $config) 371 | { 372 | $processors = isset($config['pluginProcessors']) 373 | ? $config['pluginProcessors'] 374 | : $this->getDefaultPluginProcessors(); 375 | 376 | if (!is_array($processors)) { 377 | throw new \RuntimeException('Configuration "pluginProcessors" key must reference an array'); 378 | } 379 | 380 | if (!empty($processors)) { 381 | $invalid = array_filter( 382 | $processors, 383 | function ($processor) { 384 | return !$processor instanceof PluginProcessorInterface; 385 | } 386 | ); 387 | if (!empty($invalid)) { 388 | throw new \RuntimeException( 389 | 'All configuration "pluginProcessors" array values must implement' 390 | . ' \Phergie\Irc\Bot\React\PluginProcessor\PluginProcessorInterface' 391 | ); 392 | } 393 | } 394 | 395 | return $processors; 396 | } 397 | 398 | /** 399 | * Returns a list of default plugin processors used when none are set via 400 | * configuration. 401 | * 402 | * @param \Phergie\Irc\Bot\React\PluginProcessor\PluginProcessorInterface[] 403 | * 404 | * @return PluginProcessorInterface[] 405 | */ 406 | protected function getDefaultPluginProcessors() 407 | { 408 | return [ 409 | new ClientInjector, 410 | new EventEmitterInjector, 411 | new EventQueueFactoryInjector, 412 | new LoggerInjector, 413 | new LoopInjector, 414 | ]; 415 | } 416 | 417 | /** 418 | * Validates a plugin's event callbacks. 419 | * 420 | * @param \Phergie\Irc\Bot\React\PluginInterface $plugin 421 | * @throws \RuntimeException if any event callback is invalid 422 | */ 423 | protected function validatePluginEvents(PluginInterface $plugin) 424 | { 425 | $events = $plugin->getSubscribedEvents(); 426 | if (!is_array($events)) { 427 | throw new \RuntimeException( 428 | 'Plugin of class ' . get_class($plugin) . 429 | ' has getSubscribedEvents() implementation' . 430 | ' that does not return an array' 431 | ); 432 | } 433 | foreach ($events as $event => $callback) { 434 | if (!is_string($event) 435 | || !is_callable([ $plugin, $callback ]) 436 | && !is_callable($callback)) { 437 | throw new \RuntimeException( 438 | 'Plugin of class ' . get_class($plugin) . 439 | ' returns non-string event name or invalid callback' . 440 | ' for event "' . $event . '"' 441 | ); 442 | } 443 | } 444 | } 445 | 446 | /** 447 | * Configures the client to emit events for specific types of messages. 448 | * 449 | * @param \Phergie\Irc\Client\React\ClientInterface $client Client for 450 | * which to configure events 451 | */ 452 | protected function registerClientSubscribers(ClientInterface $client) 453 | { 454 | $client->on('irc.received', function ($message, $write, $connection) { 455 | $this->processClientEvent('irc.received', $message, $connection, $write); 456 | }); 457 | 458 | $client->on('irc.sent', function ($message, $write, $connection) { 459 | $parsed = $this->getParser()->parse($message); 460 | if (!$parsed) { 461 | return; 462 | } 463 | $this->processClientEvent('irc.sent', $parsed, $connection, $write); 464 | }); 465 | 466 | $client->on('irc.tick', function ($write, $connection) { 467 | $this->processOutgoingEvents($connection, $write); 468 | }); 469 | } 470 | 471 | /** 472 | * Callback to process client events. Not intended to be called from 473 | * outside this class. 474 | * 475 | * @param string $event Received client event 476 | * @param array $message Parsed message 477 | * @param \Phergie\Irc\ConnectionInterface $connection Connection on which 478 | * the event occurred 479 | * @param \Phergie\Irc\Client\React\WriteStream $write Stream used to send 480 | * commands to the server 481 | */ 482 | public function processClientEvent($event, array $message, ConnectionInterface $connection, WriteStream $write) 483 | { 484 | $converter = $this->getConverter(); 485 | $converted = $converter->convert($message); 486 | $converted->setConnection($connection); 487 | 488 | $client = $this->getClient(); 489 | $queue = $this->getEventQueueFactory()->getEventQueue($connection); 490 | $params = [ $converted, $queue ]; 491 | $subtype = $this->getEventSubtype($converted); 492 | $client->emit($event . '.each', $params); 493 | $client->emit($event . '.' . $subtype, $params); 494 | 495 | $this->processOutgoingEvents($connection, $write); 496 | } 497 | 498 | /** 499 | * Callback to process any queued outgoing events. Not intended to be 500 | * called from outside thie class. 501 | * 502 | * @param \Phergie\Irc\ConnectionInterface $connection Connection on which 503 | * the event occurred 504 | * @param \Phergie\Irc\Client\React\WriteStream $write Stream used to send 505 | * commands to the server 506 | */ 507 | public function processOutgoingEvents(ConnectionInterface $connection, WriteStream $write) 508 | { 509 | $client = $this->getClient(); 510 | $queue = $this->getEventQueueFactory()->getEventQueue($connection); 511 | 512 | $client->emit('irc.sending.all', [ $queue ]); 513 | while ($extracted = $queue->extract()) { 514 | $extracted->setConnection($connection); 515 | $params = [ $extracted, $queue ]; 516 | $subtype = $this->getEventSubtype($extracted); 517 | $client->emit('irc.sending.each', $params); 518 | $client->emit('irc.sending.' . $subtype, $params); 519 | 520 | if ($extracted instanceof CtcpEvent) { 521 | $method = 'ctcp' . $extracted->getCtcpCommand(); 522 | if ($extracted->getCommand() === 'NOTICE') { 523 | $method .= 'Response'; 524 | } 525 | } else { 526 | $method = 'irc' . $extracted->getCommand(); 527 | } 528 | call_user_func_array( 529 | [ $write, $method ], 530 | $extracted->getParams() 531 | ); 532 | } 533 | } 534 | 535 | /** 536 | * Returns an event subtype corresponding to a given event object, used to 537 | * generate event names when emitting events. 538 | * 539 | * @param \Phergie\Irc\Event\EventInterface $event 540 | * @return string 541 | */ 542 | protected function getEventSubtype(EventInterface $event) 543 | { 544 | $subevent = ''; 545 | if ($event instanceof CtcpEvent) { 546 | $subevent = 'ctcp.' . strtolower($event->getCtcpCommand()); 547 | } elseif ($event instanceof UserEvent) { 548 | $subevent = strtolower($event->getCommand()); 549 | } elseif ($event instanceof ServerEvent) { 550 | $subevent = strtolower($event->getCode()); 551 | } 552 | return $subevent; 553 | } 554 | 555 | /** 556 | * Registers event callbacks from plugins. 557 | * 558 | * @param \Phergie\Irc\Bot\React\PluginInterface[] $plugins Plugins from 559 | * which to get callbacks 560 | */ 561 | protected function registerPluginSubscribers(array $plugins) 562 | { 563 | $client = $this->getClient(); 564 | foreach ($plugins as $plugin) { 565 | $this->validatePluginEvents($plugin); 566 | $callbacks = $plugin->getSubscribedEvents(); 567 | foreach ($callbacks as $event => $callback) { 568 | $pluginCallback = [ $plugin, $callback ]; 569 | if (is_callable($pluginCallback)) { 570 | $callback = $pluginCallback; 571 | } 572 | $client->on($event, $callback); 573 | } 574 | } 575 | } 576 | } 577 | -------------------------------------------------------------------------------- /src/EventQueue.php: -------------------------------------------------------------------------------- 1 | queue = new EventQueueInternal; 59 | 60 | $this->priorities = $this->getPriorities(); 61 | } 62 | 63 | /** 64 | * Allows iteration over the event queue. 65 | * 66 | * @return \Phergie\Irc\Bot\React\EventQueueInternal 67 | */ 68 | public function getIterator() 69 | { 70 | return clone $this->queue; 71 | } 72 | 73 | /** 74 | * Wrapper for the queue's internal count method. 75 | * 76 | * @return int 77 | */ 78 | public function count() 79 | { 80 | return $this->queue->count(); 81 | } 82 | 83 | /** 84 | * Removes and returns an event from the front of the queue. 85 | * 86 | * @return \Phergie\Irc\Event\EventInterface|null Removed event or null if 87 | * the queue is empty 88 | */ 89 | public function extract() 90 | { 91 | if ($this->queue->isEmpty()) { 92 | return null; 93 | } 94 | return $this->queue->extract(); 95 | } 96 | 97 | /** 98 | * Implements \Phergie\Irc\GeneratorInterface->setPrefix(). 99 | * 100 | * @param string $prefix 101 | */ 102 | public function setPrefix($prefix) 103 | { 104 | $this->prefix = $prefix; 105 | } 106 | 107 | /** 108 | * Returns the priority of a specified command. 109 | * 110 | * @param string $command 111 | * @param array $params Unused, intended for use by subclasses 112 | * @return \Phergie\Irc\Bot\React\EventQueuePriority 113 | */ 114 | protected function getPriority($command, array $params) 115 | { 116 | $priority = new EventQueuePriority; 117 | $priority->value = $this->priorities[$command]; 118 | $priority->timestamp = (int) (microtime(true) * 10000); 119 | if ($priority->timestamp <= $this->lastTimestamp) { 120 | $priority->timestamp = $this->lastTimestamp + 1; 121 | } 122 | $this->lastTimestamp = $priority->timestamp; 123 | return $priority; 124 | } 125 | 126 | /** 127 | * Enqueues a new event. 128 | * 129 | * @param \Phergie\Irc\Event\UserEventInterface 130 | * @param string $command 131 | * @param array $params 132 | */ 133 | protected function queueRequest(UserEventInterface $event, $command, array $params) 134 | { 135 | $event->setPrefix($this->prefix); 136 | $event->setCommand($command); 137 | $event->setParams(array_filter($params, 'strlen')); 138 | $this->queue->insert($event, $this->getPriority($command, $params)); 139 | } 140 | 141 | /** 142 | * Enqueues a new IRC event. 143 | * 144 | * @param string $command 145 | * @param array $params 146 | */ 147 | protected function queueIrcRequest($command, array $params = []) 148 | { 149 | $this->queueRequest(new UserEvent, $command, $params); 150 | } 151 | 152 | /** 153 | * Enqueues a new CTCP event. 154 | * 155 | * @param string $command IRC command 156 | * @param string $ctcpCommand CTCP command 157 | * @param array $params Command parameters 158 | */ 159 | protected function queueCtcpEvent($command, $ctcpCommand, array $params = []) 160 | { 161 | $event = new CtcpEvent; 162 | $event->setCtcpCommand($ctcpCommand); 163 | $this->queueRequest($event, $command, $params); 164 | } 165 | 166 | /** 167 | * Enqueues a new CTCP request. 168 | * 169 | * @param string $ctcpCommand CTCP command 170 | * @param array $params Command parameters 171 | */ 172 | protected function queueCtcpRequest($ctcpCommand, array $params = []) 173 | { 174 | $this->queueCtcpEvent('PRIVMSG', $ctcpCommand, $params); 175 | } 176 | 177 | /** 178 | * Enqueues a new CTCP response. 179 | * 180 | * @param string $ctcpCommand CTCP command 181 | * @param array $params CTCP parameters 182 | */ 183 | protected function queueCtcpResponse($ctcpCommand, array $params = []) 184 | { 185 | $this->queueCtcpEvent('NOTICE', $ctcpCommand, $params); 186 | } 187 | 188 | /** 189 | * Implements \Phergie\Irc\GeneratorInterface->ircPass(). 190 | * 191 | * @param string $password 192 | */ 193 | public function ircPass($password) 194 | { 195 | $this->queueIrcRequest('PASS', [ $password ]); 196 | } 197 | 198 | /** 199 | * Implements \Phergie\Irc\GeneratorInterface->ircNick(). 200 | * 201 | * @param string $nickname 202 | * @param int $hopcount 203 | */ 204 | public function ircNick($nickname, $hopcount = null) 205 | { 206 | $this->queueIrcRequest('NICK', [ $nickname, $hopcount ]); 207 | } 208 | 209 | /** 210 | * Implements \Phergie\Irc\GeneratorInterface->ircUser(). 211 | * 212 | * @param string $username 213 | * @param string $hostname 214 | * @param string $servername 215 | * @param string $realname 216 | */ 217 | public function ircUser($username, $hostname, $servername, $realname) 218 | { 219 | $this->queueIrcRequest('USER', [ $username, $hostname, $servername, $realname ]); 220 | } 221 | 222 | /** 223 | * Implements \Phergie\Irc\GeneratorInterface->ircServer(). 224 | * 225 | * @param string $servername 226 | * @param int $hopcount 227 | * @param string $info 228 | */ 229 | public function ircServer($servername, $hopcount, $info) 230 | { 231 | $this->queueIrcRequest('SERVER', [ $servername, $hopcount, $info ]); 232 | } 233 | 234 | /** 235 | * Implements \Phergie\Irc\GeneratorInterface->ircOper(). 236 | * 237 | * @param string $user 238 | * @param string $password 239 | */ 240 | public function ircOper($user, $password) 241 | { 242 | $this->queueIrcRequest('OPER', [ $user, $password ]); 243 | } 244 | 245 | /** 246 | * Implements \Phergie\Irc\GeneratorInterface->ircQuit(). 247 | * 248 | * @param string $message 249 | */ 250 | public function ircQuit($message = null) 251 | { 252 | $this->queueIrcRequest('QUIT', [ $message ]); 253 | } 254 | 255 | /** 256 | * Implements \Phergie\Irc\GeneratorInterface->ircSquit(). 257 | * 258 | * @param string $server 259 | * @param string $comment 260 | */ 261 | public function ircSquit($server, $comment) 262 | { 263 | $this->queueIrcRequest('SQUIT', [ $server, $comment ]); 264 | } 265 | 266 | /** 267 | * Implements \Phergie\Irc\GeneratorInterface->ircJoin(). 268 | * 269 | * @param string $channels 270 | * @param string $keys 271 | */ 272 | public function ircJoin($channels, $keys = null) 273 | { 274 | $this->queueIrcRequest('JOIN', [ $channels, $keys ]); 275 | } 276 | 277 | /** 278 | * Implements \Phergie\Irc\GeneratorInterface->ircPart(). 279 | * 280 | * @param string $channels 281 | * @param string|null $message 282 | */ 283 | public function ircPart($channels, $message = null) 284 | { 285 | $this->queueIrcRequest('PART', [ $channels, $message ]); 286 | } 287 | 288 | /** 289 | * Implements \Phergie\Irc\GeneratorInterface->ircMode(). 290 | * 291 | * @param string $target 292 | * @param string|null $mode 293 | * @param string|null $param 294 | */ 295 | public function ircMode($target, $mode = null, $param = null) 296 | { 297 | $this->queueIrcRequest('MODE', [ $target, $mode, $param ]); 298 | } 299 | 300 | /** 301 | * Implements \Phergie\Irc\GeneratorInterface->ircTopic(). 302 | * 303 | * @param string $channel 304 | * @param string $topic 305 | */ 306 | public function ircTopic($channel, $topic = null) 307 | { 308 | $this->queueIrcRequest('TOPIC', [ $channel, $topic ]); 309 | } 310 | 311 | /** 312 | * Implements \Phergie\Irc\GeneratorInterface->ircNames(). 313 | * 314 | * @param string $channels 315 | */ 316 | public function ircNames($channels) 317 | { 318 | $this->queueIrcRequest('NAMES', [ $channels ]); 319 | } 320 | 321 | /** 322 | * Implements \Phergie\Irc\GeneratorInterface->ircList(). 323 | * 324 | * @param string $channels 325 | * @param string $server 326 | */ 327 | public function ircList($channels = null, $server = null) 328 | { 329 | $this->queueIrcRequest('LIST', [ $channels, $server ]); 330 | } 331 | 332 | /** 333 | * Implements \Phergie\Irc\GeneratorInterface->ircInvite(). 334 | * 335 | * @param string $nickname 336 | * @param string $channel 337 | */ 338 | public function ircInvite($nickname, $channel) 339 | { 340 | $this->queueIrcRequest('INVITE', [ $nickname, $channel ]); 341 | } 342 | 343 | /** 344 | * Implements \Phergie\Irc\GeneratorInterface->ircKick(). 345 | * 346 | * @param string $channel 347 | * @param string $user 348 | * @param string $comment 349 | */ 350 | public function ircKick($channel, $user, $comment = null) 351 | { 352 | $this->queueIrcRequest('KICK', [ $channel, $user, $comment ]); 353 | } 354 | 355 | /** 356 | * Implements \Phergie\Irc\GeneratorInterface->ircVersion(). 357 | * 358 | * @param string $server 359 | */ 360 | public function ircVersion($server = null) 361 | { 362 | $this->queueIrcRequest('VERSION', [ $server ]); 363 | } 364 | 365 | /** 366 | * Implements \Phergie\Irc\GeneratorInterface->ircStats(). 367 | * 368 | * @param string $query 369 | * @param string $server 370 | */ 371 | public function ircStats($query, $server = null) 372 | { 373 | $this->queueIrcRequest('STATS', [ $query, $server ]); 374 | } 375 | 376 | /** 377 | * Implements \Phergie\Irc\GeneratorInterface->ircLinks(). 378 | * 379 | * @param string $servermask 380 | * @param string $remoteserver 381 | */ 382 | public function ircLinks($servermask = null, $remoteserver = null) 383 | { 384 | $this->queueIrcRequest('LINKS', [ $servermask, $remoteserver ]); 385 | } 386 | 387 | /** 388 | * Implements \Phergie\Irc\GeneratorInterface->ircTime(). 389 | * 390 | * @param string $server 391 | */ 392 | public function ircTime($server = null) 393 | { 394 | $this->queueIrcRequest('TIME', [ $server ]); 395 | } 396 | 397 | /** 398 | * Implements \Phergie\Irc\GeneratorInterface->ircConnect(). 399 | * 400 | * @param string $targetserver 401 | * @param int $port 402 | * @param string $remoteserver 403 | */ 404 | public function ircConnect($targetserver, $port = null, $remoteserver = null) 405 | { 406 | $this->queueIrcRequest('CONNECT', [ $targetserver, $port, $remoteserver ]); 407 | } 408 | 409 | /** 410 | * Implements \Phergie\Irc\GeneratorInterface->ircTrace(). 411 | * 412 | * @param string $server 413 | */ 414 | public function ircTrace($server = null) 415 | { 416 | $this->queueIrcRequest('TRACE', [ $server ]); 417 | } 418 | 419 | /** 420 | * Implements \Phergie\Irc\GeneratorInterface->ircAdmin() 421 | * 422 | * @param string $server 423 | */ 424 | public function ircAdmin($server = null) 425 | { 426 | $this->queueIrcRequest('ADMIN', [ $server ]); 427 | } 428 | 429 | /** 430 | * Implements \Phergie\Irc\GeneratorInterface->ircInfo(). 431 | * 432 | * @param string $server 433 | */ 434 | public function ircInfo($server = null) 435 | { 436 | $this->queueIrcRequest('INFO', [ $server ]); 437 | } 438 | 439 | /** 440 | * Implements \Phergie\Irc\GeneratorInterface->ircPrivmsg(). 441 | * 442 | * @param string $receivers 443 | * @param string $text 444 | */ 445 | public function ircPrivmsg($receivers, $text) 446 | { 447 | $this->queueIrcRequest('PRIVMSG', [ $receivers, $text ]); 448 | } 449 | 450 | /** 451 | * Implements \Phergie\Irc\GeneratorInterface->ircNotice(). 452 | * 453 | * @param string $nickname 454 | * @param string $text 455 | */ 456 | public function ircNotice($nickname, $text) 457 | { 458 | $this->queueIrcRequest('NOTICE', [ $nickname, $text ]); 459 | } 460 | 461 | /** 462 | * Implements \Phergie\Irc\GeneratorInterface->ircWho(). 463 | * 464 | * @param string $name 465 | * @param string $o 466 | */ 467 | public function ircWho($name, $o = null) 468 | { 469 | $this->queueIrcRequest('WHO', [ $name, $o ]); 470 | } 471 | 472 | /** 473 | * Implements \Phergie\Irc\GeneratorInterface->ircWhois(). 474 | * 475 | * @param string $nickmasks 476 | * @param string $server Optional 477 | */ 478 | public function ircWhois($nickmasks, $server = null) 479 | { 480 | $this->queueIrcRequest('WHOIS', [ $server, $nickmasks ]); 481 | } 482 | 483 | /** 484 | * Implements \Phergie\Irc\GeneratorInterface->ircWhowas(). 485 | * 486 | * @param string $nickname 487 | * @param int $count 488 | * @param string $server 489 | */ 490 | public function ircWhowas($nickname, $count = null, $server = null) 491 | { 492 | $this->queueIrcRequest('WHOWAS', [ $nickname, $count, $server ]); 493 | } 494 | 495 | /** 496 | * Implements \Phergie\Irc\GeneratorInterface->ircKill(). 497 | * 498 | * @param string $nickname 499 | * @param string $comment 500 | */ 501 | public function ircKill($nickname, $comment) 502 | { 503 | $this->queueIrcRequest('KILL', [ $nickname, $comment ]); 504 | } 505 | 506 | /** 507 | * Implements \Phergie\Irc\GeneratorInterface->ircPing(). 508 | * 509 | * @param string $server1 510 | * @param string $server2 511 | */ 512 | public function ircPing($server1, $server2 = null) 513 | { 514 | $this->queueIrcRequest('PING', [ $server1, $server2 ]); 515 | } 516 | 517 | /** 518 | * Implements \Phergie\Irc\GeneratorInterface->ircPong(). 519 | * 520 | * @param string $daemon 521 | * @param string $daemon2 522 | */ 523 | public function ircPong($daemon, $daemon2 = null) 524 | { 525 | $this->queueIrcRequest('PONG', [ $daemon, $daemon2 ]); 526 | } 527 | 528 | /** 529 | * Implements \Phergie\Irc\GeneratorInterface->ircError(). 530 | * 531 | * @param string $message 532 | */ 533 | public function ircError($message) 534 | { 535 | $this->queueIrcRequest('ERROR', [ $message ]); 536 | } 537 | 538 | /** 539 | * Implements \Phergie\Irc\GeneratorInterface->ircAway(). 540 | * 541 | * @param string $message 542 | */ 543 | public function ircAway($message = null) 544 | { 545 | $this->queueIrcRequest('AWAY', [ $message ]); 546 | } 547 | 548 | /** 549 | * Implements \Phergie\Irc\GeneratorInterface->ircRehash(). 550 | */ 551 | public function ircRehash() 552 | { 553 | $this->queueIrcRequest('REHASH'); 554 | } 555 | 556 | /** 557 | * Implements \Phergie\Irc\GeneratorInterface->ircRestart(). 558 | */ 559 | public function ircRestart() 560 | { 561 | $this->queueIrcRequest('RESTART'); 562 | } 563 | 564 | /** 565 | * Implements \Phergie\Irc\GeneratorInterface->ircSummon(). 566 | * 567 | * @param string $user 568 | * @param string $server 569 | */ 570 | public function ircSummon($user, $server = null) 571 | { 572 | $this->queueIrcRequest('SUMMON', [ $user, $server ]); 573 | } 574 | 575 | /** 576 | * Implements \Phergie\Irc\GeneratorInterface->ircUsers(). 577 | * 578 | * @param string $server 579 | */ 580 | public function ircUsers($server = null) 581 | { 582 | $this->queueIrcRequest('USERS', [ $server ]); 583 | } 584 | 585 | /** 586 | * Implements \Phergie\Irc\GeneratorInterface->ircWallops(). 587 | * 588 | * @param string $text 589 | */ 590 | public function ircWallops($text) 591 | { 592 | $this->queueIrcRequest('WALLOPS', [ $text ]); 593 | } 594 | 595 | /** 596 | * Implements \Phergie\Irc\GeneratorInterface->ircUserhost(). 597 | * 598 | * @param string $nickname1 599 | * @param string $nickname2 600 | * @param string $nickname3 601 | * @param string $nickname4 602 | * @param string $nickname5 603 | */ 604 | public function ircUserhost($nickname1, $nickname2 = null, $nickname3 = null, $nickname4 = null, $nickname5 = null) 605 | { 606 | $this->queueIrcRequest('USERHOST', [ $nickname1, $nickname2, $nickname3, $nickname4, $nickname5 ]); 607 | } 608 | 609 | /** 610 | * Implements \Phergie\Irc\GeneratorInterface->ircIson(). 611 | * 612 | * @param string $nicknames 613 | */ 614 | public function ircIson($nicknames) 615 | { 616 | $this->queueIrcRequest('ISON', [ $nicknames ]); 617 | } 618 | 619 | /** 620 | * Implements \Phergie\Irc\GeneratorInterface->ircProtoctl(). 621 | * 622 | * @param string $proto 623 | */ 624 | public function ircProtoctl($proto) 625 | { 626 | $this->queueIrcRequest('PROTOCTL', [ $proto ]); 627 | } 628 | 629 | /** 630 | * Implements \Phergie\Irc\GeneratorInterface->ctcpFinger(). 631 | * 632 | * @param string $receivers 633 | */ 634 | public function ctcpFinger($receivers) 635 | { 636 | $this->queueCtcpRequest('FINGER', [ $receivers ]); 637 | } 638 | 639 | /** 640 | * Implements \Phergie\Irc\GeneratorInterface->ctcpFingerResponse(). 641 | * 642 | * @param string $nickname 643 | * @param string $text 644 | */ 645 | public function ctcpFingerResponse($nickname, $text) 646 | { 647 | $this->queueCtcpResponse('FINGER', [ $nickname, $text ]); 648 | } 649 | 650 | /** 651 | * Implements \Phergie\Irc\GeneratorInterface->ctcpVersion(). 652 | * 653 | * @param string $receivers 654 | */ 655 | public function ctcpVersion($receivers) 656 | { 657 | $this->queueCtcpRequest('VERSION', [ $receivers ]); 658 | } 659 | 660 | /** 661 | * Implements \Phergie\Irc\GeneratorInterface->ctcpVersionResponse(). 662 | * 663 | * @param string $nickname 664 | * @param string $name 665 | * @param string $version 666 | * @param string $environment 667 | */ 668 | public function ctcpVersionResponse($nickname, $name, $version, $environment) 669 | { 670 | $this->queueCtcpResponse('VERSION', [ $nickname, $name, $version, $environment ]); 671 | } 672 | 673 | /** 674 | * Implements \Phergie\Irc\GeneratorInterface->ctcpSource(). 675 | * 676 | * @param string $receivers 677 | */ 678 | public function ctcpSource($receivers) 679 | { 680 | $this->queueCtcpRequest('SOURCE', [ $receivers ]); 681 | } 682 | 683 | /** 684 | * Implements \Phergie\Irc\GeneratorInterface->ctcpSourceResponse(). 685 | * 686 | * @param string $nickname 687 | * @param string $host 688 | * @param string $directories 689 | * @param string $files 690 | */ 691 | public function ctcpSourceResponse($nickname, $host, $directories, $files) 692 | { 693 | $this->queueCtcpResponse('SOURCE', [ $nickname, $host, $directories, $files ]); 694 | } 695 | 696 | /** 697 | * Implements \Phergie\Irc\GeneratorInterface->ctcpUserinfo(). 698 | * 699 | * @param string $receivers 700 | */ 701 | public function ctcpUserinfo($receivers) 702 | { 703 | $this->queueCtcpRequest('USERINFO', [ $receivers ]); 704 | } 705 | 706 | /** 707 | * Implements \Phergie\Irc\GeneratorInterface->ctcpUserinfoResponse(). 708 | * 709 | * @param string $nickname 710 | * @param string $text 711 | */ 712 | public function ctcpUserinfoResponse($nickname, $text) 713 | { 714 | $this->queueCtcpResponse('USERINFO', [ $nickname, $text ]); 715 | } 716 | 717 | /** 718 | * Implements \Phergie\Irc\GeneratorInterface->ctcpClientinfo(). 719 | * 720 | * @param string $receivers 721 | */ 722 | public function ctcpClientinfo($receivers) 723 | { 724 | $this->queueCtcpRequest('CLIENTINFO', [ $receivers ]); 725 | } 726 | 727 | /** 728 | * Implements \Phergie\Irc\GeneratorInterface->ctcpClientinfoResponse(). 729 | * 730 | * @param string $nickname 731 | * @param string $client 732 | */ 733 | public function ctcpClientinfoResponse($nickname, $client) 734 | { 735 | $this->queueCtcpResponse('CLIENTINFO', [ $nickname, $client ]); 736 | } 737 | 738 | /** 739 | * Implements \Phergie\Irc\GeneratorInterface->ctcpErrmsg(). 740 | * 741 | * @param string $receivers 742 | * @param string $query 743 | */ 744 | public function ctcpErrmsg($receivers, $query) 745 | { 746 | $this->queueCtcpRequest('ERRMSG', [ $receivers, $query ]); 747 | } 748 | 749 | /** 750 | * Implements \Phergie\Irc\GeneratorInterface->ctcpErrmsgResponse(). 751 | * 752 | * @param string $nickname 753 | * @param string $query 754 | * @param string $message 755 | */ 756 | public function ctcpErrmsgResponse($nickname, $query, $message) 757 | { 758 | $this->queueCtcpResponse('ERRMSG', [ $nickname, $query, $message ]); 759 | } 760 | 761 | /** 762 | * Implements \Phergie\Irc\GeneratorInterface->ctcpPing(). 763 | * 764 | * @param string $receivers 765 | * @param int $timestamp 766 | */ 767 | public function ctcpPing($receivers, $timestamp) 768 | { 769 | $this->queueCtcpRequest('PING', [ $receivers, $timestamp ]); 770 | } 771 | 772 | /** 773 | * Implements \Phergie\Irc\GeneratorInterface->ctcpPingResponse(). 774 | * 775 | * @param string $nickname 776 | * @param int $timestamp 777 | */ 778 | public function ctcpPingResponse($nickname, $timestamp) 779 | { 780 | $this->queueCtcpResponse('PING', [ $nickname, $timestamp ]); 781 | } 782 | 783 | /** 784 | * Implements \Phergie\Irc\GeneratorInterface->ctcpTime(). 785 | * 786 | * @param string $receivers 787 | */ 788 | public function ctcpTime($receivers) 789 | { 790 | $this->queueCtcpRequest('TIME', [ $receivers ]); 791 | } 792 | 793 | /** 794 | * Implements \Phergie\Irc\GeneratorInterface->ctcpTimeResponse(). 795 | * 796 | * @param string $nickname 797 | * @param string $time 798 | */ 799 | public function ctcpTimeResponse($nickname, $time) 800 | { 801 | $this->queueCtcpResponse('TIME', [ $nickname, $time ]); 802 | } 803 | 804 | /** 805 | * Implements \Phergie\Irc\GeneratorInterface->ctcpAction(). 806 | * 807 | * @param string $receivers 808 | * @param string $action 809 | */ 810 | public function ctcpAction($receivers, $action) 811 | { 812 | $this->queueCtcpRequest('ACTION', [ $receivers, $action ]); 813 | } 814 | 815 | /** 816 | * Implements \Phergie\Irc\GeneratorInterface->ctcpActionResponse(). 817 | * 818 | * @param string $nickname 819 | * @param string $action 820 | */ 821 | public function ctcpActionResponse($nickname, $action) 822 | { 823 | $this->queueCtcpResponse('ACTION', [ $nickname, $action ]); 824 | } 825 | 826 | /** 827 | * Returns a list of IRC events in order from most to least destructive. 828 | * 829 | * @return array Associative array keyed by event name 830 | */ 831 | protected function getPriorities() 832 | { 833 | return array_flip([ 834 | 'RESTART', 835 | 'SQUIT', 836 | 'QUIT', 837 | 'ERROR', 838 | 'KICK', 839 | 'PART', 840 | 'KILL', 841 | 'INVITE', 842 | 'TOPIC', 843 | 'ACTION', 844 | 'PRIVMSG', 845 | 'NICK', 846 | 'MODE', 847 | 'WHOWAS', 848 | 'WHOIS', 849 | 'WHO', 850 | 'INFO', 851 | 'ADMIN', 852 | 'TRACE', 853 | 'TIME', 854 | 'LINKS', 855 | 'STATS', 856 | 'VERSION', 857 | 'NAMES', 858 | 'LIST', 859 | 'JOIN', 860 | 'NOTICE', 861 | 'PONG', 862 | 'PING', 863 | 'USER', 864 | 'PASS', 865 | 'ISON', 866 | 'USERHOST', 867 | 'WALLOPS', 868 | 'PROTOCTL', 869 | 'USERS', 870 | 'SUMMON', 871 | 'REHASH', 872 | 'AWAY', 873 | 'CONNECT', 874 | 'OPER', 875 | 'SERVER', 876 | ]); 877 | } 878 | } 879 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "372473981a0eed8f8393700f8481ef22", 8 | "packages": [ 9 | { 10 | "name": "evenement/evenement", 11 | "version": "v2.1.0", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/igorw/evenement.git", 15 | "reference": "6ba9a777870ab49f417e703229d53931ed40fd7a" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/igorw/evenement/zipball/6ba9a777870ab49f417e703229d53931ed40fd7a", 20 | "reference": "6ba9a777870ab49f417e703229d53931ed40fd7a", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.4.0" 25 | }, 26 | "require-dev": { 27 | "phpunit/phpunit": "^6.0||^5.7||^4.8.35" 28 | }, 29 | "type": "library", 30 | "extra": { 31 | "branch-alias": { 32 | "dev-master": "2.0-dev" 33 | } 34 | }, 35 | "autoload": { 36 | "psr-0": { 37 | "Evenement": "src" 38 | } 39 | }, 40 | "notification-url": "https://packagist.org/downloads/", 41 | "license": [ 42 | "MIT" 43 | ], 44 | "authors": [ 45 | { 46 | "name": "Igor Wiedler", 47 | "email": "igor@wiedler.ch" 48 | } 49 | ], 50 | "description": "Événement is a very simple event dispatching library for PHP", 51 | "keywords": [ 52 | "event-dispatcher", 53 | "event-emitter" 54 | ], 55 | "time": "2017-07-17T17:39:19+00:00" 56 | }, 57 | { 58 | "name": "monolog/monolog", 59 | "version": "1.17.2", 60 | "source": { 61 | "type": "git", 62 | "url": "https://github.com/Seldaek/monolog.git", 63 | "reference": "bee7f0dc9c3e0b69a6039697533dca1e845c8c24" 64 | }, 65 | "dist": { 66 | "type": "zip", 67 | "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bee7f0dc9c3e0b69a6039697533dca1e845c8c24", 68 | "reference": "bee7f0dc9c3e0b69a6039697533dca1e845c8c24", 69 | "shasum": "" 70 | }, 71 | "require": { 72 | "php": ">=5.3.0", 73 | "psr/log": "~1.0" 74 | }, 75 | "provide": { 76 | "psr/log-implementation": "1.0.0" 77 | }, 78 | "require-dev": { 79 | "aws/aws-sdk-php": "^2.4.9", 80 | "doctrine/couchdb": "~1.0@dev", 81 | "graylog2/gelf-php": "~1.0", 82 | "jakub-onderka/php-parallel-lint": "0.9", 83 | "php-console/php-console": "^3.1.3", 84 | "phpunit/phpunit": "~4.5", 85 | "phpunit/phpunit-mock-objects": "2.3.0", 86 | "raven/raven": "^0.13", 87 | "ruflin/elastica": ">=0.90 <3.0", 88 | "swiftmailer/swiftmailer": "~5.3", 89 | "videlalvaro/php-amqplib": "~2.4" 90 | }, 91 | "suggest": { 92 | "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", 93 | "doctrine/couchdb": "Allow sending log messages to a CouchDB server", 94 | "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", 95 | "ext-mongo": "Allow sending log messages to a MongoDB server", 96 | "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", 97 | "php-console/php-console": "Allow sending log messages to Google Chrome", 98 | "raven/raven": "Allow sending log messages to a Sentry server", 99 | "rollbar/rollbar": "Allow sending log messages to Rollbar", 100 | "ruflin/elastica": "Allow sending log messages to an Elastic Search server", 101 | "videlalvaro/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib" 102 | }, 103 | "type": "library", 104 | "extra": { 105 | "branch-alias": { 106 | "dev-master": "1.16.x-dev" 107 | } 108 | }, 109 | "autoload": { 110 | "psr-4": { 111 | "Monolog\\": "src/Monolog" 112 | } 113 | }, 114 | "notification-url": "https://packagist.org/downloads/", 115 | "license": [ 116 | "MIT" 117 | ], 118 | "authors": [ 119 | { 120 | "name": "Jordi Boggiano", 121 | "email": "j.boggiano@seld.be", 122 | "homepage": "http://seld.be" 123 | } 124 | ], 125 | "description": "Sends your logs to files, sockets, inboxes, databases and various web services", 126 | "homepage": "http://github.com/Seldaek/monolog", 127 | "keywords": [ 128 | "log", 129 | "logging", 130 | "psr-3" 131 | ], 132 | "time": "2015-10-14T12:51:02+00:00" 133 | }, 134 | { 135 | "name": "phergie/phergie-irc-client-react", 136 | "version": "3.1.0", 137 | "source": { 138 | "type": "git", 139 | "url": "https://github.com/phergie/phergie-irc-client-react.git", 140 | "reference": "471b9e10e98ba874e642e5de48d7dab32b96b5a4" 141 | }, 142 | "dist": { 143 | "type": "zip", 144 | "url": "https://api.github.com/repos/phergie/phergie-irc-client-react/zipball/471b9e10e98ba874e642e5de48d7dab32b96b5a4", 145 | "reference": "471b9e10e98ba874e642e5de48d7dab32b96b5a4", 146 | "shasum": "" 147 | }, 148 | "require": { 149 | "monolog/monolog": "~1.6", 150 | "phergie/phergie-irc-connection": "~2.0", 151 | "phergie/phergie-irc-generator": "~1.5", 152 | "phergie/phergie-irc-parser": "~2.0", 153 | "php": ">=5.5", 154 | "psr/log": "~1.0", 155 | "react/dns": "~0.4.0", 156 | "react/event-loop": "~0.4.0", 157 | "react/promise": "~2.0", 158 | "react/socket-client": "~0.4.2", 159 | "react/stream": "~0.4.2" 160 | }, 161 | "conflict": { 162 | "phergie/phergie-irc-plugin-react-pong": "*" 163 | }, 164 | "require-dev": { 165 | "phergie/phergie-irc-bot-react-development": "~1.0.0" 166 | }, 167 | "type": "library", 168 | "autoload": { 169 | "psr-4": { 170 | "Phergie\\Irc\\Client\\React\\": "src" 171 | } 172 | }, 173 | "notification-url": "https://packagist.org/downloads/", 174 | "license": [ 175 | "BSD-2-Clause" 176 | ], 177 | "description": "IRC client library built on React", 178 | "keywords": [ 179 | "client", 180 | "irc", 181 | "react" 182 | ], 183 | "time": "2016-02-19T15:05:32+00:00" 184 | }, 185 | { 186 | "name": "phergie/phergie-irc-connection", 187 | "version": "2.0.0", 188 | "source": { 189 | "type": "git", 190 | "url": "https://github.com/phergie/phergie-irc-connection.git", 191 | "reference": "c5aa9188693d7ac86dc4842f4dde3d63a523f741" 192 | }, 193 | "dist": { 194 | "type": "zip", 195 | "url": "https://api.github.com/repos/phergie/phergie-irc-connection/zipball/c5aa9188693d7ac86dc4842f4dde3d63a523f741", 196 | "reference": "c5aa9188693d7ac86dc4842f4dde3d63a523f741", 197 | "shasum": "" 198 | }, 199 | "require": { 200 | "php": ">=5.4.2" 201 | }, 202 | "require-dev": { 203 | "phpunit/phpunit": "~4.6" 204 | }, 205 | "type": "library", 206 | "autoload": { 207 | "psr-4": { 208 | "Phergie\\Irc\\": "src" 209 | } 210 | }, 211 | "notification-url": "https://packagist.org/downloads/", 212 | "license": [ 213 | "BSD-2-Clause" 214 | ], 215 | "description": "Data structure for containing information about an IRC client connection", 216 | "keywords": [ 217 | "Connection", 218 | "client", 219 | "irc", 220 | "server" 221 | ], 222 | "time": "2015-05-26T15:14:31+00:00" 223 | }, 224 | { 225 | "name": "phergie/phergie-irc-event", 226 | "version": "1.0.2", 227 | "source": { 228 | "type": "git", 229 | "url": "https://github.com/phergie/phergie-irc-event.git", 230 | "reference": "bccc65cd6371ed441984d23713cfbe197245b677" 231 | }, 232 | "dist": { 233 | "type": "zip", 234 | "url": "https://api.github.com/repos/phergie/phergie-irc-event/zipball/bccc65cd6371ed441984d23713cfbe197245b677", 235 | "reference": "bccc65cd6371ed441984d23713cfbe197245b677", 236 | "shasum": "" 237 | }, 238 | "require": { 239 | "phergie/phergie-irc-connection": "2.*", 240 | "php": ">=5.3.3" 241 | }, 242 | "require-dev": { 243 | "phake/phake": "2.0.0-beta2", 244 | "phpunit/phpunit": "4.1.*" 245 | }, 246 | "type": "library", 247 | "autoload": { 248 | "psr-4": { 249 | "Phergie\\Irc\\Event\\": "src" 250 | } 251 | }, 252 | "notification-url": "https://packagist.org/downloads/", 253 | "license": [ 254 | "BSD-2-Clause" 255 | ], 256 | "description": "PHP data structure for IRC event information", 257 | "keywords": [ 258 | "event", 259 | "irc" 260 | ], 261 | "time": "2015-06-09T17:45:15+00:00" 262 | }, 263 | { 264 | "name": "phergie/phergie-irc-generator", 265 | "version": "1.7.0", 266 | "source": { 267 | "type": "git", 268 | "url": "https://github.com/phergie/phergie-irc-generator.git", 269 | "reference": "d333d7ea44d90dc2defe2a13699f6d4c382c0193" 270 | }, 271 | "dist": { 272 | "type": "zip", 273 | "url": "https://api.github.com/repos/phergie/phergie-irc-generator/zipball/d333d7ea44d90dc2defe2a13699f6d4c382c0193", 274 | "reference": "d333d7ea44d90dc2defe2a13699f6d4c382c0193", 275 | "shasum": "" 276 | }, 277 | "require": { 278 | "php": ">=5.3.3" 279 | }, 280 | "require-dev": { 281 | "phpunit/phpunit": "4.1.*" 282 | }, 283 | "type": "library", 284 | "autoload": { 285 | "psr-4": { 286 | "Phergie\\Irc\\": "src" 287 | } 288 | }, 289 | "notification-url": "https://packagist.org/downloads/", 290 | "license": [ 291 | "BSD-2-Clause" 292 | ], 293 | "description": "Generator for messages conforming to the IRC protocol", 294 | "keywords": [ 295 | "generator", 296 | "irc" 297 | ], 298 | "time": "2015-07-16T16:26:11+00:00" 299 | }, 300 | { 301 | "name": "phergie/phergie-irc-parser", 302 | "version": "2.2.0", 303 | "source": { 304 | "type": "git", 305 | "url": "https://github.com/phergie/phergie-irc-parser.git", 306 | "reference": "cec7ec29ea9bbad5f3d1c0e0271279b3d58fe6ce" 307 | }, 308 | "dist": { 309 | "type": "zip", 310 | "url": "https://api.github.com/repos/phergie/phergie-irc-parser/zipball/cec7ec29ea9bbad5f3d1c0e0271279b3d58fe6ce", 311 | "reference": "cec7ec29ea9bbad5f3d1c0e0271279b3d58fe6ce", 312 | "shasum": "" 313 | }, 314 | "require": { 315 | "php": ">=5.5" 316 | }, 317 | "require-dev": { 318 | "phergie/phergie-irc-bot-react-development": "~1.0.0" 319 | }, 320 | "type": "library", 321 | "autoload": { 322 | "psr-4": { 323 | "Phergie\\Irc\\": "src" 324 | } 325 | }, 326 | "notification-url": "https://packagist.org/downloads/", 327 | "license": [ 328 | "BSD-2-Clause" 329 | ], 330 | "description": "Parser for messages conforming to the IRC protocol", 331 | "keywords": [ 332 | "irc", 333 | "parser" 334 | ], 335 | "time": "2015-11-12T15:21:51+00:00" 336 | }, 337 | { 338 | "name": "psr/log", 339 | "version": "1.0.0", 340 | "source": { 341 | "type": "git", 342 | "url": "https://github.com/php-fig/log.git", 343 | "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" 344 | }, 345 | "dist": { 346 | "type": "zip", 347 | "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", 348 | "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", 349 | "shasum": "" 350 | }, 351 | "type": "library", 352 | "autoload": { 353 | "psr-0": { 354 | "Psr\\Log\\": "" 355 | } 356 | }, 357 | "notification-url": "https://packagist.org/downloads/", 358 | "license": [ 359 | "MIT" 360 | ], 361 | "authors": [ 362 | { 363 | "name": "PHP-FIG", 364 | "homepage": "http://www.php-fig.org/" 365 | } 366 | ], 367 | "description": "Common interface for logging libraries", 368 | "keywords": [ 369 | "log", 370 | "psr", 371 | "psr-3" 372 | ], 373 | "time": "2012-12-21T11:40:51+00:00" 374 | }, 375 | { 376 | "name": "react/cache", 377 | "version": "v0.4.0", 378 | "source": { 379 | "type": "git", 380 | "url": "https://github.com/reactphp/cache.git", 381 | "reference": "9882ab5d8b00617baae83c6996f5a34668c11beb" 382 | }, 383 | "dist": { 384 | "type": "zip", 385 | "url": "https://api.github.com/repos/reactphp/cache/zipball/9882ab5d8b00617baae83c6996f5a34668c11beb", 386 | "reference": "9882ab5d8b00617baae83c6996f5a34668c11beb", 387 | "shasum": "" 388 | }, 389 | "require": { 390 | "php": ">=5.4.0", 391 | "react/promise": "~2.0" 392 | }, 393 | "type": "library", 394 | "extra": { 395 | "branch-alias": { 396 | "dev-master": "0.4-dev" 397 | } 398 | }, 399 | "autoload": { 400 | "psr-4": { 401 | "React\\Cache\\": "" 402 | } 403 | }, 404 | "notification-url": "https://packagist.org/downloads/", 405 | "license": [ 406 | "MIT" 407 | ], 408 | "description": "Async caching.", 409 | "keywords": [ 410 | "cache" 411 | ], 412 | "time": "2014-02-02T01:11:26+00:00" 413 | }, 414 | { 415 | "name": "react/dns", 416 | "version": "v0.4.1", 417 | "source": { 418 | "type": "git", 419 | "url": "https://github.com/reactphp/dns.git", 420 | "reference": "8c5ccc35dcb4b06b70eb9201842363fac7b0f3cf" 421 | }, 422 | "dist": { 423 | "type": "zip", 424 | "url": "https://api.github.com/repos/reactphp/dns/zipball/8c5ccc35dcb4b06b70eb9201842363fac7b0f3cf", 425 | "reference": "8c5ccc35dcb4b06b70eb9201842363fac7b0f3cf", 426 | "shasum": "" 427 | }, 428 | "require": { 429 | "php": ">=5.4.0", 430 | "react/cache": "0.4.*", 431 | "react/promise": "~2.0", 432 | "react/socket": "0.4.*" 433 | }, 434 | "type": "library", 435 | "extra": { 436 | "branch-alias": { 437 | "dev-master": "0.4-dev" 438 | } 439 | }, 440 | "autoload": { 441 | "psr-4": { 442 | "React\\Dns\\": "" 443 | } 444 | }, 445 | "notification-url": "https://packagist.org/downloads/", 446 | "license": [ 447 | "MIT" 448 | ], 449 | "description": "Async DNS resolver.", 450 | "keywords": [ 451 | "dns", 452 | "dns-resolver" 453 | ], 454 | "time": "2014-04-12T14:09:10+00:00" 455 | }, 456 | { 457 | "name": "react/event-loop", 458 | "version": "v0.4.1", 459 | "source": { 460 | "type": "git", 461 | "url": "https://github.com/reactphp/event-loop.git", 462 | "reference": "18c5297087ca01de85518e2b55078f444144aa1b" 463 | }, 464 | "dist": { 465 | "type": "zip", 466 | "url": "https://api.github.com/repos/reactphp/event-loop/zipball/18c5297087ca01de85518e2b55078f444144aa1b", 467 | "reference": "18c5297087ca01de85518e2b55078f444144aa1b", 468 | "shasum": "" 469 | }, 470 | "require": { 471 | "php": ">=5.4.0" 472 | }, 473 | "suggest": { 474 | "ext-event": "~1.0", 475 | "ext-libev": "*", 476 | "ext-libevent": ">=0.1.0" 477 | }, 478 | "type": "library", 479 | "extra": { 480 | "branch-alias": { 481 | "dev-master": "0.4-dev" 482 | } 483 | }, 484 | "autoload": { 485 | "psr-4": { 486 | "React\\EventLoop\\": "" 487 | } 488 | }, 489 | "notification-url": "https://packagist.org/downloads/", 490 | "license": [ 491 | "MIT" 492 | ], 493 | "description": "Event loop abstraction layer that libraries can use for evented I/O.", 494 | "keywords": [ 495 | "event-loop" 496 | ], 497 | "time": "2014-02-26T17:36:58+00:00" 498 | }, 499 | { 500 | "name": "react/promise", 501 | "version": "v2.2.1", 502 | "source": { 503 | "type": "git", 504 | "url": "https://github.com/reactphp/promise.git", 505 | "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627" 506 | }, 507 | "dist": { 508 | "type": "zip", 509 | "url": "https://api.github.com/repos/reactphp/promise/zipball/3b6fca09c7d56321057fa8867c8dbe1abf648627", 510 | "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627", 511 | "shasum": "" 512 | }, 513 | "require": { 514 | "php": ">=5.4.0" 515 | }, 516 | "type": "library", 517 | "extra": { 518 | "branch-alias": { 519 | "dev-master": "2.0-dev" 520 | } 521 | }, 522 | "autoload": { 523 | "psr-4": { 524 | "React\\Promise\\": "src/" 525 | }, 526 | "files": [ 527 | "src/functions_include.php" 528 | ] 529 | }, 530 | "notification-url": "https://packagist.org/downloads/", 531 | "license": [ 532 | "MIT" 533 | ], 534 | "authors": [ 535 | { 536 | "name": "Jan Sorgalla", 537 | "email": "jsorgalla@gmail.com" 538 | } 539 | ], 540 | "description": "A lightweight implementation of CommonJS Promises/A for PHP", 541 | "time": "2015-07-03T13:48:55+00:00" 542 | }, 543 | { 544 | "name": "react/socket", 545 | "version": "v0.4.2", 546 | "source": { 547 | "type": "git", 548 | "url": "https://github.com/reactphp/socket.git", 549 | "reference": "a6acf405ca53fc6cfbfe7c77778ededff46aa7cc" 550 | }, 551 | "dist": { 552 | "type": "zip", 553 | "url": "https://api.github.com/repos/reactphp/socket/zipball/a6acf405ca53fc6cfbfe7c77778ededff46aa7cc", 554 | "reference": "a6acf405ca53fc6cfbfe7c77778ededff46aa7cc", 555 | "shasum": "" 556 | }, 557 | "require": { 558 | "evenement/evenement": "~2.0", 559 | "php": ">=5.4.0", 560 | "react/event-loop": "0.4.*", 561 | "react/stream": "0.4.*" 562 | }, 563 | "type": "library", 564 | "extra": { 565 | "branch-alias": { 566 | "dev-master": "0.4-dev" 567 | } 568 | }, 569 | "autoload": { 570 | "psr-4": { 571 | "React\\Socket\\": "src" 572 | } 573 | }, 574 | "notification-url": "https://packagist.org/downloads/", 575 | "license": [ 576 | "MIT" 577 | ], 578 | "description": "Library for building an evented socket server.", 579 | "keywords": [ 580 | "Socket" 581 | ], 582 | "time": "2014-05-25T17:02:16+00:00" 583 | }, 584 | { 585 | "name": "react/socket-client", 586 | "version": "v0.4.4", 587 | "source": { 588 | "type": "git", 589 | "url": "https://github.com/reactphp/socket-client.git", 590 | "reference": "3ca814d7e03e2a5bffeaa5773423107957a8aece" 591 | }, 592 | "dist": { 593 | "type": "zip", 594 | "url": "https://api.github.com/repos/reactphp/socket-client/zipball/3ca814d7e03e2a5bffeaa5773423107957a8aece", 595 | "reference": "3ca814d7e03e2a5bffeaa5773423107957a8aece", 596 | "shasum": "" 597 | }, 598 | "require": { 599 | "php": ">=5.4.0", 600 | "react/dns": "0.4.*", 601 | "react/event-loop": "0.4.*", 602 | "react/promise": "~2.0", 603 | "react/stream": "0.4.*" 604 | }, 605 | "type": "library", 606 | "extra": { 607 | "branch-alias": { 608 | "dev-master": "0.4-dev" 609 | } 610 | }, 611 | "autoload": { 612 | "psr-4": { 613 | "React\\SocketClient\\": "src" 614 | } 615 | }, 616 | "notification-url": "https://packagist.org/downloads/", 617 | "license": [ 618 | "MIT" 619 | ], 620 | "description": "Async connector to open TCP/IP and SSL/TLS based connections.", 621 | "keywords": [ 622 | "Socket" 623 | ], 624 | "time": "2015-09-23T22:40:04+00:00" 625 | }, 626 | { 627 | "name": "react/stream", 628 | "version": "v0.4.3", 629 | "source": { 630 | "type": "git", 631 | "url": "https://github.com/reactphp/stream.git", 632 | "reference": "305b2328d2a2e157bc13b61a0f5c6e41b666b188" 633 | }, 634 | "dist": { 635 | "type": "zip", 636 | "url": "https://api.github.com/repos/reactphp/stream/zipball/305b2328d2a2e157bc13b61a0f5c6e41b666b188", 637 | "reference": "305b2328d2a2e157bc13b61a0f5c6e41b666b188", 638 | "shasum": "" 639 | }, 640 | "require": { 641 | "evenement/evenement": "^2.0|^1.0", 642 | "php": ">=5.3.8" 643 | }, 644 | "require-dev": { 645 | "react/event-loop": "^0.4|^0.3", 646 | "react/promise": "^2.0|^1.0" 647 | }, 648 | "suggest": { 649 | "react/event-loop": "^0.4", 650 | "react/promise": "^2.0" 651 | }, 652 | "type": "library", 653 | "extra": { 654 | "branch-alias": { 655 | "dev-master": "0.5-dev" 656 | } 657 | }, 658 | "autoload": { 659 | "psr-4": { 660 | "React\\Stream\\": "src" 661 | } 662 | }, 663 | "notification-url": "https://packagist.org/downloads/", 664 | "license": [ 665 | "MIT" 666 | ], 667 | "description": "Basic readable and writable stream interfaces that support piping.", 668 | "keywords": [ 669 | "pipe", 670 | "stream" 671 | ], 672 | "time": "2015-10-07T18:32:58+00:00" 673 | } 674 | ], 675 | "packages-dev": [ 676 | { 677 | "name": "codeclimate/php-test-reporter", 678 | "version": "v0.2.0", 679 | "source": { 680 | "type": "git", 681 | "url": "https://github.com/codeclimate/php-test-reporter.git", 682 | "reference": "85b5de950678a25f3e85adb6bc26de7f7f231d18" 683 | }, 684 | "dist": { 685 | "type": "zip", 686 | "url": "https://api.github.com/repos/codeclimate/php-test-reporter/zipball/85b5de950678a25f3e85adb6bc26de7f7f231d18", 687 | "reference": "85b5de950678a25f3e85adb6bc26de7f7f231d18", 688 | "shasum": "" 689 | }, 690 | "require": { 691 | "ext-curl": "*", 692 | "php": ">=5.3", 693 | "satooshi/php-coveralls": "0.6.*", 694 | "symfony/console": ">=2.0" 695 | }, 696 | "require-dev": { 697 | "ext-xdebug": "*", 698 | "phpunit/phpunit": "3.7.*@stable" 699 | }, 700 | "bin": [ 701 | "composer/bin/test-reporter" 702 | ], 703 | "type": "library", 704 | "extra": { 705 | "branch-alias": { 706 | "dev-master": "0.1.x-dev" 707 | } 708 | }, 709 | "autoload": { 710 | "psr-0": { 711 | "CodeClimate\\Component": "src/", 712 | "CodeClimate\\Bundle": "src/" 713 | } 714 | }, 715 | "notification-url": "https://packagist.org/downloads/", 716 | "license": [ 717 | "MIT" 718 | ], 719 | "authors": [ 720 | { 721 | "name": "Code Climate", 722 | "email": "hello@codeclimate.com", 723 | "homepage": "https://codeclimate.com" 724 | } 725 | ], 726 | "description": "PHP client for reporting test coverage to Code Climate", 727 | "homepage": "https://github.com/codeclimate/php-test-reporter", 728 | "keywords": [ 729 | "codeclimate", 730 | "coverage" 731 | ], 732 | "time": "2015-09-08T14:22:33+00:00" 733 | }, 734 | { 735 | "name": "doctrine/instantiator", 736 | "version": "1.0.5", 737 | "source": { 738 | "type": "git", 739 | "url": "https://github.com/doctrine/instantiator.git", 740 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 741 | }, 742 | "dist": { 743 | "type": "zip", 744 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", 745 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 746 | "shasum": "" 747 | }, 748 | "require": { 749 | "php": ">=5.3,<8.0-DEV" 750 | }, 751 | "require-dev": { 752 | "athletic/athletic": "~0.1.8", 753 | "ext-pdo": "*", 754 | "ext-phar": "*", 755 | "phpunit/phpunit": "~4.0", 756 | "squizlabs/php_codesniffer": "~2.0" 757 | }, 758 | "type": "library", 759 | "extra": { 760 | "branch-alias": { 761 | "dev-master": "1.0.x-dev" 762 | } 763 | }, 764 | "autoload": { 765 | "psr-4": { 766 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 767 | } 768 | }, 769 | "notification-url": "https://packagist.org/downloads/", 770 | "license": [ 771 | "MIT" 772 | ], 773 | "authors": [ 774 | { 775 | "name": "Marco Pivetta", 776 | "email": "ocramius@gmail.com", 777 | "homepage": "http://ocramius.github.com/" 778 | } 779 | ], 780 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 781 | "homepage": "https://github.com/doctrine/instantiator", 782 | "keywords": [ 783 | "constructor", 784 | "instantiate" 785 | ], 786 | "time": "2015-06-14T21:17:01+00:00" 787 | }, 788 | { 789 | "name": "friendsofphp/php-cs-fixer", 790 | "version": "v1.11.8", 791 | "source": { 792 | "type": "git", 793 | "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", 794 | "reference": "117137e9970054d022b7656209f094dab852b90c" 795 | }, 796 | "dist": { 797 | "type": "zip", 798 | "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/117137e9970054d022b7656209f094dab852b90c", 799 | "reference": "117137e9970054d022b7656209f094dab852b90c", 800 | "shasum": "" 801 | }, 802 | "require": { 803 | "ext-tokenizer": "*", 804 | "php": ">=5.3.6", 805 | "sebastian/diff": "~1.1", 806 | "symfony/console": "~2.3|~3.0", 807 | "symfony/event-dispatcher": "~2.1|~3.0", 808 | "symfony/filesystem": "~2.1|~3.0", 809 | "symfony/finder": "~2.1|~3.0", 810 | "symfony/process": "~2.3|~3.0", 811 | "symfony/stopwatch": "~2.5|~3.0" 812 | }, 813 | "conflict": { 814 | "hhvm": "<3.9" 815 | }, 816 | "require-dev": { 817 | "phpunit/phpunit": "^4.5|^5", 818 | "satooshi/php-coveralls": "^0.7.1" 819 | }, 820 | "bin": [ 821 | "php-cs-fixer" 822 | ], 823 | "type": "application", 824 | "autoload": { 825 | "psr-4": { 826 | "Symfony\\CS\\": "Symfony/CS/" 827 | } 828 | }, 829 | "notification-url": "https://packagist.org/downloads/", 830 | "license": [ 831 | "MIT" 832 | ], 833 | "authors": [ 834 | { 835 | "name": "Dariusz Rumiński", 836 | "email": "dariusz.ruminski@gmail.com" 837 | }, 838 | { 839 | "name": "Fabien Potencier", 840 | "email": "fabien@symfony.com" 841 | } 842 | ], 843 | "description": "A tool to automatically fix PHP code style", 844 | "time": "2016-08-16T23:31:05+00:00" 845 | }, 846 | { 847 | "name": "guzzle/guzzle", 848 | "version": "v3.9.3", 849 | "source": { 850 | "type": "git", 851 | "url": "https://github.com/guzzle/guzzle3.git", 852 | "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9" 853 | }, 854 | "dist": { 855 | "type": "zip", 856 | "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9", 857 | "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9", 858 | "shasum": "" 859 | }, 860 | "require": { 861 | "ext-curl": "*", 862 | "php": ">=5.3.3", 863 | "symfony/event-dispatcher": "~2.1" 864 | }, 865 | "replace": { 866 | "guzzle/batch": "self.version", 867 | "guzzle/cache": "self.version", 868 | "guzzle/common": "self.version", 869 | "guzzle/http": "self.version", 870 | "guzzle/inflection": "self.version", 871 | "guzzle/iterator": "self.version", 872 | "guzzle/log": "self.version", 873 | "guzzle/parser": "self.version", 874 | "guzzle/plugin": "self.version", 875 | "guzzle/plugin-async": "self.version", 876 | "guzzle/plugin-backoff": "self.version", 877 | "guzzle/plugin-cache": "self.version", 878 | "guzzle/plugin-cookie": "self.version", 879 | "guzzle/plugin-curlauth": "self.version", 880 | "guzzle/plugin-error-response": "self.version", 881 | "guzzle/plugin-history": "self.version", 882 | "guzzle/plugin-log": "self.version", 883 | "guzzle/plugin-md5": "self.version", 884 | "guzzle/plugin-mock": "self.version", 885 | "guzzle/plugin-oauth": "self.version", 886 | "guzzle/service": "self.version", 887 | "guzzle/stream": "self.version" 888 | }, 889 | "require-dev": { 890 | "doctrine/cache": "~1.3", 891 | "monolog/monolog": "~1.0", 892 | "phpunit/phpunit": "3.7.*", 893 | "psr/log": "~1.0", 894 | "symfony/class-loader": "~2.1", 895 | "zendframework/zend-cache": "2.*,<2.3", 896 | "zendframework/zend-log": "2.*,<2.3" 897 | }, 898 | "suggest": { 899 | "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated." 900 | }, 901 | "type": "library", 902 | "extra": { 903 | "branch-alias": { 904 | "dev-master": "3.9-dev" 905 | } 906 | }, 907 | "autoload": { 908 | "psr-0": { 909 | "Guzzle": "src/", 910 | "Guzzle\\Tests": "tests/" 911 | } 912 | }, 913 | "notification-url": "https://packagist.org/downloads/", 914 | "license": [ 915 | "MIT" 916 | ], 917 | "authors": [ 918 | { 919 | "name": "Michael Dowling", 920 | "email": "mtdowling@gmail.com", 921 | "homepage": "https://github.com/mtdowling" 922 | }, 923 | { 924 | "name": "Guzzle Community", 925 | "homepage": "https://github.com/guzzle/guzzle/contributors" 926 | } 927 | ], 928 | "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle", 929 | "homepage": "http://guzzlephp.org/", 930 | "keywords": [ 931 | "client", 932 | "curl", 933 | "framework", 934 | "http", 935 | "http client", 936 | "rest", 937 | "web service" 938 | ], 939 | "abandoned": "guzzlehttp/guzzle", 940 | "time": "2015-03-18T18:23:50+00:00" 941 | }, 942 | { 943 | "name": "phake/phake", 944 | "version": "v2.2.0", 945 | "source": { 946 | "type": "git", 947 | "url": "https://github.com/mlively/Phake.git", 948 | "reference": "9c3c287ef3f23d5ca438917ab1a4f8c47b654b4b" 949 | }, 950 | "dist": { 951 | "type": "zip", 952 | "url": "https://api.github.com/repos/mlively/Phake/zipball/9c3c287ef3f23d5ca438917ab1a4f8c47b654b4b", 953 | "reference": "9c3c287ef3f23d5ca438917ab1a4f8c47b654b4b", 954 | "shasum": "" 955 | }, 956 | "require": { 957 | "php": ">=5.3.3", 958 | "sebastian/comparator": "~1.1" 959 | }, 960 | "require-dev": { 961 | "codeclimate/php-test-reporter": "dev-master", 962 | "doctrine/common": "2.3.*", 963 | "ext-soap": "*", 964 | "hamcrest/hamcrest-php": "1.1.*", 965 | "phpunit/phpunit": "3.7.*" 966 | }, 967 | "suggest": { 968 | "doctrine/common": "Allows mock annotations to use import statements for classes.", 969 | "hamcrest/hamcrest-php": "Use Hamcrest matchers." 970 | }, 971 | "type": "library", 972 | "extra": { 973 | "branch-alias": { 974 | "dev-master": "3.0.0-dev" 975 | } 976 | }, 977 | "autoload": { 978 | "psr-0": { 979 | "Phake": "src/" 980 | } 981 | }, 982 | "notification-url": "https://packagist.org/downloads/", 983 | "license": [ 984 | "BSD-3-Clause" 985 | ], 986 | "authors": [ 987 | { 988 | "name": "Mike Lively", 989 | "email": "m@digitalsandwich.com" 990 | } 991 | ], 992 | "description": "The Phake mock testing library", 993 | "homepage": "https://github.com/mlively/Phake", 994 | "keywords": [ 995 | "mock", 996 | "testing" 997 | ], 998 | "time": "2015-11-30T17:02:04+00:00" 999 | }, 1000 | { 1001 | "name": "phergie/phergie-irc-bot-react-development", 1002 | "version": "1.0.2", 1003 | "source": { 1004 | "type": "git", 1005 | "url": "https://github.com/phergie/phergie-irc-bot-react-development.git", 1006 | "reference": "a2a077dbe4cea47d477659233c181e154c4e831f" 1007 | }, 1008 | "dist": { 1009 | "type": "zip", 1010 | "url": "https://api.github.com/repos/phergie/phergie-irc-bot-react-development/zipball/a2a077dbe4cea47d477659233c181e154c4e831f", 1011 | "reference": "a2a077dbe4cea47d477659233c181e154c4e831f", 1012 | "shasum": "" 1013 | }, 1014 | "require": { 1015 | "codeclimate/php-test-reporter": "~0.1", 1016 | "phake/phake": "~2.0", 1017 | "phpunit/phpunit": "~4.6", 1018 | "satooshi/php-coveralls": "0.6.1", 1019 | "squizlabs/php_codesniffer": "^1.5.3", 1020 | "symfony/config": "~2.0", 1021 | "symfony/console": "~2.0", 1022 | "symfony/filesystem": "~2.0", 1023 | "symfony/stopwatch": "~2.0", 1024 | "vectorface/dunit": "^2.0" 1025 | }, 1026 | "type": "library", 1027 | "notification-url": "https://packagist.org/downloads/", 1028 | "license": [ 1029 | "BSD-2-Clause" 1030 | ], 1031 | "description": "Development Dependencies for phergie-irc-bot-react", 1032 | "keywords": [ 1033 | "bot", 1034 | "irc", 1035 | "react" 1036 | ], 1037 | "time": "2015-11-10T03:33:26+00:00" 1038 | }, 1039 | { 1040 | "name": "phpdocumentor/reflection-docblock", 1041 | "version": "2.0.4", 1042 | "source": { 1043 | "type": "git", 1044 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 1045 | "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" 1046 | }, 1047 | "dist": { 1048 | "type": "zip", 1049 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", 1050 | "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", 1051 | "shasum": "" 1052 | }, 1053 | "require": { 1054 | "php": ">=5.3.3" 1055 | }, 1056 | "require-dev": { 1057 | "phpunit/phpunit": "~4.0" 1058 | }, 1059 | "suggest": { 1060 | "dflydev/markdown": "~1.0", 1061 | "erusev/parsedown": "~1.0" 1062 | }, 1063 | "type": "library", 1064 | "extra": { 1065 | "branch-alias": { 1066 | "dev-master": "2.0.x-dev" 1067 | } 1068 | }, 1069 | "autoload": { 1070 | "psr-0": { 1071 | "phpDocumentor": [ 1072 | "src/" 1073 | ] 1074 | } 1075 | }, 1076 | "notification-url": "https://packagist.org/downloads/", 1077 | "license": [ 1078 | "MIT" 1079 | ], 1080 | "authors": [ 1081 | { 1082 | "name": "Mike van Riel", 1083 | "email": "mike.vanriel@naenius.com" 1084 | } 1085 | ], 1086 | "time": "2015-02-03T12:10:50+00:00" 1087 | }, 1088 | { 1089 | "name": "phpspec/prophecy", 1090 | "version": "v1.5.0", 1091 | "source": { 1092 | "type": "git", 1093 | "url": "https://github.com/phpspec/prophecy.git", 1094 | "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7" 1095 | }, 1096 | "dist": { 1097 | "type": "zip", 1098 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4745ded9307786b730d7a60df5cb5a6c43cf95f7", 1099 | "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7", 1100 | "shasum": "" 1101 | }, 1102 | "require": { 1103 | "doctrine/instantiator": "^1.0.2", 1104 | "phpdocumentor/reflection-docblock": "~2.0", 1105 | "sebastian/comparator": "~1.1" 1106 | }, 1107 | "require-dev": { 1108 | "phpspec/phpspec": "~2.0" 1109 | }, 1110 | "type": "library", 1111 | "extra": { 1112 | "branch-alias": { 1113 | "dev-master": "1.4.x-dev" 1114 | } 1115 | }, 1116 | "autoload": { 1117 | "psr-0": { 1118 | "Prophecy\\": "src/" 1119 | } 1120 | }, 1121 | "notification-url": "https://packagist.org/downloads/", 1122 | "license": [ 1123 | "MIT" 1124 | ], 1125 | "authors": [ 1126 | { 1127 | "name": "Konstantin Kudryashov", 1128 | "email": "ever.zet@gmail.com", 1129 | "homepage": "http://everzet.com" 1130 | }, 1131 | { 1132 | "name": "Marcello Duarte", 1133 | "email": "marcello.duarte@gmail.com" 1134 | } 1135 | ], 1136 | "description": "Highly opinionated mocking framework for PHP 5.3+", 1137 | "homepage": "https://github.com/phpspec/prophecy", 1138 | "keywords": [ 1139 | "Double", 1140 | "Dummy", 1141 | "fake", 1142 | "mock", 1143 | "spy", 1144 | "stub" 1145 | ], 1146 | "time": "2015-08-13T10:07:40+00:00" 1147 | }, 1148 | { 1149 | "name": "phpunit/php-code-coverage", 1150 | "version": "2.2.4", 1151 | "source": { 1152 | "type": "git", 1153 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 1154 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" 1155 | }, 1156 | "dist": { 1157 | "type": "zip", 1158 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", 1159 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", 1160 | "shasum": "" 1161 | }, 1162 | "require": { 1163 | "php": ">=5.3.3", 1164 | "phpunit/php-file-iterator": "~1.3", 1165 | "phpunit/php-text-template": "~1.2", 1166 | "phpunit/php-token-stream": "~1.3", 1167 | "sebastian/environment": "^1.3.2", 1168 | "sebastian/version": "~1.0" 1169 | }, 1170 | "require-dev": { 1171 | "ext-xdebug": ">=2.1.4", 1172 | "phpunit/phpunit": "~4" 1173 | }, 1174 | "suggest": { 1175 | "ext-dom": "*", 1176 | "ext-xdebug": ">=2.2.1", 1177 | "ext-xmlwriter": "*" 1178 | }, 1179 | "type": "library", 1180 | "extra": { 1181 | "branch-alias": { 1182 | "dev-master": "2.2.x-dev" 1183 | } 1184 | }, 1185 | "autoload": { 1186 | "classmap": [ 1187 | "src/" 1188 | ] 1189 | }, 1190 | "notification-url": "https://packagist.org/downloads/", 1191 | "license": [ 1192 | "BSD-3-Clause" 1193 | ], 1194 | "authors": [ 1195 | { 1196 | "name": "Sebastian Bergmann", 1197 | "email": "sb@sebastian-bergmann.de", 1198 | "role": "lead" 1199 | } 1200 | ], 1201 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 1202 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 1203 | "keywords": [ 1204 | "coverage", 1205 | "testing", 1206 | "xunit" 1207 | ], 1208 | "time": "2015-10-06T15:47:00+00:00" 1209 | }, 1210 | { 1211 | "name": "phpunit/php-file-iterator", 1212 | "version": "1.4.1", 1213 | "source": { 1214 | "type": "git", 1215 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 1216 | "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" 1217 | }, 1218 | "dist": { 1219 | "type": "zip", 1220 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", 1221 | "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", 1222 | "shasum": "" 1223 | }, 1224 | "require": { 1225 | "php": ">=5.3.3" 1226 | }, 1227 | "type": "library", 1228 | "extra": { 1229 | "branch-alias": { 1230 | "dev-master": "1.4.x-dev" 1231 | } 1232 | }, 1233 | "autoload": { 1234 | "classmap": [ 1235 | "src/" 1236 | ] 1237 | }, 1238 | "notification-url": "https://packagist.org/downloads/", 1239 | "license": [ 1240 | "BSD-3-Clause" 1241 | ], 1242 | "authors": [ 1243 | { 1244 | "name": "Sebastian Bergmann", 1245 | "email": "sb@sebastian-bergmann.de", 1246 | "role": "lead" 1247 | } 1248 | ], 1249 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 1250 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 1251 | "keywords": [ 1252 | "filesystem", 1253 | "iterator" 1254 | ], 1255 | "time": "2015-06-21T13:08:43+00:00" 1256 | }, 1257 | { 1258 | "name": "phpunit/php-text-template", 1259 | "version": "1.2.1", 1260 | "source": { 1261 | "type": "git", 1262 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 1263 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 1264 | }, 1265 | "dist": { 1266 | "type": "zip", 1267 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1268 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1269 | "shasum": "" 1270 | }, 1271 | "require": { 1272 | "php": ">=5.3.3" 1273 | }, 1274 | "type": "library", 1275 | "autoload": { 1276 | "classmap": [ 1277 | "src/" 1278 | ] 1279 | }, 1280 | "notification-url": "https://packagist.org/downloads/", 1281 | "license": [ 1282 | "BSD-3-Clause" 1283 | ], 1284 | "authors": [ 1285 | { 1286 | "name": "Sebastian Bergmann", 1287 | "email": "sebastian@phpunit.de", 1288 | "role": "lead" 1289 | } 1290 | ], 1291 | "description": "Simple template engine.", 1292 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 1293 | "keywords": [ 1294 | "template" 1295 | ], 1296 | "time": "2015-06-21T13:50:34+00:00" 1297 | }, 1298 | { 1299 | "name": "phpunit/php-timer", 1300 | "version": "1.0.7", 1301 | "source": { 1302 | "type": "git", 1303 | "url": "https://github.com/sebastianbergmann/php-timer.git", 1304 | "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" 1305 | }, 1306 | "dist": { 1307 | "type": "zip", 1308 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", 1309 | "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", 1310 | "shasum": "" 1311 | }, 1312 | "require": { 1313 | "php": ">=5.3.3" 1314 | }, 1315 | "type": "library", 1316 | "autoload": { 1317 | "classmap": [ 1318 | "src/" 1319 | ] 1320 | }, 1321 | "notification-url": "https://packagist.org/downloads/", 1322 | "license": [ 1323 | "BSD-3-Clause" 1324 | ], 1325 | "authors": [ 1326 | { 1327 | "name": "Sebastian Bergmann", 1328 | "email": "sb@sebastian-bergmann.de", 1329 | "role": "lead" 1330 | } 1331 | ], 1332 | "description": "Utility class for timing", 1333 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 1334 | "keywords": [ 1335 | "timer" 1336 | ], 1337 | "time": "2015-06-21T08:01:12+00:00" 1338 | }, 1339 | { 1340 | "name": "phpunit/php-token-stream", 1341 | "version": "1.4.8", 1342 | "source": { 1343 | "type": "git", 1344 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 1345 | "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" 1346 | }, 1347 | "dist": { 1348 | "type": "zip", 1349 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", 1350 | "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", 1351 | "shasum": "" 1352 | }, 1353 | "require": { 1354 | "ext-tokenizer": "*", 1355 | "php": ">=5.3.3" 1356 | }, 1357 | "require-dev": { 1358 | "phpunit/phpunit": "~4.2" 1359 | }, 1360 | "type": "library", 1361 | "extra": { 1362 | "branch-alias": { 1363 | "dev-master": "1.4-dev" 1364 | } 1365 | }, 1366 | "autoload": { 1367 | "classmap": [ 1368 | "src/" 1369 | ] 1370 | }, 1371 | "notification-url": "https://packagist.org/downloads/", 1372 | "license": [ 1373 | "BSD-3-Clause" 1374 | ], 1375 | "authors": [ 1376 | { 1377 | "name": "Sebastian Bergmann", 1378 | "email": "sebastian@phpunit.de" 1379 | } 1380 | ], 1381 | "description": "Wrapper around PHP's tokenizer extension.", 1382 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 1383 | "keywords": [ 1384 | "tokenizer" 1385 | ], 1386 | "time": "2015-09-15T10:49:45+00:00" 1387 | }, 1388 | { 1389 | "name": "phpunit/phpunit", 1390 | "version": "4.8.21", 1391 | "source": { 1392 | "type": "git", 1393 | "url": "https://github.com/sebastianbergmann/phpunit.git", 1394 | "reference": "ea76b17bced0500a28098626b84eda12dbcf119c" 1395 | }, 1396 | "dist": { 1397 | "type": "zip", 1398 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ea76b17bced0500a28098626b84eda12dbcf119c", 1399 | "reference": "ea76b17bced0500a28098626b84eda12dbcf119c", 1400 | "shasum": "" 1401 | }, 1402 | "require": { 1403 | "ext-dom": "*", 1404 | "ext-json": "*", 1405 | "ext-pcre": "*", 1406 | "ext-reflection": "*", 1407 | "ext-spl": "*", 1408 | "php": ">=5.3.3", 1409 | "phpspec/prophecy": "^1.3.1", 1410 | "phpunit/php-code-coverage": "~2.1", 1411 | "phpunit/php-file-iterator": "~1.4", 1412 | "phpunit/php-text-template": "~1.2", 1413 | "phpunit/php-timer": ">=1.0.6", 1414 | "phpunit/phpunit-mock-objects": "~2.3", 1415 | "sebastian/comparator": "~1.1", 1416 | "sebastian/diff": "~1.2", 1417 | "sebastian/environment": "~1.3", 1418 | "sebastian/exporter": "~1.2", 1419 | "sebastian/global-state": "~1.0", 1420 | "sebastian/version": "~1.0", 1421 | "symfony/yaml": "~2.1|~3.0" 1422 | }, 1423 | "suggest": { 1424 | "phpunit/php-invoker": "~1.1" 1425 | }, 1426 | "bin": [ 1427 | "phpunit" 1428 | ], 1429 | "type": "library", 1430 | "extra": { 1431 | "branch-alias": { 1432 | "dev-master": "4.8.x-dev" 1433 | } 1434 | }, 1435 | "autoload": { 1436 | "classmap": [ 1437 | "src/" 1438 | ] 1439 | }, 1440 | "notification-url": "https://packagist.org/downloads/", 1441 | "license": [ 1442 | "BSD-3-Clause" 1443 | ], 1444 | "authors": [ 1445 | { 1446 | "name": "Sebastian Bergmann", 1447 | "email": "sebastian@phpunit.de", 1448 | "role": "lead" 1449 | } 1450 | ], 1451 | "description": "The PHP Unit Testing framework.", 1452 | "homepage": "https://phpunit.de/", 1453 | "keywords": [ 1454 | "phpunit", 1455 | "testing", 1456 | "xunit" 1457 | ], 1458 | "time": "2015-12-12T07:45:58+00:00" 1459 | }, 1460 | { 1461 | "name": "phpunit/phpunit-mock-objects", 1462 | "version": "2.3.8", 1463 | "source": { 1464 | "type": "git", 1465 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 1466 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" 1467 | }, 1468 | "dist": { 1469 | "type": "zip", 1470 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", 1471 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", 1472 | "shasum": "" 1473 | }, 1474 | "require": { 1475 | "doctrine/instantiator": "^1.0.2", 1476 | "php": ">=5.3.3", 1477 | "phpunit/php-text-template": "~1.2", 1478 | "sebastian/exporter": "~1.2" 1479 | }, 1480 | "require-dev": { 1481 | "phpunit/phpunit": "~4.4" 1482 | }, 1483 | "suggest": { 1484 | "ext-soap": "*" 1485 | }, 1486 | "type": "library", 1487 | "extra": { 1488 | "branch-alias": { 1489 | "dev-master": "2.3.x-dev" 1490 | } 1491 | }, 1492 | "autoload": { 1493 | "classmap": [ 1494 | "src/" 1495 | ] 1496 | }, 1497 | "notification-url": "https://packagist.org/downloads/", 1498 | "license": [ 1499 | "BSD-3-Clause" 1500 | ], 1501 | "authors": [ 1502 | { 1503 | "name": "Sebastian Bergmann", 1504 | "email": "sb@sebastian-bergmann.de", 1505 | "role": "lead" 1506 | } 1507 | ], 1508 | "description": "Mock Object library for PHPUnit", 1509 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 1510 | "keywords": [ 1511 | "mock", 1512 | "xunit" 1513 | ], 1514 | "time": "2015-10-02T06:51:40+00:00" 1515 | }, 1516 | { 1517 | "name": "satooshi/php-coveralls", 1518 | "version": "v0.6.1", 1519 | "source": { 1520 | "type": "git", 1521 | "url": "https://github.com/satooshi/php-coveralls.git", 1522 | "reference": "dd0df95bd37a7cf5c5c50304dfe260ffe4b50760" 1523 | }, 1524 | "dist": { 1525 | "type": "zip", 1526 | "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/dd0df95bd37a7cf5c5c50304dfe260ffe4b50760", 1527 | "reference": "dd0df95bd37a7cf5c5c50304dfe260ffe4b50760", 1528 | "shasum": "" 1529 | }, 1530 | "require": { 1531 | "ext-curl": "*", 1532 | "ext-json": "*", 1533 | "ext-simplexml": "*", 1534 | "guzzle/guzzle": ">=3.0", 1535 | "php": ">=5.3", 1536 | "psr/log": "1.0.0", 1537 | "symfony/config": ">=2.0", 1538 | "symfony/console": ">=2.0", 1539 | "symfony/stopwatch": ">=2.2", 1540 | "symfony/yaml": ">=2.0" 1541 | }, 1542 | "require-dev": { 1543 | "apigen/apigen": "2.8.*@stable", 1544 | "pdepend/pdepend": "dev-master", 1545 | "phpmd/phpmd": "dev-master", 1546 | "phpunit/php-invoker": ">=1.1.0,<1.2.0", 1547 | "phpunit/phpunit": "3.7.*@stable", 1548 | "sebastian/finder-facade": "dev-master", 1549 | "sebastian/phpcpd": "1.4.*@stable", 1550 | "squizlabs/php_codesniffer": "1.4.*@stable", 1551 | "theseer/fdomdocument": "dev-master" 1552 | }, 1553 | "bin": [ 1554 | "composer/bin/coveralls" 1555 | ], 1556 | "type": "library", 1557 | "autoload": { 1558 | "psr-0": { 1559 | "Contrib\\Component": "src/", 1560 | "Contrib\\Bundle": "src/" 1561 | } 1562 | }, 1563 | "notification-url": "https://packagist.org/downloads/", 1564 | "license": [ 1565 | "MIT" 1566 | ], 1567 | "authors": [ 1568 | { 1569 | "name": "Kitamura Satoshi", 1570 | "email": "with.no.parachute@gmail.com", 1571 | "homepage": "https://www.facebook.com/satooshi.jp" 1572 | } 1573 | ], 1574 | "description": "PHP client library for Coveralls API", 1575 | "homepage": "https://github.com/satooshi/php-coveralls", 1576 | "keywords": [ 1577 | "ci", 1578 | "coverage", 1579 | "github", 1580 | "test" 1581 | ], 1582 | "time": "2013-05-04T08:07:33+00:00" 1583 | }, 1584 | { 1585 | "name": "sebastian/comparator", 1586 | "version": "1.2.0", 1587 | "source": { 1588 | "type": "git", 1589 | "url": "https://github.com/sebastianbergmann/comparator.git", 1590 | "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" 1591 | }, 1592 | "dist": { 1593 | "type": "zip", 1594 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", 1595 | "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", 1596 | "shasum": "" 1597 | }, 1598 | "require": { 1599 | "php": ">=5.3.3", 1600 | "sebastian/diff": "~1.2", 1601 | "sebastian/exporter": "~1.2" 1602 | }, 1603 | "require-dev": { 1604 | "phpunit/phpunit": "~4.4" 1605 | }, 1606 | "type": "library", 1607 | "extra": { 1608 | "branch-alias": { 1609 | "dev-master": "1.2.x-dev" 1610 | } 1611 | }, 1612 | "autoload": { 1613 | "classmap": [ 1614 | "src/" 1615 | ] 1616 | }, 1617 | "notification-url": "https://packagist.org/downloads/", 1618 | "license": [ 1619 | "BSD-3-Clause" 1620 | ], 1621 | "authors": [ 1622 | { 1623 | "name": "Jeff Welch", 1624 | "email": "whatthejeff@gmail.com" 1625 | }, 1626 | { 1627 | "name": "Volker Dusch", 1628 | "email": "github@wallbash.com" 1629 | }, 1630 | { 1631 | "name": "Bernhard Schussek", 1632 | "email": "bschussek@2bepublished.at" 1633 | }, 1634 | { 1635 | "name": "Sebastian Bergmann", 1636 | "email": "sebastian@phpunit.de" 1637 | } 1638 | ], 1639 | "description": "Provides the functionality to compare PHP values for equality", 1640 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 1641 | "keywords": [ 1642 | "comparator", 1643 | "compare", 1644 | "equality" 1645 | ], 1646 | "time": "2015-07-26T15:48:44+00:00" 1647 | }, 1648 | { 1649 | "name": "sebastian/diff", 1650 | "version": "1.4.1", 1651 | "source": { 1652 | "type": "git", 1653 | "url": "https://github.com/sebastianbergmann/diff.git", 1654 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" 1655 | }, 1656 | "dist": { 1657 | "type": "zip", 1658 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", 1659 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", 1660 | "shasum": "" 1661 | }, 1662 | "require": { 1663 | "php": ">=5.3.3" 1664 | }, 1665 | "require-dev": { 1666 | "phpunit/phpunit": "~4.8" 1667 | }, 1668 | "type": "library", 1669 | "extra": { 1670 | "branch-alias": { 1671 | "dev-master": "1.4-dev" 1672 | } 1673 | }, 1674 | "autoload": { 1675 | "classmap": [ 1676 | "src/" 1677 | ] 1678 | }, 1679 | "notification-url": "https://packagist.org/downloads/", 1680 | "license": [ 1681 | "BSD-3-Clause" 1682 | ], 1683 | "authors": [ 1684 | { 1685 | "name": "Kore Nordmann", 1686 | "email": "mail@kore-nordmann.de" 1687 | }, 1688 | { 1689 | "name": "Sebastian Bergmann", 1690 | "email": "sebastian@phpunit.de" 1691 | } 1692 | ], 1693 | "description": "Diff implementation", 1694 | "homepage": "https://github.com/sebastianbergmann/diff", 1695 | "keywords": [ 1696 | "diff" 1697 | ], 1698 | "time": "2015-12-08T07:14:41+00:00" 1699 | }, 1700 | { 1701 | "name": "sebastian/environment", 1702 | "version": "1.3.3", 1703 | "source": { 1704 | "type": "git", 1705 | "url": "https://github.com/sebastianbergmann/environment.git", 1706 | "reference": "6e7133793a8e5a5714a551a8324337374be209df" 1707 | }, 1708 | "dist": { 1709 | "type": "zip", 1710 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e7133793a8e5a5714a551a8324337374be209df", 1711 | "reference": "6e7133793a8e5a5714a551a8324337374be209df", 1712 | "shasum": "" 1713 | }, 1714 | "require": { 1715 | "php": ">=5.3.3" 1716 | }, 1717 | "require-dev": { 1718 | "phpunit/phpunit": "~4.4" 1719 | }, 1720 | "type": "library", 1721 | "extra": { 1722 | "branch-alias": { 1723 | "dev-master": "1.3.x-dev" 1724 | } 1725 | }, 1726 | "autoload": { 1727 | "classmap": [ 1728 | "src/" 1729 | ] 1730 | }, 1731 | "notification-url": "https://packagist.org/downloads/", 1732 | "license": [ 1733 | "BSD-3-Clause" 1734 | ], 1735 | "authors": [ 1736 | { 1737 | "name": "Sebastian Bergmann", 1738 | "email": "sebastian@phpunit.de" 1739 | } 1740 | ], 1741 | "description": "Provides functionality to handle HHVM/PHP environments", 1742 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1743 | "keywords": [ 1744 | "Xdebug", 1745 | "environment", 1746 | "hhvm" 1747 | ], 1748 | "time": "2015-12-02T08:37:27+00:00" 1749 | }, 1750 | { 1751 | "name": "sebastian/exporter", 1752 | "version": "1.2.1", 1753 | "source": { 1754 | "type": "git", 1755 | "url": "https://github.com/sebastianbergmann/exporter.git", 1756 | "reference": "7ae5513327cb536431847bcc0c10edba2701064e" 1757 | }, 1758 | "dist": { 1759 | "type": "zip", 1760 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", 1761 | "reference": "7ae5513327cb536431847bcc0c10edba2701064e", 1762 | "shasum": "" 1763 | }, 1764 | "require": { 1765 | "php": ">=5.3.3", 1766 | "sebastian/recursion-context": "~1.0" 1767 | }, 1768 | "require-dev": { 1769 | "phpunit/phpunit": "~4.4" 1770 | }, 1771 | "type": "library", 1772 | "extra": { 1773 | "branch-alias": { 1774 | "dev-master": "1.2.x-dev" 1775 | } 1776 | }, 1777 | "autoload": { 1778 | "classmap": [ 1779 | "src/" 1780 | ] 1781 | }, 1782 | "notification-url": "https://packagist.org/downloads/", 1783 | "license": [ 1784 | "BSD-3-Clause" 1785 | ], 1786 | "authors": [ 1787 | { 1788 | "name": "Jeff Welch", 1789 | "email": "whatthejeff@gmail.com" 1790 | }, 1791 | { 1792 | "name": "Volker Dusch", 1793 | "email": "github@wallbash.com" 1794 | }, 1795 | { 1796 | "name": "Bernhard Schussek", 1797 | "email": "bschussek@2bepublished.at" 1798 | }, 1799 | { 1800 | "name": "Sebastian Bergmann", 1801 | "email": "sebastian@phpunit.de" 1802 | }, 1803 | { 1804 | "name": "Adam Harvey", 1805 | "email": "aharvey@php.net" 1806 | } 1807 | ], 1808 | "description": "Provides the functionality to export PHP variables for visualization", 1809 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1810 | "keywords": [ 1811 | "export", 1812 | "exporter" 1813 | ], 1814 | "time": "2015-06-21T07:55:53+00:00" 1815 | }, 1816 | { 1817 | "name": "sebastian/global-state", 1818 | "version": "1.1.1", 1819 | "source": { 1820 | "type": "git", 1821 | "url": "https://github.com/sebastianbergmann/global-state.git", 1822 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" 1823 | }, 1824 | "dist": { 1825 | "type": "zip", 1826 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", 1827 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", 1828 | "shasum": "" 1829 | }, 1830 | "require": { 1831 | "php": ">=5.3.3" 1832 | }, 1833 | "require-dev": { 1834 | "phpunit/phpunit": "~4.2" 1835 | }, 1836 | "suggest": { 1837 | "ext-uopz": "*" 1838 | }, 1839 | "type": "library", 1840 | "extra": { 1841 | "branch-alias": { 1842 | "dev-master": "1.0-dev" 1843 | } 1844 | }, 1845 | "autoload": { 1846 | "classmap": [ 1847 | "src/" 1848 | ] 1849 | }, 1850 | "notification-url": "https://packagist.org/downloads/", 1851 | "license": [ 1852 | "BSD-3-Clause" 1853 | ], 1854 | "authors": [ 1855 | { 1856 | "name": "Sebastian Bergmann", 1857 | "email": "sebastian@phpunit.de" 1858 | } 1859 | ], 1860 | "description": "Snapshotting of global state", 1861 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1862 | "keywords": [ 1863 | "global state" 1864 | ], 1865 | "time": "2015-10-12T03:26:01+00:00" 1866 | }, 1867 | { 1868 | "name": "sebastian/recursion-context", 1869 | "version": "1.0.2", 1870 | "source": { 1871 | "type": "git", 1872 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1873 | "reference": "913401df809e99e4f47b27cdd781f4a258d58791" 1874 | }, 1875 | "dist": { 1876 | "type": "zip", 1877 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", 1878 | "reference": "913401df809e99e4f47b27cdd781f4a258d58791", 1879 | "shasum": "" 1880 | }, 1881 | "require": { 1882 | "php": ">=5.3.3" 1883 | }, 1884 | "require-dev": { 1885 | "phpunit/phpunit": "~4.4" 1886 | }, 1887 | "type": "library", 1888 | "extra": { 1889 | "branch-alias": { 1890 | "dev-master": "1.0.x-dev" 1891 | } 1892 | }, 1893 | "autoload": { 1894 | "classmap": [ 1895 | "src/" 1896 | ] 1897 | }, 1898 | "notification-url": "https://packagist.org/downloads/", 1899 | "license": [ 1900 | "BSD-3-Clause" 1901 | ], 1902 | "authors": [ 1903 | { 1904 | "name": "Jeff Welch", 1905 | "email": "whatthejeff@gmail.com" 1906 | }, 1907 | { 1908 | "name": "Sebastian Bergmann", 1909 | "email": "sebastian@phpunit.de" 1910 | }, 1911 | { 1912 | "name": "Adam Harvey", 1913 | "email": "aharvey@php.net" 1914 | } 1915 | ], 1916 | "description": "Provides functionality to recursively process PHP variables", 1917 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1918 | "time": "2015-11-11T19:50:13+00:00" 1919 | }, 1920 | { 1921 | "name": "sebastian/version", 1922 | "version": "1.0.6", 1923 | "source": { 1924 | "type": "git", 1925 | "url": "https://github.com/sebastianbergmann/version.git", 1926 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" 1927 | }, 1928 | "dist": { 1929 | "type": "zip", 1930 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 1931 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 1932 | "shasum": "" 1933 | }, 1934 | "type": "library", 1935 | "autoload": { 1936 | "classmap": [ 1937 | "src/" 1938 | ] 1939 | }, 1940 | "notification-url": "https://packagist.org/downloads/", 1941 | "license": [ 1942 | "BSD-3-Clause" 1943 | ], 1944 | "authors": [ 1945 | { 1946 | "name": "Sebastian Bergmann", 1947 | "email": "sebastian@phpunit.de", 1948 | "role": "lead" 1949 | } 1950 | ], 1951 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1952 | "homepage": "https://github.com/sebastianbergmann/version", 1953 | "time": "2015-06-21T13:59:46+00:00" 1954 | }, 1955 | { 1956 | "name": "squizlabs/php_codesniffer", 1957 | "version": "1.5.6", 1958 | "source": { 1959 | "type": "git", 1960 | "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", 1961 | "reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5" 1962 | }, 1963 | "dist": { 1964 | "type": "zip", 1965 | "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/6f3e42d311b882b25b4d409d23a289f4d3b803d5", 1966 | "reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5", 1967 | "shasum": "" 1968 | }, 1969 | "require": { 1970 | "ext-tokenizer": "*", 1971 | "php": ">=5.1.2" 1972 | }, 1973 | "suggest": { 1974 | "phpunit/php-timer": "dev-master" 1975 | }, 1976 | "bin": [ 1977 | "scripts/phpcs" 1978 | ], 1979 | "type": "library", 1980 | "extra": { 1981 | "branch-alias": { 1982 | "dev-phpcs-fixer": "2.0.x-dev" 1983 | } 1984 | }, 1985 | "autoload": { 1986 | "classmap": [ 1987 | "CodeSniffer.php", 1988 | "CodeSniffer/CLI.php", 1989 | "CodeSniffer/Exception.php", 1990 | "CodeSniffer/File.php", 1991 | "CodeSniffer/Report.php", 1992 | "CodeSniffer/Reporting.php", 1993 | "CodeSniffer/Sniff.php", 1994 | "CodeSniffer/Tokens.php", 1995 | "CodeSniffer/Reports/", 1996 | "CodeSniffer/CommentParser/", 1997 | "CodeSniffer/Tokenizers/", 1998 | "CodeSniffer/DocGenerators/", 1999 | "CodeSniffer/Standards/AbstractPatternSniff.php", 2000 | "CodeSniffer/Standards/AbstractScopeSniff.php", 2001 | "CodeSniffer/Standards/AbstractVariableSniff.php", 2002 | "CodeSniffer/Standards/IncorrectPatternException.php", 2003 | "CodeSniffer/Standards/Generic/Sniffs/", 2004 | "CodeSniffer/Standards/MySource/Sniffs/", 2005 | "CodeSniffer/Standards/PEAR/Sniffs/", 2006 | "CodeSniffer/Standards/PSR1/Sniffs/", 2007 | "CodeSniffer/Standards/PSR2/Sniffs/", 2008 | "CodeSniffer/Standards/Squiz/Sniffs/", 2009 | "CodeSniffer/Standards/Zend/Sniffs/" 2010 | ] 2011 | }, 2012 | "notification-url": "https://packagist.org/downloads/", 2013 | "license": [ 2014 | "BSD-3-Clause" 2015 | ], 2016 | "authors": [ 2017 | { 2018 | "name": "Greg Sherwood", 2019 | "role": "lead" 2020 | } 2021 | ], 2022 | "description": "PHP_CodeSniffer tokenises PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", 2023 | "homepage": "http://www.squizlabs.com/php-codesniffer", 2024 | "keywords": [ 2025 | "phpcs", 2026 | "standards" 2027 | ], 2028 | "time": "2014-12-04T22:32:15+00:00" 2029 | }, 2030 | { 2031 | "name": "symfony/config", 2032 | "version": "v2.8.0", 2033 | "source": { 2034 | "type": "git", 2035 | "url": "https://github.com/symfony/config.git", 2036 | "reference": "cc75e0cf582c412e49ad4cd5f83bd0d8e6ff2b33" 2037 | }, 2038 | "dist": { 2039 | "type": "zip", 2040 | "url": "https://api.github.com/repos/symfony/config/zipball/cc75e0cf582c412e49ad4cd5f83bd0d8e6ff2b33", 2041 | "reference": "cc75e0cf582c412e49ad4cd5f83bd0d8e6ff2b33", 2042 | "shasum": "" 2043 | }, 2044 | "require": { 2045 | "php": ">=5.3.9", 2046 | "symfony/filesystem": "~2.3|~3.0.0" 2047 | }, 2048 | "type": "library", 2049 | "extra": { 2050 | "branch-alias": { 2051 | "dev-master": "2.8-dev" 2052 | } 2053 | }, 2054 | "autoload": { 2055 | "psr-4": { 2056 | "Symfony\\Component\\Config\\": "" 2057 | }, 2058 | "exclude-from-classmap": [ 2059 | "/Tests/" 2060 | ] 2061 | }, 2062 | "notification-url": "https://packagist.org/downloads/", 2063 | "license": [ 2064 | "MIT" 2065 | ], 2066 | "authors": [ 2067 | { 2068 | "name": "Fabien Potencier", 2069 | "email": "fabien@symfony.com" 2070 | }, 2071 | { 2072 | "name": "Symfony Community", 2073 | "homepage": "https://symfony.com/contributors" 2074 | } 2075 | ], 2076 | "description": "Symfony Config Component", 2077 | "homepage": "https://symfony.com", 2078 | "time": "2015-11-23T20:38:01+00:00" 2079 | }, 2080 | { 2081 | "name": "symfony/console", 2082 | "version": "v2.8.0", 2083 | "source": { 2084 | "type": "git", 2085 | "url": "https://github.com/symfony/console.git", 2086 | "reference": "d232bfc100dfd32b18ccbcab4bcc8f28697b7e41" 2087 | }, 2088 | "dist": { 2089 | "type": "zip", 2090 | "url": "https://api.github.com/repos/symfony/console/zipball/d232bfc100dfd32b18ccbcab4bcc8f28697b7e41", 2091 | "reference": "d232bfc100dfd32b18ccbcab4bcc8f28697b7e41", 2092 | "shasum": "" 2093 | }, 2094 | "require": { 2095 | "php": ">=5.3.9", 2096 | "symfony/polyfill-mbstring": "~1.0" 2097 | }, 2098 | "require-dev": { 2099 | "psr/log": "~1.0", 2100 | "symfony/event-dispatcher": "~2.1|~3.0.0", 2101 | "symfony/process": "~2.1|~3.0.0" 2102 | }, 2103 | "suggest": { 2104 | "psr/log": "For using the console logger", 2105 | "symfony/event-dispatcher": "", 2106 | "symfony/process": "" 2107 | }, 2108 | "type": "library", 2109 | "extra": { 2110 | "branch-alias": { 2111 | "dev-master": "2.8-dev" 2112 | } 2113 | }, 2114 | "autoload": { 2115 | "psr-4": { 2116 | "Symfony\\Component\\Console\\": "" 2117 | }, 2118 | "exclude-from-classmap": [ 2119 | "/Tests/" 2120 | ] 2121 | }, 2122 | "notification-url": "https://packagist.org/downloads/", 2123 | "license": [ 2124 | "MIT" 2125 | ], 2126 | "authors": [ 2127 | { 2128 | "name": "Fabien Potencier", 2129 | "email": "fabien@symfony.com" 2130 | }, 2131 | { 2132 | "name": "Symfony Community", 2133 | "homepage": "https://symfony.com/contributors" 2134 | } 2135 | ], 2136 | "description": "Symfony Console Component", 2137 | "homepage": "https://symfony.com", 2138 | "time": "2015-11-30T12:35:10+00:00" 2139 | }, 2140 | { 2141 | "name": "symfony/event-dispatcher", 2142 | "version": "v2.8.0", 2143 | "source": { 2144 | "type": "git", 2145 | "url": "https://github.com/symfony/event-dispatcher.git", 2146 | "reference": "a5eb815363c0388e83247e7e9853e5dbc14999cc" 2147 | }, 2148 | "dist": { 2149 | "type": "zip", 2150 | "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a5eb815363c0388e83247e7e9853e5dbc14999cc", 2151 | "reference": "a5eb815363c0388e83247e7e9853e5dbc14999cc", 2152 | "shasum": "" 2153 | }, 2154 | "require": { 2155 | "php": ">=5.3.9" 2156 | }, 2157 | "require-dev": { 2158 | "psr/log": "~1.0", 2159 | "symfony/config": "~2.0,>=2.0.5|~3.0.0", 2160 | "symfony/dependency-injection": "~2.6|~3.0.0", 2161 | "symfony/expression-language": "~2.6|~3.0.0", 2162 | "symfony/stopwatch": "~2.3|~3.0.0" 2163 | }, 2164 | "suggest": { 2165 | "symfony/dependency-injection": "", 2166 | "symfony/http-kernel": "" 2167 | }, 2168 | "type": "library", 2169 | "extra": { 2170 | "branch-alias": { 2171 | "dev-master": "2.8-dev" 2172 | } 2173 | }, 2174 | "autoload": { 2175 | "psr-4": { 2176 | "Symfony\\Component\\EventDispatcher\\": "" 2177 | }, 2178 | "exclude-from-classmap": [ 2179 | "/Tests/" 2180 | ] 2181 | }, 2182 | "notification-url": "https://packagist.org/downloads/", 2183 | "license": [ 2184 | "MIT" 2185 | ], 2186 | "authors": [ 2187 | { 2188 | "name": "Fabien Potencier", 2189 | "email": "fabien@symfony.com" 2190 | }, 2191 | { 2192 | "name": "Symfony Community", 2193 | "homepage": "https://symfony.com/contributors" 2194 | } 2195 | ], 2196 | "description": "Symfony EventDispatcher Component", 2197 | "homepage": "https://symfony.com", 2198 | "time": "2015-10-30T20:15:42+00:00" 2199 | }, 2200 | { 2201 | "name": "symfony/filesystem", 2202 | "version": "v2.8.0", 2203 | "source": { 2204 | "type": "git", 2205 | "url": "https://github.com/symfony/filesystem.git", 2206 | "reference": "3e661a0d521ac67496515fa6e6704bd61bcfff60" 2207 | }, 2208 | "dist": { 2209 | "type": "zip", 2210 | "url": "https://api.github.com/repos/symfony/filesystem/zipball/3e661a0d521ac67496515fa6e6704bd61bcfff60", 2211 | "reference": "3e661a0d521ac67496515fa6e6704bd61bcfff60", 2212 | "shasum": "" 2213 | }, 2214 | "require": { 2215 | "php": ">=5.3.9" 2216 | }, 2217 | "type": "library", 2218 | "extra": { 2219 | "branch-alias": { 2220 | "dev-master": "2.8-dev" 2221 | } 2222 | }, 2223 | "autoload": { 2224 | "psr-4": { 2225 | "Symfony\\Component\\Filesystem\\": "" 2226 | }, 2227 | "exclude-from-classmap": [ 2228 | "/Tests/" 2229 | ] 2230 | }, 2231 | "notification-url": "https://packagist.org/downloads/", 2232 | "license": [ 2233 | "MIT" 2234 | ], 2235 | "authors": [ 2236 | { 2237 | "name": "Fabien Potencier", 2238 | "email": "fabien@symfony.com" 2239 | }, 2240 | { 2241 | "name": "Symfony Community", 2242 | "homepage": "https://symfony.com/contributors" 2243 | } 2244 | ], 2245 | "description": "Symfony Filesystem Component", 2246 | "homepage": "https://symfony.com", 2247 | "time": "2015-11-23T10:19:46+00:00" 2248 | }, 2249 | { 2250 | "name": "symfony/finder", 2251 | "version": "v3.4.3", 2252 | "source": { 2253 | "type": "git", 2254 | "url": "https://github.com/symfony/finder.git", 2255 | "reference": "613e26310776f49a1773b6737c6bd554b8bc8c6f" 2256 | }, 2257 | "dist": { 2258 | "type": "zip", 2259 | "url": "https://api.github.com/repos/symfony/finder/zipball/613e26310776f49a1773b6737c6bd554b8bc8c6f", 2260 | "reference": "613e26310776f49a1773b6737c6bd554b8bc8c6f", 2261 | "shasum": "" 2262 | }, 2263 | "require": { 2264 | "php": "^5.5.9|>=7.0.8" 2265 | }, 2266 | "type": "library", 2267 | "extra": { 2268 | "branch-alias": { 2269 | "dev-master": "3.4-dev" 2270 | } 2271 | }, 2272 | "autoload": { 2273 | "psr-4": { 2274 | "Symfony\\Component\\Finder\\": "" 2275 | }, 2276 | "exclude-from-classmap": [ 2277 | "/Tests/" 2278 | ] 2279 | }, 2280 | "notification-url": "https://packagist.org/downloads/", 2281 | "license": [ 2282 | "MIT" 2283 | ], 2284 | "authors": [ 2285 | { 2286 | "name": "Fabien Potencier", 2287 | "email": "fabien@symfony.com" 2288 | }, 2289 | { 2290 | "name": "Symfony Community", 2291 | "homepage": "https://symfony.com/contributors" 2292 | } 2293 | ], 2294 | "description": "Symfony Finder Component", 2295 | "homepage": "https://symfony.com", 2296 | "time": "2018-01-03T07:37:34+00:00" 2297 | }, 2298 | { 2299 | "name": "symfony/polyfill-mbstring", 2300 | "version": "v1.0.0", 2301 | "source": { 2302 | "type": "git", 2303 | "url": "https://github.com/symfony/polyfill-mbstring.git", 2304 | "reference": "0b6a8940385311a24e060ec1fe35680e17c74497" 2305 | }, 2306 | "dist": { 2307 | "type": "zip", 2308 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0b6a8940385311a24e060ec1fe35680e17c74497", 2309 | "reference": "0b6a8940385311a24e060ec1fe35680e17c74497", 2310 | "shasum": "" 2311 | }, 2312 | "require": { 2313 | "php": ">=5.3.3" 2314 | }, 2315 | "type": "library", 2316 | "extra": { 2317 | "branch-alias": { 2318 | "dev-master": "1.0-dev" 2319 | } 2320 | }, 2321 | "autoload": { 2322 | "psr-4": { 2323 | "Symfony\\Polyfill\\Mbstring\\": "" 2324 | }, 2325 | "files": [ 2326 | "bootstrap.php" 2327 | ] 2328 | }, 2329 | "notification-url": "https://packagist.org/downloads/", 2330 | "license": [ 2331 | "MIT" 2332 | ], 2333 | "authors": [ 2334 | { 2335 | "name": "Nicolas Grekas", 2336 | "email": "p@tchwork.com" 2337 | }, 2338 | { 2339 | "name": "Symfony Community", 2340 | "homepage": "https://symfony.com/contributors" 2341 | } 2342 | ], 2343 | "description": "Symfony polyfill for the Mbstring extension", 2344 | "homepage": "https://symfony.com", 2345 | "keywords": [ 2346 | "compatibility", 2347 | "mbstring", 2348 | "polyfill", 2349 | "portable", 2350 | "shim" 2351 | ], 2352 | "time": "2015-11-04T20:28:58+00:00" 2353 | }, 2354 | { 2355 | "name": "symfony/process", 2356 | "version": "v3.4.3", 2357 | "source": { 2358 | "type": "git", 2359 | "url": "https://github.com/symfony/process.git", 2360 | "reference": "ff69f110c6b33fd33cd2089ba97d6112f44ef0ba" 2361 | }, 2362 | "dist": { 2363 | "type": "zip", 2364 | "url": "https://api.github.com/repos/symfony/process/zipball/ff69f110c6b33fd33cd2089ba97d6112f44ef0ba", 2365 | "reference": "ff69f110c6b33fd33cd2089ba97d6112f44ef0ba", 2366 | "shasum": "" 2367 | }, 2368 | "require": { 2369 | "php": "^5.5.9|>=7.0.8" 2370 | }, 2371 | "type": "library", 2372 | "extra": { 2373 | "branch-alias": { 2374 | "dev-master": "3.4-dev" 2375 | } 2376 | }, 2377 | "autoload": { 2378 | "psr-4": { 2379 | "Symfony\\Component\\Process\\": "" 2380 | }, 2381 | "exclude-from-classmap": [ 2382 | "/Tests/" 2383 | ] 2384 | }, 2385 | "notification-url": "https://packagist.org/downloads/", 2386 | "license": [ 2387 | "MIT" 2388 | ], 2389 | "authors": [ 2390 | { 2391 | "name": "Fabien Potencier", 2392 | "email": "fabien@symfony.com" 2393 | }, 2394 | { 2395 | "name": "Symfony Community", 2396 | "homepage": "https://symfony.com/contributors" 2397 | } 2398 | ], 2399 | "description": "Symfony Process Component", 2400 | "homepage": "https://symfony.com", 2401 | "time": "2018-01-03T07:37:34+00:00" 2402 | }, 2403 | { 2404 | "name": "symfony/stopwatch", 2405 | "version": "v2.8.0", 2406 | "source": { 2407 | "type": "git", 2408 | "url": "https://github.com/symfony/stopwatch.git", 2409 | "reference": "5f1e2ebd1044da542d2b9510527836e8be92b1cb" 2410 | }, 2411 | "dist": { 2412 | "type": "zip", 2413 | "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5f1e2ebd1044da542d2b9510527836e8be92b1cb", 2414 | "reference": "5f1e2ebd1044da542d2b9510527836e8be92b1cb", 2415 | "shasum": "" 2416 | }, 2417 | "require": { 2418 | "php": ">=5.3.9" 2419 | }, 2420 | "type": "library", 2421 | "extra": { 2422 | "branch-alias": { 2423 | "dev-master": "2.8-dev" 2424 | } 2425 | }, 2426 | "autoload": { 2427 | "psr-4": { 2428 | "Symfony\\Component\\Stopwatch\\": "" 2429 | }, 2430 | "exclude-from-classmap": [ 2431 | "/Tests/" 2432 | ] 2433 | }, 2434 | "notification-url": "https://packagist.org/downloads/", 2435 | "license": [ 2436 | "MIT" 2437 | ], 2438 | "authors": [ 2439 | { 2440 | "name": "Fabien Potencier", 2441 | "email": "fabien@symfony.com" 2442 | }, 2443 | { 2444 | "name": "Symfony Community", 2445 | "homepage": "https://symfony.com/contributors" 2446 | } 2447 | ], 2448 | "description": "Symfony Stopwatch Component", 2449 | "homepage": "https://symfony.com", 2450 | "time": "2015-10-30T20:15:42+00:00" 2451 | }, 2452 | { 2453 | "name": "symfony/yaml", 2454 | "version": "v3.0.0", 2455 | "source": { 2456 | "type": "git", 2457 | "url": "https://github.com/symfony/yaml.git", 2458 | "reference": "4113f97104ffdcb734e15c27fbe27a7e1a3ac3b0" 2459 | }, 2460 | "dist": { 2461 | "type": "zip", 2462 | "url": "https://api.github.com/repos/symfony/yaml/zipball/4113f97104ffdcb734e15c27fbe27a7e1a3ac3b0", 2463 | "reference": "4113f97104ffdcb734e15c27fbe27a7e1a3ac3b0", 2464 | "shasum": "" 2465 | }, 2466 | "require": { 2467 | "php": ">=5.5.9" 2468 | }, 2469 | "type": "library", 2470 | "extra": { 2471 | "branch-alias": { 2472 | "dev-master": "3.0-dev" 2473 | } 2474 | }, 2475 | "autoload": { 2476 | "psr-4": { 2477 | "Symfony\\Component\\Yaml\\": "" 2478 | }, 2479 | "exclude-from-classmap": [ 2480 | "/Tests/" 2481 | ] 2482 | }, 2483 | "notification-url": "https://packagist.org/downloads/", 2484 | "license": [ 2485 | "MIT" 2486 | ], 2487 | "authors": [ 2488 | { 2489 | "name": "Fabien Potencier", 2490 | "email": "fabien@symfony.com" 2491 | }, 2492 | { 2493 | "name": "Symfony Community", 2494 | "homepage": "https://symfony.com/contributors" 2495 | } 2496 | ], 2497 | "description": "Symfony Yaml Component", 2498 | "homepage": "https://symfony.com", 2499 | "time": "2015-11-30T12:36:17+00:00" 2500 | }, 2501 | { 2502 | "name": "vectorface/dunit", 2503 | "version": "v2.1.0", 2504 | "source": { 2505 | "type": "git", 2506 | "url": "https://github.com/Vectorface/dunit.git", 2507 | "reference": "3f04c7a8bef5ff100666e92db96e93f80a6640bf" 2508 | }, 2509 | "dist": { 2510 | "type": "zip", 2511 | "url": "https://api.github.com/repos/Vectorface/dunit/zipball/3f04c7a8bef5ff100666e92db96e93f80a6640bf", 2512 | "reference": "3f04c7a8bef5ff100666e92db96e93f80a6640bf", 2513 | "shasum": "" 2514 | }, 2515 | "require-dev": { 2516 | "phpunit/phpunit": "~4.3", 2517 | "symfony/console": "~2.5" 2518 | }, 2519 | "bin": [ 2520 | "bin/dunit" 2521 | ], 2522 | "type": "library", 2523 | "autoload": { 2524 | "psr-4": { 2525 | "Vectorface\\Dunit\\": "src" 2526 | } 2527 | }, 2528 | "notification-url": "https://packagist.org/downloads/", 2529 | "license": [ 2530 | "MIT" 2531 | ], 2532 | "authors": [ 2533 | { 2534 | "name": "Daniel Bruce", 2535 | "email": "dbruce@vectorface.com", 2536 | "role": "Developer" 2537 | }, 2538 | { 2539 | "name": "Cory Darby", 2540 | "email": "ckdarby@vectorface.com", 2541 | "role": "Developer" 2542 | } 2543 | ], 2544 | "description": "Test code against multiple versions of PHP with the help of docker", 2545 | "homepage": "https://github.com/Vectorface/dunit", 2546 | "keywords": [ 2547 | "docker", 2548 | "php", 2549 | "phpunit", 2550 | "testing" 2551 | ], 2552 | "time": "2015-03-31T19:30:02+00:00" 2553 | } 2554 | ], 2555 | "aliases": [], 2556 | "minimum-stability": "stable", 2557 | "stability-flags": [], 2558 | "prefer-stable": false, 2559 | "prefer-lowest": false, 2560 | "platform": { 2561 | "php": ">=5.6.0" 2562 | }, 2563 | "platform-dev": [] 2564 | } 2565 | --------------------------------------------------------------------------------