diff --git a/composer.lock b/composer.lock index d99c78c..48491ed 100644 --- a/composer.lock +++ b/composer.lock @@ -1,3063 +1,3063 @@ { - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "e4bf44b9498b87159a1ec70b7d6225bd", - "packages": [ - { - "name": "doctrine/annotations", - "version": "v1.2.7", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/f25c8aab83e0c3e976fd7d19875f198ccf2f7535", - "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535", - "shasum": "" - }, - "require": { - "doctrine/lexer": "1.*", - "php": ">=5.3.2" - }, - "require-dev": { - "doctrine/cache": "1.*", - "phpunit/phpunit": "4.*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\Common\\Annotations\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "time": "2015-08-31T12:32:49+00:00" - }, - { - "name": "doctrine/cache", - "version": "v1.6.2", - "source": { - "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/eb152c5100571c7a45470ff2a35095ab3f3b900b", - "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b", - "shasum": "" - }, - "require": { - "php": "~5.5|~7.0" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "require-dev": { - "phpunit/phpunit": "~4.8|~5.0", - "predis/predis": "~1.0", - "satooshi/php-coveralls": "~0.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Caching library offering an object-oriented API for many cache backends", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "cache", - "caching" - ], - "time": "2017-07-22T12:49:21+00:00" - }, - { - "name": "doctrine/collections", - "version": "v1.3.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/collections.git", - "reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/6c1e4eef75f310ea1b3e30945e9f06e652128b8a", - "reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\Common\\Collections\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Collections Abstraction library", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "array", - "collections", - "iterator" - ], - "time": "2015-04-14T22:21:58+00:00" - }, - { - "name": "doctrine/common", - "version": "v2.6.2", - "source": { - "type": "git", - "url": "https://github.com/doctrine/common.git", - "reference": "7bce00698899aa2c06fe7365c76e4d78ddb15fa3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/7bce00698899aa2c06fe7365c76e4d78ddb15fa3", - "reference": "7bce00698899aa2c06fe7365c76e4d78ddb15fa3", - "shasum": "" - }, - "require": { - "doctrine/annotations": "1.*", - "doctrine/cache": "1.*", - "doctrine/collections": "1.*", - "doctrine/inflector": "1.*", - "doctrine/lexer": "1.*", - "php": "~5.5|~7.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.8|~5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.7.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Common Library for Doctrine projects", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "annotations", - "collections", - "eventmanager", - "persistence", - "spl" - ], - "time": "2016-11-30T16:50:46+00:00" - }, - { - "name": "doctrine/dbal", - "version": "v2.5.13", - "source": { - "type": "git", - "url": "https://github.com/doctrine/dbal.git", - "reference": "729340d8d1eec8f01bff708e12e449a3415af873" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/729340d8d1eec8f01bff708e12e449a3415af873", - "reference": "729340d8d1eec8f01bff708e12e449a3415af873", - "shasum": "" - }, - "require": { - "doctrine/common": ">=2.4,<2.8-dev", - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "4.*", - "symfony/console": "2.*||^3.0" - }, - "suggest": { - "symfony/console": "For helpful console commands such as SQL execution and import of files." - }, - "bin": [ - "bin/doctrine-dbal" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.5.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\DBAL\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - } - ], - "description": "Database Abstraction Layer", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "database", - "dbal", - "persistence", - "queryobject" - ], - "time": "2017-07-22T20:44:48+00:00" - }, - { - "name": "doctrine/inflector", - "version": "v1.3.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/inflector.git", - "reference": "5527a48b7313d15261292c149e55e26eae771b0a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a", - "reference": "5527a48b7313d15261292c149e55e26eae771b0a", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "phpunit/phpunit": "^6.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Common String Manipulations with regard to casing and singular/plural rules.", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "inflection", - "pluralize", - "singularize", - "string" - ], - "time": "2018-01-09T20:05:19+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "1.0.5", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", - "shasum": "" - }, - "require": { - "php": ">=5.3,<8.0-DEV" - }, - "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", - "keywords": [ - "constructor", - "instantiate" - ], - "time": "2015-06-14T21:17:01+00:00" - }, - { - "name": "doctrine/lexer", - "version": "v1.0.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\Common\\Lexer\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "lexer", - "parser" - ], - "time": "2014-09-09T13:34:57+00:00" - }, - { - "name": "doctrine/orm", - "version": "v2.5.14", - "source": { - "type": "git", - "url": "https://github.com/doctrine/orm.git", - "reference": "810a7baf81462a5ddf10e8baa8cb94b6eec02754" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/810a7baf81462a5ddf10e8baa8cb94b6eec02754", - "reference": "810a7baf81462a5ddf10e8baa8cb94b6eec02754", - "shasum": "" - }, - "require": { - "doctrine/cache": "~1.4", - "doctrine/collections": "~1.2", - "doctrine/common": ">=2.5-dev,<2.9-dev", - "doctrine/dbal": ">=2.5-dev,<2.7-dev", - "doctrine/instantiator": "^1.0.1", - "ext-pdo": "*", - "php": ">=5.4", - "symfony/console": "~2.5|~3.0|~4.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0", - "symfony/yaml": "~2.3|~3.0|~4.0" - }, - "suggest": { - "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" - }, - "bin": [ - "bin/doctrine", - "bin/doctrine.php" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.6.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\ORM\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - } - ], - "description": "Object-Relational-Mapper for PHP", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "database", - "orm" - ], - "time": "2017-12-17T02:57:51+00:00" - }, - { - "name": "friendica/json-ld", - "version": "1.1.1", - "source": { - "type": "git", - "url": "https://git.friendi.ca/friendica/php-json-ld", - "reference": "ca3916d10d2ad9073b3b1eae383978dbe828e1e1" - }, - "require": { - "ext-json": "*", - "php": ">=5.4.0" - }, - "type": "library", - "autoload": { - "files": [ - "jsonld.php" - ] - }, - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Digital Bazaar, Inc.", - "email": "support@digitalbazaar.com", - "homepage": "http://digitalbazaar.com/" - }, - { - "name": "Friendica Team", - "homepage": "https://friendi.ca/" - } - ], - "description": "A JSON-LD Processor and API implementation in PHP.", - "homepage": "https://git.friendi.ca/friendica/php-json-ld", - "keywords": [ - "JSON", - "JSON-LD", - "Linked Data", - "RDF", - "Semantic Web", - "jsonld" - ], - "time": "2018-10-08T20:41:00+00:00" - }, - { - "name": "guzzlehttp/guzzle", - "version": "6.3.3", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "shasum": "" - }, - "require": { - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.4", - "php": ">=5.5" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", - "psr/log": "^1.0" - }, - "suggest": { - "psr/log": "Required for using the Log middleware" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.3-dev" - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2018-04-22T15:46:56+00:00" - }, - { - "name": "guzzlehttp/promises", - "version": "v1.3.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "shasum": "" - }, - "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "time": "2016-12-20T10:07:11+00:00" - }, - { - "name": "guzzlehttp/psr7", - "version": "1.5.2", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "9f83dded91781a01c63574e387eaa769be769115" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115", - "reference": "9f83dded91781a01c63574e387eaa769be769115", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0", - "ralouphie/getallheaders": "^2.0.5" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.5-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Tobias Schultze", - "homepage": "https://github.com/Tobion" - } - ], - "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": [ - "http", - "message", - "psr-7", - "request", - "response", - "stream", - "uri", - "url" - ], - "time": "2018-12-04T20:46:45+00:00" - }, - { - "name": "paragonie/random_compat", - "version": "v9.99.99", - "source": { - "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", - "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", - "shasum": "" - }, - "require": { - "php": "^7" - }, - "require-dev": { - "phpunit/phpunit": "4.*|5.*", - "vimeo/psalm": "^1" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." - }, - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", - "keywords": [ - "csprng", - "polyfill", - "pseudorandom", - "random" - ], - "time": "2018-07-02T15:55:56+00:00" - }, - { - "name": "phpseclib/phpseclib", - "version": "2.0.14", - "source": { - "type": "git", - "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "8ebfcadbf30524aeb75b2c446bc2519d5b321478" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/8ebfcadbf30524aeb75b2c446bc2519d5b321478", - "reference": "8ebfcadbf30524aeb75b2c446bc2519d5b321478", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phing/phing": "~2.7", - "phpunit/phpunit": "^4.8.35|^5.7|^6.0", - "sami/sami": "~2.0", - "squizlabs/php_codesniffer": "~2.0" - }, - "suggest": { - "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", - "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", - "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", - "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." - }, - "type": "library", - "autoload": { - "files": [ - "phpseclib/bootstrap.php" - ], - "psr-4": { - "phpseclib\\": "phpseclib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jim Wigginton", - "email": "terrafrost@php.net", - "role": "Lead Developer" - }, - { - "name": "Patrick Monnerat", - "email": "pm@datasphere.ch", - "role": "Developer" - }, - { - "name": "Andreas Fischer", - "email": "bantu@phpbb.com", - "role": "Developer" - }, - { - "name": "Hans-Jürgen Petrich", - "email": "petrich@tronic-media.com", - "role": "Developer" - }, - { - "name": "Graham Campbell", - "email": "graham@alt-three.com", - "role": "Developer" - } - ], - "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", - "homepage": "http://phpseclib.sourceforge.net", - "keywords": [ - "BigInteger", - "aes", - "asn.1", - "asn1", - "blowfish", - "crypto", - "cryptography", - "encryption", - "rsa", - "security", - "sftp", - "signature", - "signing", - "ssh", - "twofish", - "x.509", - "x509" - ], - "time": "2019-01-27T19:37:29+00:00" - }, - { - "name": "psr/container", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "time": "2017-02-14T16:28:37+00:00" - }, - { - "name": "psr/http-message", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "time": "2016-08-06T14:39:51+00:00" - }, - { - "name": "psr/log", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", - "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2018-11-20T15:27:04+00:00" - }, - { - "name": "ralouphie/getallheaders", - "version": "2.0.5", - "source": { - "type": "git", - "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa", - "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa", - "shasum": "" - }, - "require": { - "php": ">=5.3" - }, - "require-dev": { - "phpunit/phpunit": "~3.7.0", - "satooshi/php-coveralls": ">=1.0" - }, - "type": "library", - "autoload": { - "files": [ - "src/getallheaders.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ralph Khattar", - "email": "ralph.khattar@gmail.com" - } - ], - "description": "A polyfill for getallheaders.", - "time": "2016-02-11T07:05:27+00:00" - }, - { - "name": "symfony/console", - "version": "v4.2.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "1f0ad51dfde4da8a6070f06adc58b4e37cbb37a4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/1f0ad51dfde4da8a6070f06adc58b4e37cbb37a4", - "reference": "1f0ad51dfde4da8a6070f06adc58b4e37cbb37a4", - "shasum": "" - }, - "require": { - "php": "^7.1.3", - "symfony/contracts": "^1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/dependency-injection": "<3.4", - "symfony/process": "<3.3" - }, - "provide": { - "psr/log-implementation": "1.0" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.4|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/event-dispatcher": "~3.4|~4.0", - "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.4|~4.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.2-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Console Component", - "homepage": "https://symfony.com", - "time": "2019-01-25T14:35:16+00:00" - }, - { - "name": "symfony/contracts", - "version": "v1.0.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/contracts.git", - "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/contracts/zipball/1aa7ab2429c3d594dd70689604b5cf7421254cdf", - "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf", - "shasum": "" - }, - "require": { - "php": "^7.1.3" - }, - "require-dev": { - "psr/cache": "^1.0", - "psr/container": "^1.0" - }, - "suggest": { - "psr/cache": "When using the Cache contracts", - "psr/container": "When using the Service contracts", - "symfony/cache-contracts-implementation": "", - "symfony/service-contracts-implementation": "", - "symfony/translation-contracts-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\": "" - }, - "exclude-from-classmap": [ - "**/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A set of abstractions extracted out of the Symfony components", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "time": "2018-12-05T08:06:11+00:00" - }, - { - "name": "symfony/debug", - "version": "v4.2.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "cf9b2e33f757deb884ce474e06d2647c1c769b65" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/cf9b2e33f757deb884ce474e06d2647c1c769b65", - "reference": "cf9b2e33f757deb884ce474e06d2647c1c769b65", - "shasum": "" - }, - "require": { - "php": "^7.1.3", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/http-kernel": "<3.4" - }, - "require-dev": { - "symfony/http-kernel": "~3.4|~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.2-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Debug\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Debug Component", - "homepage": "https://symfony.com", - "time": "2019-01-25T14:35:16+00:00" - }, - { - "name": "symfony/dependency-injection", - "version": "v3.4.22", - "source": { - "type": "git", - "url": "https://github.com/symfony/dependency-injection.git", - "reference": "b514f5b765cf3e4a56e9d8ebacf14b117f7a0ee1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/b514f5b765cf3e4a56e9d8ebacf14b117f7a0ee1", - "reference": "b514f5b765cf3e4a56e9d8ebacf14b117f7a0ee1", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "psr/container": "^1.0" - }, - "conflict": { - "symfony/config": "<3.3.7", - "symfony/finder": "<3.3", - "symfony/proxy-manager-bridge": "<3.4", - "symfony/yaml": "<3.4" - }, - "provide": { - "psr/container-implementation": "1.0" - }, - "require-dev": { - "symfony/config": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/yaml": "~3.4|~4.0" - }, - "suggest": { - "symfony/config": "", - "symfony/expression-language": "For using expressions in service container configuration", - "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", - "symfony/yaml": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\DependencyInjection\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony DependencyInjection Component", - "homepage": "https://symfony.com", - "time": "2019-01-30T17:48:51+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v3.4.22", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "ed5be1663fa66623b3a7004d5d51a14c4045399b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ed5be1663fa66623b3a7004d5d51a14c4045399b", - "reference": "ed5be1663fa66623b3a7004d5d51a14c4045399b", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "conflict": { - "symfony/dependency-injection": "<3.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony EventDispatcher Component", - "homepage": "https://symfony.com", - "time": "2019-01-16T13:27:11+00:00" - }, - { - "name": "symfony/http-foundation", - "version": "v3.4.22", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "9a81d2330ea255ded06a69b4f7fb7804836e7a05" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9a81d2330ea255ded06a69b4f7fb7804836e7a05", - "reference": "9a81d2330ea255ded06a69b4f7fb7804836e7a05", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php70": "~1.6" - }, - "require-dev": { - "symfony/expression-language": "~2.8|~3.0|~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpFoundation\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony HttpFoundation Component", - "homepage": "https://symfony.com", - "time": "2019-01-27T09:04:14+00:00" - }, - { - "name": "symfony/http-kernel", - "version": "v3.4.22", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-kernel.git", - "reference": "dc6bf17684b7120f7bf74fae85c9155506041002" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/dc6bf17684b7120f7bf74fae85c9155506041002", - "reference": "dc6bf17684b7120f7bf74fae85c9155506041002", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "psr/log": "~1.0", - "symfony/debug": "^3.3.3|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~3.4.12|~4.0.12|^4.1.1", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/config": "<2.8", - "symfony/dependency-injection": "<3.4.10|<4.0.10,>=4", - "symfony/var-dumper": "<3.3", - "twig/twig": "<1.34|<2.4,>=2" - }, - "provide": { - "psr/log-implementation": "1.0" - }, - "require-dev": { - "psr/cache": "~1.0", - "symfony/browser-kit": "~2.8|~3.0|~4.0", - "symfony/class-loader": "~2.8|~3.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/console": "~2.8|~3.0|~4.0", - "symfony/css-selector": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "^3.4.10|^4.0.10", - "symfony/dom-crawler": "~2.8|~3.0|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/process": "~2.8|~3.0|~4.0", - "symfony/routing": "~3.4|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", - "symfony/templating": "~2.8|~3.0|~4.0", - "symfony/translation": "~2.8|~3.0|~4.0", - "symfony/var-dumper": "~3.3|~4.0" - }, - "suggest": { - "symfony/browser-kit": "", - "symfony/config": "", - "symfony/console": "", - "symfony/dependency-injection": "", - "symfony/finder": "", - "symfony/var-dumper": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpKernel\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony HttpKernel Component", - "homepage": "https://symfony.com", - "time": "2019-02-03T12:22:50+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.10.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", - "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - }, - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "time": "2018-08-06T14:22:27+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.10.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "c79c051f5b3a46be09205c73b80b346e4153e494" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494", - "reference": "c79c051f5b3a46be09205c73b80b346e4153e494", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "time": "2018-09-21T13:07:52+00:00" - }, - { - "name": "symfony/polyfill-php70", - "version": "v1.10.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "6b88000cdd431cd2e940caa2cb569201f3f84224" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/6b88000cdd431cd2e940caa2cb569201f3f84224", - "reference": "6b88000cdd431cd2e940caa2cb569201f3f84224", - "shasum": "" - }, - "require": { - "paragonie/random_compat": "~1.0|~2.0|~9.99", - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php70\\": "" - }, - "files": [ - "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "time": "2018-09-21T06:26:08+00:00" - }, - { - "name": "symfony/psr-http-message-bridge", - "version": "v1.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "53c15a6a7918e6c2ab16ae370ea607fb40cab196" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/53c15a6a7918e6c2ab16ae370ea607fb40cab196", - "reference": "53c15a6a7918e6c2ab16ae370ea607fb40cab196", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0", - "psr/http-message": "^1.0", - "symfony/http-foundation": "^2.3.42 || ^3.4 || ^4.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "^3.4 || 4.0" - }, - "suggest": { - "psr/http-factory-implementation": "To use the PSR-17 factory", - "psr/http-message-implementation": "To use the HttpFoundation factory", - "zendframework/zend-diactoros": "To use the Zend Diactoros factory" - }, - "type": "symfony-bridge", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Bridge\\PsrHttpMessage\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "PSR HTTP message bridge", - "homepage": "http://symfony.com", - "keywords": [ - "http", - "http-message", - "psr-7" - ], - "time": "2018-08-30T16:28:28+00:00" - }, - { - "name": "zendframework/zend-diactoros", - "version": "1.4.1", - "source": { - "type": "git", - "url": "https://github.com/zendframework/zend-diactoros.git", - "reference": "424a840dc3bedcdeea510b42e056c77c2d6c4bef" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/424a840dc3bedcdeea510b42e056c77c2d6c4bef", - "reference": "424a840dc3bedcdeea510b42e056c77c2d6c4bef", - "shasum": "" - }, - "require": { - "php": "^5.4 || ^7.0", - "psr/http-message": "~1.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "ext-dom": "*", - "ext-libxml": "*", - "phpunit/phpunit": "^4.6 || ^5.5", - "zendframework/zend-coding-standard": "~1.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev", - "dev-develop": "1.5-dev" - } - }, - "autoload": { - "psr-4": { - "Zend\\Diactoros\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "description": "PSR HTTP Message implementations", - "homepage": "https://github.com/zendframework/zend-diactoros", - "keywords": [ - "http", - "psr", - "psr-7" - ], - "time": "2017-08-17T21:21:00+00:00" + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "e4bf44b9498b87159a1ec70b7d6225bd", + "packages": [ + { + "name": "doctrine/annotations", + "version": "v1.2.7", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/f25c8aab83e0c3e976fd7d19875f198ccf2f7535", + "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "php": ">=5.3.2" + }, + "require-dev": { + "doctrine/cache": "1.*", + "phpunit/phpunit": "4.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" } - ], - "packages-dev": [ - { - "name": "phpdocumentor/reflection-common", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "shasum": "" - }, - "require": { - "php": ">=5.5" - }, - "require-dev": { - "phpunit/phpunit": "^4.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "time": "2017-09-11T18:02:19+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "4.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08", - "shasum": "" - }, - "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", - "webmozart/assert": "^1.0" - }, - "require-dev": { - "doctrine/instantiator": "~1.0.5", - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^6.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-11-30T07:14:17+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "0.4.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", - "shasum": "" - }, - "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "time": "2017-07-14T14:27:02+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "1.8.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", - "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0|^3.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" - }, - "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8.x-dev" - } - }, - "autoload": { - "psr-0": { - "Prophecy\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "time": "2018-08-05T17:53:17+00:00" - }, - { - "name": "phpunit/dbunit", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/dbunit.git", - "reference": "5c35d74549c21ba55d0ea74ba89d191a51f8cf25" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/dbunit/zipball/5c35d74549c21ba55d0ea74ba89d191a51f8cf25", - "reference": "5c35d74549c21ba55d0ea74ba89d191a51f8cf25", - "shasum": "" - }, - "require": { - "ext-pdo": "*", - "ext-simplexml": "*", - "php": "^5.4 || ^7.0", - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0", - "symfony/yaml": "^2.1 || ^3.0" - }, - "bin": [ - "dbunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "DbUnit port for PHP/PHPUnit to support database interaction testing.", - "homepage": "https://github.com/sebastianbergmann/dbunit/", - "keywords": [ - "database", - "testing", - "xunit" - ], - "abandoned": true, - "time": "2016-12-02T14:39:14+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "2.2.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0" - }, - "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" - }, - "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.2.1", - "ext-xmlwriter": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "time": "2015-10-06T15:47:00+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "1.4.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "time": "2017-11-27T13:52:08+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2015-06-21T13:50:34+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "1.0.9", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2017-02-26T11:10:40+00:00" - }, - { - "name": "phpunit/php-token-stream", - "version": "1.4.12", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", - "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2017-12-04T08:55:13+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "4.8.36", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "46023de9a91eec7dfb06cc56cb4e260017298517" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517", - "reference": "46023de9a91eec7dfb06cc56cb4e260017298517", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "~2.1", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.2.2", - "sebastian/diff": "~1.2", - "sebastian/environment": "~1.3", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/version": "~1.0", - "symfony/yaml": "~2.1|~3.0" - }, - "suggest": { - "phpunit/php-invoker": "~1.1" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.8.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2017-06-21T08:07:12+00:00" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "2.3.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2", - "sebastian/exporter": "~1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2015-10-02T06:51:40+00:00" - }, - { - "name": "sebastian/comparator", - "version": "1.2.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "time": "2017-01-29T09:50:25+00:00" - }, - { - "name": "sebastian/diff", - "version": "1.4.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff" - ], - "time": "2017-05-22T07:24:03+00:00" - }, - { - "name": "sebastian/environment", - "version": "1.3.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8 || ^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "time": "2016-08-18T05:49:44+00:00" - }, - { - "name": "sebastian/exporter", - "version": "1.2.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "time": "2016-06-17T09:04:28+00:00" - }, - { - "name": "sebastian/global-state", - "version": "1.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "time": "2015-10-12T03:26:01+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "1.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-10-03T07:41:43+00:00" - }, - { - "name": "sebastian/version", - "version": "1.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "shasum": "" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21T13:59:46+00:00" - }, - { - "name": "symfony/yaml", - "version": "v3.4.22", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "ba11776e9e6c15ad5759a07bffb15899bac75c2d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/ba11776e9e6c15ad5759a07bffb15899bac75c2d", - "reference": "ba11776e9e6c15ad5759a07bffb15899bac75c2d", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/console": "<3.4" - }, - "require-dev": { - "symfony/console": "~3.4|~4.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2019-01-16T10:59:17+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", - "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0", - "symfony/polyfill-ctype": "^1.8" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "time": "2018-12-25T11:19:39+00:00" + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Annotations\\": "lib/" } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "ext-json": "*" + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "time": "2015-08-31T12:32:49+00:00" }, - "platform-dev": { - "ext-pdo": "*" + { + "name": "doctrine/cache", + "version": "v1.6.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/eb152c5100571c7a45470ff2a35095ab3f3b900b", + "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b", + "shasum": "" + }, + "require": { + "php": "~5.5|~7.0" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "phpunit/phpunit": "~4.8|~5.0", + "predis/predis": "~1.0", + "satooshi/php-coveralls": "~0.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Caching library offering an object-oriented API for many cache backends", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "cache", + "caching" + ], + "time": "2017-07-22T12:49:21+00:00" + }, + { + "name": "doctrine/collections", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/6c1e4eef75f310ea1b3e30945e9f06e652128b8a", + "reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Collections\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Collections Abstraction library", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "array", + "collections", + "iterator" + ], + "time": "2015-04-14T22:21:58+00:00" + }, + { + "name": "doctrine/common", + "version": "v2.6.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/common.git", + "reference": "7bce00698899aa2c06fe7365c76e4d78ddb15fa3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/common/zipball/7bce00698899aa2c06fe7365c76e4d78ddb15fa3", + "reference": "7bce00698899aa2c06fe7365c76e4d78ddb15fa3", + "shasum": "" + }, + "require": { + "doctrine/annotations": "1.*", + "doctrine/cache": "1.*", + "doctrine/collections": "1.*", + "doctrine/inflector": "1.*", + "doctrine/lexer": "1.*", + "php": "~5.5|~7.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.8|~5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Common Library for Doctrine projects", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "collections", + "eventmanager", + "persistence", + "spl" + ], + "time": "2016-11-30T16:50:46+00:00" + }, + { + "name": "doctrine/dbal", + "version": "v2.5.13", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "729340d8d1eec8f01bff708e12e449a3415af873" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/729340d8d1eec8f01bff708e12e449a3415af873", + "reference": "729340d8d1eec8f01bff708e12e449a3415af873", + "shasum": "" + }, + "require": { + "doctrine/common": ">=2.4,<2.8-dev", + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "4.*", + "symfony/console": "2.*||^3.0" + }, + "suggest": { + "symfony/console": "For helpful console commands such as SQL execution and import of files." + }, + "bin": [ + "bin/doctrine-dbal" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\DBAL\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Database Abstraction Layer", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database", + "dbal", + "persistence", + "queryobject" + ], + "time": "2017-07-22T20:44:48+00:00" + }, + { + "name": "doctrine/inflector", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string" + ], + "time": "2018-01-09T20:05:19+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2015-06-14T21:17:01+00:00" + }, + { + "name": "doctrine/lexer", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Lexer\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "lexer", + "parser" + ], + "time": "2014-09-09T13:34:57+00:00" + }, + { + "name": "doctrine/orm", + "version": "v2.5.14", + "source": { + "type": "git", + "url": "https://github.com/doctrine/orm.git", + "reference": "810a7baf81462a5ddf10e8baa8cb94b6eec02754" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/orm/zipball/810a7baf81462a5ddf10e8baa8cb94b6eec02754", + "reference": "810a7baf81462a5ddf10e8baa8cb94b6eec02754", + "shasum": "" + }, + "require": { + "doctrine/cache": "~1.4", + "doctrine/collections": "~1.2", + "doctrine/common": ">=2.5-dev,<2.9-dev", + "doctrine/dbal": ">=2.5-dev,<2.7-dev", + "doctrine/instantiator": "^1.0.1", + "ext-pdo": "*", + "php": ">=5.4", + "symfony/console": "~2.5|~3.0|~4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0", + "symfony/yaml": "~2.3|~3.0|~4.0" + }, + "suggest": { + "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" + }, + "bin": [ + "bin/doctrine", + "bin/doctrine.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\ORM\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Object-Relational-Mapper for PHP", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database", + "orm" + ], + "time": "2017-12-17T02:57:51+00:00" + }, + { + "name": "friendica/json-ld", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://git.friendi.ca/friendica/php-json-ld", + "reference": "ca3916d10d2ad9073b3b1eae383978dbe828e1e1" + }, + "require": { + "ext-json": "*", + "php": ">=5.4.0" + }, + "type": "library", + "autoload": { + "files": [ + "jsonld.php" + ] + }, + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Digital Bazaar, Inc.", + "email": "support@digitalbazaar.com", + "homepage": "http://digitalbazaar.com/" + }, + { + "name": "Friendica Team", + "homepage": "https://friendi.ca/" + } + ], + "description": "A JSON-LD Processor and API implementation in PHP.", + "homepage": "https://git.friendi.ca/friendica/php-json-ld", + "keywords": [ + "JSON", + "JSON-LD", + "Linked Data", + "RDF", + "Semantic Web", + "jsonld" + ], + "time": "2018-10-08T20:41:00+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "6.3.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.3-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2018-04-22T15:46:56+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-12-20T10:07:11+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.5.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "9f83dded91781a01c63574e387eaa769be769115" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115", + "reference": "9f83dded91781a01c63574e387eaa769be769115", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2018-12-04T20:46:45+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v9.99.99", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "shasum": "" + }, + "require": { + "php": "^7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "time": "2018-07-02T15:55:56+00:00" + }, + { + "name": "phpseclib/phpseclib", + "version": "2.0.14", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "8ebfcadbf30524aeb75b2c446bc2519d5b321478" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/8ebfcadbf30524aeb75b2c446bc2519d5b321478", + "reference": "8ebfcadbf30524aeb75b2c446bc2519d5b321478", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phing/phing": "~2.7", + "phpunit/phpunit": "^4.8.35|^5.7|^6.0", + "sami/sami": "~2.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "suggest": { + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." + }, + "type": "library", + "autoload": { + "files": [ + "phpseclib/bootstrap.php" + ], + "psr-4": { + "phpseclib\\": "phpseclib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "time": "2019-01-27T19:37:29+00:00" + }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "psr/log", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2018-11-20T15:27:04+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "2.0.5", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa", + "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "~3.7.0", + "satooshi/php-coveralls": ">=1.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "time": "2016-02-11T07:05:27+00:00" + }, + { + "name": "symfony/console", + "version": "v4.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "1f0ad51dfde4da8a6070f06adc58b4e37cbb37a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/1f0ad51dfde4da8a6070f06adc58b4e37cbb37a4", + "reference": "1f0ad51dfde4da8a6070f06adc58b4e37cbb37a4", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/contracts": "^1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2019-01-25T14:35:16+00:00" + }, + { + "name": "symfony/contracts", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/contracts.git", + "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/contracts/zipball/1aa7ab2429c3d594dd70689604b5cf7421254cdf", + "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "psr/cache": "^1.0", + "psr/container": "^1.0" + }, + "suggest": { + "psr/cache": "When using the Cache contracts", + "psr/container": "When using the Service contracts", + "symfony/cache-contracts-implementation": "", + "symfony/service-contracts-implementation": "", + "symfony/translation-contracts-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\": "" + }, + "exclude-from-classmap": [ + "**/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A set of abstractions extracted out of the Symfony components", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2018-12-05T08:06:11+00:00" + }, + { + "name": "symfony/debug", + "version": "v4.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "cf9b2e33f757deb884ce474e06d2647c1c769b65" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/cf9b2e33f757deb884ce474e06d2647c1c769b65", + "reference": "cf9b2e33f757deb884ce474e06d2647c1c769b65", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": "<3.4" + }, + "require-dev": { + "symfony/http-kernel": "~3.4|~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2019-01-25T14:35:16+00:00" + }, + { + "name": "symfony/dependency-injection", + "version": "v3.4.22", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "b514f5b765cf3e4a56e9d8ebacf14b117f7a0ee1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/b514f5b765cf3e4a56e9d8ebacf14b117f7a0ee1", + "reference": "b514f5b765cf3e4a56e9d8ebacf14b117f7a0ee1", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "psr/container": "^1.0" + }, + "conflict": { + "symfony/config": "<3.3.7", + "symfony/finder": "<3.3", + "symfony/proxy-manager-bridge": "<3.4", + "symfony/yaml": "<3.4" + }, + "provide": { + "psr/container-implementation": "1.0" + }, + "require-dev": { + "symfony/config": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DependencyInjection Component", + "homepage": "https://symfony.com", + "time": "2019-01-30T17:48:51+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v3.4.22", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "ed5be1663fa66623b3a7004d5d51a14c4045399b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ed5be1663fa66623b3a7004d5d51a14c4045399b", + "reference": "ed5be1663fa66623b3a7004d5d51a14c4045399b", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "conflict": { + "symfony/dependency-injection": "<3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2019-01-16T13:27:11+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v3.4.22", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "9a81d2330ea255ded06a69b4f7fb7804836e7a05" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9a81d2330ea255ded06a69b4f7fb7804836e7a05", + "reference": "9a81d2330ea255ded06a69b4f7fb7804836e7a05", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php70": "~1.6" + }, + "require-dev": { + "symfony/expression-language": "~2.8|~3.0|~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "https://symfony.com", + "time": "2019-01-27T09:04:14+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v3.4.22", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "dc6bf17684b7120f7bf74fae85c9155506041002" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/dc6bf17684b7120f7bf74fae85c9155506041002", + "reference": "dc6bf17684b7120f7bf74fae85c9155506041002", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "psr/log": "~1.0", + "symfony/debug": "^3.3.3|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~3.4.12|~4.0.12|^4.1.1", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/config": "<2.8", + "symfony/dependency-injection": "<3.4.10|<4.0.10,>=4", + "symfony/var-dumper": "<3.3", + "twig/twig": "<1.34|<2.4,>=2" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/cache": "~1.0", + "symfony/browser-kit": "~2.8|~3.0|~4.0", + "symfony/class-loader": "~2.8|~3.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/console": "~2.8|~3.0|~4.0", + "symfony/css-selector": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "^3.4.10|^4.0.10", + "symfony/dom-crawler": "~2.8|~3.0|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/process": "~2.8|~3.0|~4.0", + "symfony/routing": "~3.4|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0", + "symfony/templating": "~2.8|~3.0|~4.0", + "symfony/translation": "~2.8|~3.0|~4.0", + "symfony/var-dumper": "~3.3|~4.0" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "", + "symfony/finder": "", + "symfony/var-dumper": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpKernel Component", + "homepage": "https://symfony.com", + "time": "2019-02-03T12:22:50+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.10.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", + "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2018-08-06T14:22:27+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.10.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "c79c051f5b3a46be09205c73b80b346e4153e494" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494", + "reference": "c79c051f5b3a46be09205c73b80b346e4153e494", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2018-09-21T13:07:52+00:00" + }, + { + "name": "symfony/polyfill-php70", + "version": "v1.10.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php70.git", + "reference": "6b88000cdd431cd2e940caa2cb569201f3f84224" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/6b88000cdd431cd2e940caa2cb569201f3f84224", + "reference": "6b88000cdd431cd2e940caa2cb569201f3f84224", + "shasum": "" + }, + "require": { + "paragonie/random_compat": "~1.0|~2.0|~9.99", + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php70\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2018-09-21T06:26:08+00:00" + }, + { + "name": "symfony/psr-http-message-bridge", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/psr-http-message-bridge.git", + "reference": "53c15a6a7918e6c2ab16ae370ea607fb40cab196" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/53c15a6a7918e6c2ab16ae370ea607fb40cab196", + "reference": "53c15a6a7918e6c2ab16ae370ea607fb40cab196", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0", + "psr/http-message": "^1.0", + "symfony/http-foundation": "^2.3.42 || ^3.4 || ^4.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^3.4 || 4.0" + }, + "suggest": { + "psr/http-factory-implementation": "To use the PSR-17 factory", + "psr/http-message-implementation": "To use the HttpFoundation factory", + "zendframework/zend-diactoros": "To use the Zend Diactoros factory" + }, + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bridge\\PsrHttpMessage\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "PSR HTTP message bridge", + "homepage": "http://symfony.com", + "keywords": [ + "http", + "http-message", + "psr-7" + ], + "time": "2018-08-30T16:28:28+00:00" + }, + { + "name": "zendframework/zend-diactoros", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-diactoros.git", + "reference": "424a840dc3bedcdeea510b42e056c77c2d6c4bef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/424a840dc3bedcdeea510b42e056c77c2d6c4bef", + "reference": "424a840dc3bedcdeea510b42e056c77c2d6c4bef", + "shasum": "" + }, + "require": { + "php": "^5.4 || ^7.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "ext-dom": "*", + "ext-libxml": "*", + "phpunit/phpunit": "^4.6 || ^5.5", + "zendframework/zend-coding-standard": "~1.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev", + "dev-develop": "1.5-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Diactoros\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "description": "PSR HTTP Message implementations", + "homepage": "https://github.com/zendframework/zend-diactoros", + "keywords": [ + "http", + "psr", + "psr-7" + ], + "time": "2017-08-17T21:21:00+00:00" } + ], + "packages-dev": [ + { + "name": "phpdocumentor/reflection-common", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2017-09-11T18:02:19+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "4.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08", + "shasum": "" + }, + "require": { + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "doctrine/instantiator": "~1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2017-11-30T07:14:17+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.4.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "time": "2017-07-14T14:27:02+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "1.8.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2018-08-05T17:53:17+00:00" + }, + { + "name": "phpunit/dbunit", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/dbunit.git", + "reference": "5c35d74549c21ba55d0ea74ba89d191a51f8cf25" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/dbunit/zipball/5c35d74549c21ba55d0ea74ba89d191a51f8cf25", + "reference": "5c35d74549c21ba55d0ea74ba89d191a51f8cf25", + "shasum": "" + }, + "require": { + "ext-pdo": "*", + "ext-simplexml": "*", + "php": "^5.4 || ^7.0", + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0", + "symfony/yaml": "^2.1 || ^3.0" + }, + "bin": [ + "dbunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "DbUnit port for PHP/PHPUnit to support database interaction testing.", + "homepage": "https://github.com/sebastianbergmann/dbunit/", + "keywords": [ + "database", + "testing", + "xunit" + ], + "abandoned": true, + "time": "2016-12-02T14:39:14+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "2.2.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.3", + "sebastian/environment": "^1.3.2", + "sebastian/version": "~1.0" + }, + "require-dev": { + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~4" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.2.1", + "ext-xmlwriter": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2015-10-06T15:47:00+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2017-11-27T13:52:08+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21T13:50:34+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2017-02-26T11:10:40+00:00" + }, + { + "name": "phpunit/php-token-stream", + "version": "1.4.12", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2017-12-04T08:55:13+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "4.8.36", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "46023de9a91eec7dfb06cc56cb4e260017298517" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517", + "reference": "46023de9a91eec7dfb06cc56cb4e260017298517", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "~2.1", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "~2.3", + "sebastian/comparator": "~1.2.2", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.3", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/version": "~1.0", + "symfony/yaml": "~2.1|~3.0" + }, + "suggest": { + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.8.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2017-06-21T08:07:12+00:00" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "2.3.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": ">=5.3.3", + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2015-10-02T06:51:40+00:00" + }, + { + "name": "sebastian/comparator", + "version": "1.2.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2 || ~2.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2017-01-29T09:50:25+00:00" + }, + { + "name": "sebastian/diff", + "version": "1.4.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2017-05-22T07:24:03+00:00" + }, + { + "name": "sebastian/environment", + "version": "1.3.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2016-08-18T05:49:44+00:00" + }, + { + "name": "sebastian/exporter", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2016-06-17T09:04:28+00:00" + }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12T03:26:01+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2016-10-03T07:41:43+00:00" + }, + { + "name": "sebastian/version", + "version": "1.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2015-06-21T13:59:46+00:00" + }, + { + "name": "symfony/yaml", + "version": "v3.4.22", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "ba11776e9e6c15ad5759a07bffb15899bac75c2d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/ba11776e9e6c15ad5759a07bffb15899bac75c2d", + "reference": "ba11776e9e6c15ad5759a07bffb15899bac75c2d", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/console": "<3.4" + }, + "require-dev": { + "symfony/console": "~3.4|~4.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2019-01-16T10:59:17+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", + "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2018-12-25T11:19:39+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "ext-json": "*" + }, + "platform-dev": { + "ext-pdo": "*" + } } diff --git a/src/Activities/AcceptHandler.php b/src/Activities/AcceptHandler.php index aff1189..910e3f3 100644 --- a/src/Activities/AcceptHandler.php +++ b/src/Activities/AcceptHandler.php @@ -1,4 +1,5 @@ 'handleInbox', - OutboxActivityEvent::NAME => 'handleOutbox', - ); - } public function __construct( ObjectsService $objectsService, CollectionsService $collectionsService ) @@ -32,6 +25,14 @@ class AcceptHandler implements EventSubscriberInterface $this->collectionsService = $collectionsService; } + public static function getSubscribedEvents() + { + return array( + InboxActivityEvent::NAME => 'handleInbox', + OutboxActivityEvent::NAME => 'handleOutbox', + ); + } + public function handleInbox( InboxActivityEvent $event ) { $activity = $event->getActivity(); @@ -54,17 +55,17 @@ class AcceptHandler implements EventSubscriberInterface // or there isn't, in which case this is an ordinary Accept // sent by a client and the Follow is in the database $follow = $request->attributes->get( 'follow' ); - if ( ! $follow ) { + if ( !$follow ) { $followId = $activity['object']; if ( is_array( $followId ) && array_key_exists( 'id', $followId ) ) { $followId = $followId['id']; } - if ( ! is_string( $followId ) ) { + if ( !is_string( $followId ) ) { return; } $follow = $this->objectsService->dereference( $followId )->asArray( -1 ); } - if ( ! $follow || ! array_key_exists( 'object', $follow ) ) { + if ( !$follow || !array_key_exists( 'object', $follow ) ) { return; } $followObjectId = $follow['object']; diff --git a/src/Activities/ActivityEvent.php b/src/Activities/ActivityEvent.php index 603d240..abbe589 100644 --- a/src/Activities/ActivityEvent.php +++ b/src/Activities/ActivityEvent.php @@ -1,4 +1,5 @@ activity = $activity; $this->actor = $actor; diff --git a/src/Activities/CreateHandler.php b/src/Activities/CreateHandler.php index 3fbf72c..9ea1a1c 100644 --- a/src/Activities/CreateHandler.php +++ b/src/Activities/CreateHandler.php @@ -1,4 +1,5 @@ 'handleInbox', - OutboxActivityEvent::NAME => 'handleOutbox', - ); - } - public function __construct( ObjectsService $objectsService, IdProvider $idProvider, CollectionsService $collectionsService ) @@ -39,6 +32,15 @@ class CreateHandler implements EventSubscriberInterface $this->idProvider = $idProvider; $this->collectionsService = $collectionsService; } + + public static function getSubscribedEvents() + { + return array( + InboxActivityEvent::NAME => 'handleInbox', + OutboxActivityEvent::NAME => 'handleOutbox', + ); + } + public function handleInbox( InboxActivityEvent $event ) { $activity = $event->getActivity(); @@ -61,7 +63,7 @@ class CreateHandler implements EventSubscriberInterface return; } $object = $activity['object']; - if ( ! array_key_exists( 'id', $object ) ) { + if ( !array_key_exists( 'id', $object ) ) { $object['id'] = $this->idProvider->getId( $event->getRequest(), strtolower( $object['type'] ) @@ -94,31 +96,31 @@ class CreateHandler implements EventSubscriberInterface private function copyFields( array $fields, array $sourceObj, array $targetObj ) { - foreach( $fields as $field ) { - if ( ! array_key_exists( $field, $sourceObj ) ) { + foreach ( $fields as $field ) { + if ( !array_key_exists( $field, $sourceObj ) ) { continue; } if ( array_key_exists( $field, $targetObj ) && - $sourceObj[$field] === $targetObj[$field] ) { + $sourceObj[$field] === $targetObj[$field] ) { continue; - } else if ( ! array_key_exists( $field, $targetObj ) ) { + } else if ( !array_key_exists( $field, $targetObj ) ) { $targetObj[$field] = $sourceObj[$field]; } else if ( is_array( $sourceObj[$field] ) && - is_array( $targetObj[$field] ) ) { + is_array( $targetObj[$field] ) ) { $targetObj[$field] = array_unique( array_merge( $sourceObj[$field], $targetObj[$field] ) ); } else if ( is_array( $sourceObj[$field] ) && - ! is_array( $targetObj[$field] ) ) { + !is_array( $targetObj[$field] ) ) { $targetObj[$field] = array( $targetObj[$field] ); $targetObj[$field] = array_unique( array_merge( $sourceObj[$field], $targetObj[$field] ) ); - } else if ( ! is_array( $sourceObj[$field] ) && - is_array( $targetObj[$field] ) ) { + } else if ( !is_array( $sourceObj[$field] ) && + is_array( $targetObj[$field] ) ) { $targetObj[$field][] = $sourceObj[$field]; - } else if ( ! is_array( $sourceObj[$field] ) && - ! is_array( $targetObj[$field] ) ) { + } else if ( !is_array( $sourceObj[$field] ) && + !is_array( $targetObj[$field] ) ) { $targetObj[$field] = array( $targetObj[$field] ); $targetObj[$field][] = $sourceObj[$field]; } diff --git a/src/Activities/DeleteHandler.php b/src/Activities/DeleteHandler.php index 6395373..6a72890 100644 --- a/src/Activities/DeleteHandler.php +++ b/src/Activities/DeleteHandler.php @@ -1,4 +1,5 @@ dateTimeProvider = $dateTimeProvider; + $this->objectsService = $objectsService; + } + public static function getSubscribedEvents() { return array( @@ -29,13 +37,6 @@ class DeleteHandler implements EventSubscriberInterface ); } - public function __construct( DateTimeProvider $dateTimeProvider, - ObjectsService $objectsService ) - { - $this->dateTimeProvider = $dateTimeProvider; - $this->objectsService = $objectsService; - } - public function handleDelete( ActivityEvent $event ) { $activity = $event->getActivity(); @@ -43,14 +44,14 @@ class DeleteHandler implements EventSubscriberInterface return; } $objectId = $activity['object']; - if ( ! is_string( $objectId ) ) { + if ( !is_string( $objectId ) ) { if ( is_array( $objectId ) && array_key_exists( 'id', $objectId ) ) { $objectId = $objectId['id']; } else { throw new BadRequestHttpException( 'Object must have an "id" field' ); } } - if ( ! $this->authorized( $event->getRequest(), $objectId ) ) { + if ( !$this->authorized( $event->getRequest(), $objectId ) ) { throw new UnauthorizedHttpException( 'Signature realm="ActivityPub",headers="(request-target) host date"' ); @@ -68,27 +69,27 @@ class DeleteHandler implements EventSubscriberInterface $this->objectsService->replace( $objectId, $tombstone ); } + public function authorized( Request $request, $objectId ) + { + if ( !$request->attributes->has( 'actor' ) ) { + return false; + } + $requestActor = $request->attributes->get( 'actor' ); + $object = $this->objectsService->dereference( $objectId ); + if ( !$object || !$object->hasField( 'attributedTo' ) ) { + return false; + } + $attributedActorId = $object['attributedTo']; + if ( !is_string( $attributedActorId ) ) { + $attributedActorId = $attributedActorId['id']; + } + return $requestActor['id'] === $attributedActorId; + } + private function getNowTimestamp() { return $this->dateTimeProvider->getTime( 'activities.delete' ) ->format( DateTime::ISO8601 ); } - - public function authorized( Request $request, $objectId ) - { - if ( ! $request->attributes->has( 'actor' ) ) { - return false; - } - $requestActor = $request->attributes->get( 'actor' ); - $object = $this->objectsService->dereference( $objectId ); - if ( ! $object || ! $object->hasField( 'attributedTo' ) ) { - return false; - } - $attributedActorId = $object['attributedTo']; - if ( ! is_string( $attributedActorId ) ) { - $attributedActorId = $attributedActorId['id']; - } - return $requestActor['id'] === $attributedActorId; - } } diff --git a/src/Activities/FollowHandler.php b/src/Activities/FollowHandler.php index 52c49c7..ce54aca 100644 --- a/src/Activities/FollowHandler.php +++ b/src/Activities/FollowHandler.php @@ -1,4 +1,5 @@ 'handleInbox', - ); - } - public function __construct( $autoAccepts, ContextProvider $contextProvider ) { @@ -32,14 +26,20 @@ class FollowHandler implements EventSubscriberInterface $this->contextProvider = $contextProvider; } + public static function getSubscribedEvents() + { + return array( + InboxActivityEvent::NAME => 'handleInbox', + ); + } - public function handleInbox(InboxActivityEvent $event, - /** @noinspection PhpUnusedParameterInspection */ - $eventName, - EventDispatcher $eventDispatcher ) + public function handleInbox( InboxActivityEvent $event, + /** @noinspection PhpUnusedParameterInspection */ + $eventName, + EventDispatcher $eventDispatcher ) { $activity = $event->getActivity(); - if ( ! $activity['type'] === 'Follow' ) { + if ( !$activity['type'] === 'Follow' ) { return; } if ( $this->autoAccepts ) { diff --git a/src/Activities/InboxActivityEvent.php b/src/Activities/InboxActivityEvent.php index 2b70645..9869519 100644 --- a/src/Activities/InboxActivityEvent.php +++ b/src/Activities/InboxActivityEvent.php @@ -1,4 +1,5 @@ contextProvider = $contextProvider; } - + public static function getSubscribedEvents() { return array( @@ -36,11 +29,6 @@ class NonActivityHandler implements EventSubscriberInterface ); } - public function __construct( ContextProvider $contextProvider ) - { - $this->contextProvider = $contextProvider; - } - public function handle( OutboxActivityEvent $event ) { $object = $event->getActivity(); @@ -52,6 +40,19 @@ class NonActivityHandler implements EventSubscriberInterface $event->setActivity( $create ); } + public static function activityTypes() + { + return array( + 'Accept', 'Add', 'Announce', 'Arrive', + 'Block', 'Create', 'Delete', 'Dislike', + 'Flag', 'Follow', 'Ignore', 'Invite', + 'Join', 'Leave', 'Like', 'Listen', + 'Move', 'Offer', 'Question', 'Reject', + 'Read', 'Remove', 'TentativeReject', 'TentativeAccept', + 'Travel', 'Undo', 'Update', 'View', + ); + } + /** * Makes a new Create activity with $object as the object * diff --git a/src/Activities/OutboxActivityEvent.php b/src/Activities/OutboxActivityEvent.php index caa9c90..d77ee20 100644 --- a/src/Activities/OutboxActivityEvent.php +++ b/src/Activities/OutboxActivityEvent.php @@ -1,4 +1,5 @@ objectsService = $objectsService; + } + public static function getSubscribedEvents() { return array( @@ -22,11 +28,6 @@ class UpdateHandler implements EventSubscriberInterface ); } - public function __construct( ObjectsService $objectsService ) - { - $this->objectsService = $objectsService; - } - public function handleInbox( InboxActivityEvent $event ) { $activity = $event->getActivity(); @@ -34,10 +35,10 @@ class UpdateHandler implements EventSubscriberInterface return; } $object = $activity['object']; - if ( ! array_key_exists( 'id', $object ) ) { + if ( !array_key_exists( 'id', $object ) ) { throw new BadRequestHttpException( 'Update object has no "id" field' ); } - if ( ! $this->authorized( $event->getRequest(), $object ) ) { + if ( !$this->authorized( $event->getRequest(), $object ) ) { throw new UnauthorizedHttpException( 'Signature realm="ActivityPub",headers="(request-target) host date"' ); @@ -45,26 +46,6 @@ class UpdateHandler implements EventSubscriberInterface $this->objectsService->replace( $object['id'], $object ); } - public function handleOutbox( OutboxActivityEvent $event ) - { - $activity = $event->getActivity(); - if ( $activity['type'] !== 'Update' ) { - return; - } - $updateFields = $activity['object']; - if ( ! array_key_exists( 'id', $updateFields ) ) { - throw new BadRequestHttpException( 'Update object has no "id" field' ); - } - if ( ! $this->authorized( $event->getRequest(), $updateFields ) ) { - throw new UnauthorizedHttpException( - 'Signature realm="ActivityPub",headers="(request-target) host date"' - ); - } - $updated = $this->objectsService->update( $updateFields['id'], $updateFields ); - $activity['object'] = $updated->asArray(); - $event->setActivity( $activity ); - } - /** * Returns true if $request is authorized to update $object * @@ -74,25 +55,45 @@ class UpdateHandler implements EventSubscriberInterface */ private function authorized( Request $request, array $object ) { - if ( ! $request->attributes->has( 'actor' ) ) { + if ( !$request->attributes->has( 'actor' ) ) { return false; } - if ( ! array_key_exists( 'id', $object ) ) { + if ( !array_key_exists( 'id', $object ) ) { return false; } $object = $this->objectsService->dereference( $object['id'] ); - if ( ! $object->hasField( 'attributedTo' ) ) { + if ( !$object->hasField( 'attributedTo' ) ) { return false; } $attributedActorId = $object['attributedTo']; if ( is_array( $attributedActorId ) && - array_key_exists( 'id', $attributedActorId ) ) { + array_key_exists( 'id', $attributedActorId ) ) { $attributedActorId = $attributedActorId['id']; } - if ( ! is_string( $attributedActorId ) ) { + if ( !is_string( $attributedActorId ) ) { return false; } $requestActor = $request->attributes->get( 'actor' ); return $requestActor['id'] === $attributedActorId; } + + public function handleOutbox( OutboxActivityEvent $event ) + { + $activity = $event->getActivity(); + if ( $activity['type'] !== 'Update' ) { + return; + } + $updateFields = $activity['object']; + if ( !array_key_exists( 'id', $updateFields ) ) { + throw new BadRequestHttpException( 'Update object has no "id" field' ); + } + if ( !$this->authorized( $event->getRequest(), $updateFields ) ) { + throw new UnauthorizedHttpException( + 'Signature realm="ActivityPub",headers="(request-target) host date"' + ); + } + $updated = $this->objectsService->update( $updateFields['id'], $updateFields ); + $activity['object'] = $updated->asArray(); + $event->setActivity( $activity ); + } } diff --git a/src/Activities/ValidationHandler.php b/src/Activities/ValidationHandler.php index 42505a9..268b832 100644 --- a/src/Activities/ValidationHandler.php +++ b/src/Activities/ValidationHandler.php @@ -1,4 +1,5 @@ 'verifyInboxActivity', + OutboxActivityEvent::NAME => 'verifyOutboxActivity', + ); + } + + public function verifyInboxActivity( InboxActivityEvent $event ) + { + $activity = $event->getActivity(); + $requiredFields = array( 'type', 'id', 'actor' ); + if ( array_key_exists( 'type', $activity ) && + in_array( $activity['type'], self::getObjectRequiredTypes() ) ) { + $requiredFields[] = 'object'; + } + if ( array_key_exists( 'type', $activity ) && + in_array( $activity['type'], self::getTargetRequiredTypes() ) ) { + $requiredFields[] = 'target'; + } + $this->requireFields( $activity, $requiredFields ); + } + public static function getObjectRequiredTypes() { return array( @@ -21,49 +45,11 @@ class ValidationHandler implements EventSubscriberInterface ); } - public static function getSubscribedEvents() - { - return array( - InboxActivityEvent::NAME => 'verifyInboxActivity', - OutboxActivityEvent::NAME => 'verifyOutboxActivity', - ); - } - - public function verifyInboxActivity( InboxActivityEvent $event ) - { - $activity = $event->getActivity(); - $requiredFields = array( 'type', 'id', 'actor' ); - if ( array_key_exists( 'type', $activity ) && - in_array( $activity['type'], self::getObjectRequiredTypes() ) ) { - $requiredFields[] = 'object'; - } - if ( array_key_exists( 'type', $activity ) && - in_array( $activity['type'], self::getTargetRequiredTypes() ) ) { - $requiredFields[] = 'target'; - } - $this->requireFields( $activity, $requiredFields ); - } - - public function verifyOutboxActivity( OutboxActivityEvent $event ) - { - $activity = $event->getActivity(); - $requiredFields = array( 'type', 'actor' ); - if ( array_key_exists( 'type', $activity ) && - in_array( $activity['type'], self::getObjectRequiredTypes() ) ) { - $requiredFields[] = 'object'; - } - if ( array_key_exists( 'type', $activity ) && - in_array( $activity['type'], self::getTargetRequiredTypes() ) ) { - $requiredFields[] = 'target'; - } - $this->requireFields( $activity, $requiredFields ); - } - private function requireFields( array $activity, array $fields ) { $missing = array(); foreach ( $fields as $field ) { - if ( ! array_key_exists( $field, $activity ) ) { + if ( !array_key_exists( $field, $activity ) ) { $missing[] = $field; } } @@ -73,5 +59,20 @@ class ValidationHandler implements EventSubscriberInterface ); } } + + public function verifyOutboxActivity( OutboxActivityEvent $event ) + { + $activity = $event->getActivity(); + $requiredFields = array( 'type', 'actor' ); + if ( array_key_exists( 'type', $activity ) && + in_array( $activity['type'], self::getObjectRequiredTypes() ) ) { + $requiredFields[] = 'object'; + } + if ( array_key_exists( 'type', $activity ) && + in_array( $activity['type'], self::getTargetRequiredTypes() ) ) { + $requiredFields[] = 'target'; + } + $this->requireFields( $activity, $requiredFields ); + } } diff --git a/src/ActivityPub.php b/src/ActivityPub.php index a4a38e1..3cb5b98 100644 --- a/src/ActivityPub.php +++ b/src/ActivityPub.php @@ -39,7 +39,7 @@ class ActivityPub */ public function __construct( ActivityPubConfig $config ) { - $this->module = new ActivityPubModule( $config); + $this->module = new ActivityPubModule( $config ); } /** @@ -52,7 +52,7 @@ class ActivityPub */ public function handle( $request = null ) { - if ( ! $request ) { + if ( !$request ) { $request = Request::createFromGlobals(); } @@ -73,21 +73,6 @@ class ActivityPub return $kernel->handle( $request ); } - /** - * Creates the database tables necessary for the library to function, - * if they have not already been created. - * - * For best performance, this should only get called once in an application - * (for example, when other database migrations get run). - */ - public function updateSchema() - { - $entityManager = $this->module->get( EntityManager::class ); - $schemaTool = new SchemaTool( $entityManager ); - $classes = $entityManager->getMetadataFactory()->getAllMetadata(); - $schemaTool->updateSchema( $classes ); - } - /** * Sets up the activity handling pipeline * @@ -102,5 +87,20 @@ class ActivityPub $dispatcher->addSubscriber( $this->module->get( UpdateHandler::class ) ); $dispatcher->addSubscriber( $this->module->get( DeleteHandler::class ) ); } + + /** + * Creates the database tables necessary for the library to function, + * if they have not already been created. + * + * For best performance, this should only get called once in an application + * (for example, when other database migrations get run). + */ + public function updateSchema() + { + $entityManager = $this->module->get( EntityManager::class ); + $schemaTool = new SchemaTool( $entityManager ); + $classes = $entityManager->getMetadataFactory()->getAllMetadata(); + $schemaTool->updateSchema( $classes ); + } } diff --git a/src/Auth/AuthListener.php b/src/Auth/AuthListener.php index 83b5538..bc2f910 100644 --- a/src/Auth/AuthListener.php +++ b/src/Auth/AuthListener.php @@ -2,14 +2,14 @@ namespace ActivityPub\Auth; -use Exception; use ActivityPub\Objects\ObjectsService; +use Exception; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; /** - * The AuthListener class answers the question, "is this request authorized + * The AuthListener class answers the question, "is this request authorized * to act on behalf of this Actor?" * * It delegates most of the work to a passed-in Callable to allow library clients to @@ -30,13 +30,6 @@ class AuthListener implements EventSubscriberInterface */ private $objectsService; - public static function getSubscribedEvents() - { - return array( - KernelEvents::REQUEST => 'checkAuth' - ); - } - /** * Constructs a new AuthenticationService * @@ -49,6 +42,13 @@ class AuthListener implements EventSubscriberInterface $this->objectsService = $objectsService; } + public static function getSubscribedEvents() + { + return array( + KernelEvents::REQUEST => 'checkAuth' + ); + } + public function checkAuth( GetResponseEvent $event ) { $request = $event->getRequest(); @@ -56,9 +56,9 @@ class AuthListener implements EventSubscriberInterface return; } $actorId = call_user_func( $this->authFunction ); - if ( $actorId && ! empty( $actorId ) ) { + if ( $actorId && !empty( $actorId ) ) { $actor = $this->objectsService->dereference( $actorId ); - if ( ! $actor ) { + if ( !$actor ) { throw new Exception( "Actor $actorId does not exist" ); } $request->attributes->set( 'actor', $actor ); diff --git a/src/Auth/AuthService.php b/src/Auth/AuthService.php index dff0023..41dd12e 100644 --- a/src/Auth/AuthService.php +++ b/src/Auth/AuthService.php @@ -1,4 +1,5 @@ hasAudience( $object ) ) { + if ( !$this->hasAudience( $object ) ) { return true; } $audience = $this->getAudience( $object ); @@ -43,8 +44,8 @@ class AuthService // TODO do I need to traverse the inReplyTo chain here? $objectArr = $object->asArray( 0 ); $audience = array(); - foreach( array( 'to', 'bto', 'cc', 'bcc', 'audience', 'attributedTo', 'actor' ) - as $attribute ) { + foreach ( array( 'to', 'bto', 'cc', 'bcc', 'audience', 'attributedTo', 'actor' ) + as $attribute ) { $audience = $this->checkAudienceAttribute( $audience, $attribute, $objectArr ); } return $audience; @@ -54,7 +55,7 @@ class AuthService { if ( array_key_exists( $attribute, $objectArr ) ) { $audienceValue = $objectArr[$attribute]; - if ( ! is_array( $audienceValue ) ) { + if ( !is_array( $audienceValue ) ) { $audienceValue = array( $audienceValue ); } return array_merge( $audience, $audienceValue ); diff --git a/src/Auth/SignatureListener.php b/src/Auth/SignatureListener.php index 2a3414a..3ffef04 100644 --- a/src/Auth/SignatureListener.php +++ b/src/Auth/SignatureListener.php @@ -1,4 +1,5 @@ 'validateHttpSignature' - ); - } - public function __construct( HttpSignatureService $httpSignatureService, ObjectsService $objectsService ) { @@ -38,6 +32,13 @@ class SignatureListener implements EventSubscriberInterface $this->objectsService = $objectsService; } + public static function getSubscribedEvents() + { + return array( + KernelEvents::REQUEST => 'validateHttpSignature' + ); + } + /** * Check for a valid HTTP signature on the request. If the request has a valid * signature, set the 'signed' and 'signedBy' keys on the request ('signedBy' is @@ -52,33 +53,33 @@ class SignatureListener implements EventSubscriberInterface if ( $headers->has( 'signature' ) ) { $signatureHeader = $headers->get( 'signature' ); } else if ( $headers->has( 'authorization' ) && - substr( $headers->get( 'authorization' ), 0, 9 ) === 'Signature' ) { + substr( $headers->get( 'authorization' ), 0, 9 ) === 'Signature' ) { $signatureHeader = substr( $headers->get( 'authorization' ), 10 ); } - if ( ! $signatureHeader ) { + if ( !$signatureHeader ) { return; } $matches = array(); - if ( ! preg_match( '/keyId="([^"]*)"/', $signatureHeader, $matches) ) { + if ( !preg_match( '/keyId="([^"]*)"/', $signatureHeader, $matches ) ) { return; } $keyId = $matches[1]; $key = $this->objectsService->dereference( $keyId ); - if ( ! $key || ! $key->hasField( 'owner' ) || ! $key->hasField( 'publicKeyPem' ) ) { + if ( !$key || !$key->hasField( 'owner' ) || !$key->hasField( 'publicKeyPem' ) ) { return; } $owner = $key['owner']; if ( is_string( $owner ) ) { $owner = $this->objectsService->dereference( $owner ); } - if ( ! $owner ) { + if ( !$owner ) { return; } - if ( ! $this->httpSignatureService->verify( $request, $key['publicKeyPem'] ) ) { + if ( !$this->httpSignatureService->verify( $request, $key['publicKeyPem'] ) ) { return; } $request->attributes->set( 'signed', true ); - if ( ! $request->attributes->has( 'actor' ) ) { + if ( !$request->attributes->has( 'actor' ) ) { $request->attributes->set( 'actor', $owner ); } } diff --git a/src/Config/ActivityPubConfig.php b/src/Config/ActivityPubConfig.php index 7830e5d..52d8ede 100644 --- a/src/Config/ActivityPubConfig.php +++ b/src/Config/ActivityPubConfig.php @@ -1,4 +1,5 @@ createBuilder()->build() * * @param ActivityPubConfigBuilder $builder diff --git a/src/Config/ActivityPubConfigBuilder.php b/src/Config/ActivityPubConfigBuilder.php index 79dee64..3f1f614 100644 --- a/src/Config/ActivityPubConfigBuilder.php +++ b/src/Config/ActivityPubConfigBuilder.php @@ -1,4 +1,5 @@ isDevMode = false; $this->dbPrefix = ''; - $this->authFunction = function() { + $this->authFunction = function () { return false; }; $this->jsonLdContext = ContextProvider::getDefaultContext(); @@ -85,11 +86,21 @@ class ActivityPubConfigBuilder */ private function validate() { - if ( ! $this->dbConnectionParams ) { + if ( !$this->dbConnectionParams ) { throw new Exception( "Missing required option 'dbConnectionParams'" ); } } + /** + * @return array + * + * + */ + public function getDbConnectionParams() + { + return $this->dbConnectionParams; + } + /** * The `dbConnectionParams` are the Doctrine connection parameters, * passed directly through to EntityManager::create(). See @@ -106,13 +117,13 @@ class ActivityPubConfigBuilder } /** - * @return array + * @return bool * * */ - public function getDbConnectionParams() + public function getIsDevMode() { - return $this->dbConnectionParams; + return $this->isDevMode; } /** @@ -130,13 +141,11 @@ class ActivityPubConfigBuilder } /** - * @return bool - * - * + * @return string */ - public function getIsDevMode() + public function getDbPrefix() { - return $this->isDevMode; + return $this->dbPrefix; } /** @@ -156,11 +165,11 @@ class ActivityPubConfigBuilder } /** - * @return string + * @return Callable */ - public function getDbPrefix() + public function getAuthFunction() { - return $this->dbPrefix; + return $this->authFunction; } /** @@ -182,11 +191,11 @@ class ActivityPubConfigBuilder } /** - * @return Callable + * @return array */ - public function getAuthFunction() + public function getJsonLdContext() { - return $this->authFunction; + return $this->jsonLdContext; } /** @@ -205,11 +214,11 @@ class ActivityPubConfigBuilder } /** - * @return array + * @return string */ - public function getJsonLdContext() + public function getIdPathPrefix() { - return $this->jsonLdContext; + return $this->idPathPrefix; } /** @@ -226,13 +235,5 @@ class ActivityPubConfigBuilder $this->idPathPrefix = $idPathPrefix; return $this; } - - /** - * @return string - */ - public function getIdPathPrefix() - { - return $this->idPathPrefix; - } } diff --git a/src/Config/ActivityPubModule.php b/src/Config/ActivityPubModule.php index 3985bed..be5c50f 100644 --- a/src/Config/ActivityPubModule.php +++ b/src/Config/ActivityPubModule.php @@ -5,8 +5,8 @@ namespace ActivityPub\Config; use ActivityPub\Activities\CreateHandler; -use ActivityPub\Activities\NonActivityHandler; use ActivityPub\Activities\DeleteHandler; +use ActivityPub\Activities\NonActivityHandler; use ActivityPub\Activities\UpdateHandler; use ActivityPub\Activities\ValidationHandler; use ActivityPub\Auth\AuthListener; @@ -17,8 +17,8 @@ use ActivityPub\Controllers\PostController; use ActivityPub\Crypto\HttpSignatureService; use ActivityPub\Database\PrefixNamingStrategy; use ActivityPub\Http\Router; -use ActivityPub\Objects\ContextProvider; use ActivityPub\Objects\CollectionsService; +use ActivityPub\Objects\ContextProvider; use ActivityPub\Objects\IdProvider; use ActivityPub\Objects\ObjectsService; use ActivityPub\Utils\RandomProvider; @@ -94,7 +94,7 @@ class ActivityPubModule ->addArgument( new Reference( AuthService::class ) ) ->addArgument( new Reference( ContextProvider::class ) ) ->addArgument( new Reference( Client::class ) ) - ->addArgument( new Reference( SimpleDateTimeProvider::class )); + ->addArgument( new Reference( SimpleDateTimeProvider::class ) ); $this->injector->register( RandomProvider::class, RandomProvider::class ); diff --git a/src/Controllers/GetController.php b/src/Controllers/GetController.php index 62b8efa..5a9b656 100644 --- a/src/Controllers/GetController.php +++ b/src/Controllers/GetController.php @@ -1,4 +1,5 @@ objectsService->dereference( $uri ); - if ( ! $object ) { + if ( !$object ) { throw new NotFoundHttpException(); } - if ( ! $this->authService->isAuthorized( $request, $object ) ) { + if ( !$this->authService->isAuthorized( $request, $object ) ) { throw new UnauthorizedHttpException( 'Signature realm="ActivityPub",headers="(request-target) host date"' ); } if ( $object->hasField( 'type' ) && - ( $object['type'] === 'Collection' || - $object['type'] === 'OrderedCollection' ) ) { + ( $object['type'] === 'Collection' || + $object['type'] === 'OrderedCollection' ) ) { $pagedCollection = $this->collectionsService->pageAndFilterCollection( $request, $object ); return new JsonResponse( $pagedCollection ); } $response = new JsonResponse( $object->asArray() ); if ( $object->hasField( 'type' ) && - $object['type'] === 'Tombstone' ) { + $object['type'] === 'Tombstone' ) { $response->setStatusCode( 410 ); } return $response; diff --git a/src/Controllers/PostController.php b/src/Controllers/PostController.php index 1c7c0ce..ea3d477 100644 --- a/src/Controllers/PostController.php +++ b/src/Controllers/PostController.php @@ -1,4 +1,5 @@ getReferencingField( 'inbox' ); if ( $inboxField ) { $activity = json_decode( $request->getContent(), true ); - if ( ! $activity || ! array_key_exists( 'actor', $activity ) ) { + if ( !$activity || !array_key_exists( 'actor', $activity ) ) { throw new BadRequestHttpException(); } $activityActor = $this->getActivityActor( $activity ); - if ( ! $activityActor) { + if ( !$activityActor ) { throw new BadRequestHttpException(); } - if ( ! $request->attributes->has( 'signed' ) || - ! $this->authorized( $request, $activityActor ) ) { + if ( !$request->attributes->has( 'signed' ) || + !$this->authorized( $request, $activityActor ) ) { throw new UnauthorizedHttpException( 'Signature realm="ActivityPub",headers="(request-target) host date"' ); @@ -75,22 +76,32 @@ class PostController $outboxField = $object->getReferencingField( 'outbox' ); if ( $outboxField ) { $actorWithOutbox = $outboxField->getObject(); - if ( ! $this->authorized( $request, $actorWithOutbox ) ) { + if ( !$this->authorized( $request, $actorWithOutbox ) ) { throw new UnauthorizedHttpException( 'Signature realm="ActivityPub",headers="(request-target) host date"' ); } $activity = json_decode( $request->getContent(), true ); - if ( ! $activity ) { + if ( !$activity ) { throw new BadRequestHttpException(); } $event = new OutboxActivityEvent( $activity, $actorWithOutbox, $request ); $this->eventDispatcher->dispatch( OutboxActivityEvent::NAME, $event ); return $event->getResponse(); - } + } throw new MethodNotAllowedHttpException( array( Request::METHOD_GET ) ); } + private function getUriWithoutQuery( Request $request ) + { + $uri = $request->getUri(); + $queryPos = strpos( $uri, '?' ); + if ( $queryPos !== false ) { + $uri = substr( $uri, 0, $queryPos ); + } + return $uri; + } + private function getActivityActor( array $activity ) { $actor = $activity['actor']; @@ -104,7 +115,7 @@ class PostController private function authorized( Request $request, ActivityPubObject $activityActor ) { - if ( ! $request->attributes->has( 'actor' ) ) { + if ( !$request->attributes->has( 'actor' ) ) { return false; } $requestActor = $request->attributes->get( 'actor' ); @@ -113,15 +124,5 @@ class PostController } return true; } - - private function getUriWithoutQuery( Request $request ) - { - $uri = $request->getUri(); - $queryPos = strpos( $uri, '?' ); - if ( $queryPos !== false ) { - $uri = substr( $uri, 0, $queryPos ); - } - return $uri; - } } diff --git a/src/Crypto/HttpSignatureService.php b/src/Crypto/HttpSignatureService.php index 9206790..c82adca 100644 --- a/src/Crypto/HttpSignatureService.php +++ b/src/Crypto/HttpSignatureService.php @@ -1,10 +1,11 @@ dateTimeProvider = $dateTimeProvider; $this->psr7Factory = new DiactorosFactory(); } - public static function getDefaultHeaders() - { - return array( - '(request-target)', - 'host', - 'date', - ); - } - /** * Generates a signature given the request and private key * * @param RequestInterface $request The request to be signed * @param string $privateKey The private key to use to sign the request * @param string $keyId The id of the signing key - * @param array $headers|null The headers to use in the signature + * @param array $headers |null The headers to use in the signature * (default ['(request-target)', 'host', 'date']) * @return string The Signature header value */ - public function sign( RequestInterface $request, $privateKey, + public function sign( RequestInterface $request, $privateKey, $keyId, $headers = null ) { - if ( ! $headers ) { + if ( !$headers ) { $headers = self::getDefaultHeaders(); } $headers = array_map( 'strtolower', $headers ); @@ -78,6 +70,45 @@ class HttpSignatureService "signature=\"$signature\""; } + public static function getDefaultHeaders() + { + return array( + '(request-target)', + 'host', + 'date', + ); + } + + /** + * Returns the signing string from the request + * + * @param RequestInterface $request The request + * @param array $headers The headers to use to generate the signing string + * @return string The signing string + */ + private function getSigningString( RequestInterface $request, $headers ) + { + $signingComponents = array(); + foreach ( $headers as $header ) { + $component = "${header}: "; + if ( $header == '(request-target)' ) { + $method = strtolower( $request->getMethod() ); + $path = $request->getUri()->getPath(); + $query = $request->getUri()->getQuery(); + if ( !empty( $query ) ) { + $path = "$path?$query"; + } + $component = $component . $method . ' ' . $path; + } else { + // TODO handle 'digest' specially here too + $values = $request->getHeader( $header ); + $component = $component . implode( ', ', $values ); + } + $signingComponents[] = $component; + } + return implode( "\n", $signingComponents ); + } + /** * Verifies the HTTP signature of $request * @@ -85,12 +116,12 @@ class HttpSignatureService * @param string $publicKey The public key to use to verify the request * @return bool True if the signature is valid, false if it is missing or invalid */ - public function verify( Request $request, $publicKey ) + public function verify( Request $request, $publicKey ) { $params = array(); $headers = $request->headers; - if ( ! $headers->has( 'date' ) ) { + if ( !$headers->has( 'date' ) ) { return false; } $now = $this->dateTimeProvider->getTime( 'http-signature.verify' ); @@ -102,7 +133,7 @@ class HttpSignatureService if ( $headers->has( 'signature' ) ) { $params = $this->parseSignatureParams( $headers->get( 'signature' ) ); } else if ( $headers->has( 'authorization' ) && - substr($headers->get( 'authorization' ), 0, 9) === 'Signature' ) { + substr( $headers->get( 'authorization' ), 0, 9 ) === 'Signature' ) { $paramsStr = substr( $headers->get( 'authorization' ), 10 ); $params = $this->parseSignatureParams( $paramsStr ); } @@ -121,43 +152,13 @@ class HttpSignatureService $signature = base64_decode( $params['signature'] ); // TODO handle different algorithms here, checking the 'algorithm' param and the key headers $keypair = RsaKeypair::fromPublicKey( $publicKey ); - return $keypair->verify($signingString, $signature, 'sha256'); - } - - /** - * Returns the signing string from the request - * - * @param RequestInterface $request The request - * @param array $headers The headers to use to generate the signing string - * @return string The signing string - */ - private function getSigningString( RequestInterface $request, $headers ) - { - $signingComponents = array(); - foreach ( $headers as $header ) { - $component = "${header}: "; - if ( $header == '(request-target)' ) { - $method = strtolower( $request->getMethod()); - $path = $request->getUri()->getPath(); - $query = $request->getUri()->getQuery(); - if ( ! empty( $query ) ) { - $path = "$path?$query"; - } - $component = $component . $method . ' ' . $path; - } else { - // TODO handle 'digest' specially here too - $values = $request->getHeader( $header ); - $component = $component . implode( ', ', $values ); - } - $signingComponents[] = $component; - } - return implode( "\n", $signingComponents ); + return $keypair->verify( $signingString, $signature, 'sha256' ); } /** * Parses the signature params from the provided params string * - * @param string $paramsStr The params represented as a string, + * @param string $paramsStr The params represented as a string, * e.g. 'keyId="theKey",algorithm="rsa-sha256"' * @return array The params as an associative array */ @@ -169,7 +170,7 @@ class HttpSignatureService $paramName = $paramArr[0]; $paramValue = $paramArr[1]; if ( $paramName == 'headers' ) { - $paramValue = explode(' ', $paramValue); + $paramValue = explode( ' ', $paramValue ); } $params[$paramName] = $paramValue; } diff --git a/src/Crypto/RsaKeypair.php b/src/Crypto/RsaKeypair.php index 4b89242..e2e245b 100644 --- a/src/Crypto/RsaKeypair.php +++ b/src/Crypto/RsaKeypair.php @@ -1,4 +1,5 @@ publicKey = $publicKey; $this->privateKey = $privateKey; } + /** + * Generates a new keypair + * + * @return RsaKeypair + */ + public static function generate() + { + $rsa = new RSA(); + $key = $rsa->createKey( 2048 ); + return new RsaKeypair( $key['publickey'], $key['privatekey'] ); + } + + /** + * Generates an RsaKeypair with the given public key + * + * The generated RsaKeypair will be able to verify signatures but + * not sign data, since it won't have a private key. + * + * @param string $publicKey The public key + * @return RsaKeypair + */ + public static function fromPublicKey( $publicKey ) + { + return new RsaKeypair( $publicKey, '' ); + } + + /** + * Generates an RsaKeypair with the given private key + * + * The generated RsaKeypair will be able to sign data but + * not verify signatures, since it won't have a public key. + * + * @param string $privateKey The private key + * @return RsaKeypair + */ + public static function fromPrivateKey( $privateKey ) + { + return new RsaKeypair( '', $privateKey ); + } + /** * Returns the public key as a string * @@ -66,7 +107,7 @@ class RsaKeypair } $rsa = new RSA(); $rsa->setHash( $hash ); - $rsa->setSignatureMode(RSA::SIGNATURE_PKCS1); + $rsa->setSignatureMode( RSA::SIGNATURE_PKCS1 ); $rsa->loadKey( $this->privateKey ); return $rsa->sign( $data ); } @@ -86,49 +127,9 @@ class RsaKeypair // I have no idea what that means or how to fix it $rsa = new RSA(); $rsa->setHash( $hash ); - $rsa->setSignatureMode(RSA::SIGNATURE_PKCS1); + $rsa->setSignatureMode( RSA::SIGNATURE_PKCS1 ); $rsa->loadKey( $this->publicKey ); return $rsa->verify( $data, $signature ); } - - /** - * Generates a new keypair - * - * @return RsaKeypair - */ - public static function generate() - { - $rsa = new RSA(); - $key = $rsa->createKey( 2048 ); - return new RsaKeypair( $key['publickey'], $key['privatekey'] ); - } - - /** - * Generates an RsaKeypair with the given public key - * - * The generated RsaKeypair will be able to verify signatures but - * not sign data, since it won't have a private key. - * - * @param string $publicKey The public key - * @return RsaKeypair - */ - public static function fromPublicKey( $publicKey ) - { - return new RsaKeypair( $publicKey, '' ); - } - - /** - * Generates an RsaKeypair with the given private key - * - * The generated RsaKeypair will be able to sign data but - * not verify signatures, since it won't have a public key. - * - * @param string $privateKey The private key - * @return RsaKeypair - */ - public static function fromPrivateKey( $privateKey) - { - return new RsaKeypair( '', $privateKey ); - } } diff --git a/src/Database/PrefixNamingStrategy.php b/src/Database/PrefixNamingStrategy.php index c6e3301..718fe9c 100644 --- a/src/Database/PrefixNamingStrategy.php +++ b/src/Database/PrefixNamingStrategy.php @@ -1,4 +1,5 @@ prefix = $prefix; } - public function classToTableName($className) - { - return $this->prefix . substr($className, strrpos($className, '\\') + 1); - } - - public function propertyToColumnName($propertyName, $className = null) + public function propertyToColumnName( $propertyName, $className = null ) { return $propertyName; } + public function joinColumnName( $propertyName, $className = null ) + { + return $propertyName . '_' . $this->referenceColumnName(); + } + public function referenceColumnName() { return 'id'; } - public function joinColumnName($propertyName, $className = null) + public function joinTableName( $sourceEntity, $targetEntity, $propertyName = null ) { - return $propertyName . '_' . $this->referenceColumnName(); + return strtolower( $this->classToTableName( $sourceEntity ) . '_' . + $this->classToTableName( $targetEntity ) ); } - public function joinTableName($sourceEntity, $targetEntity, $propertyName = null) + public function classToTableName( $className ) { - return strtolower($this->classToTableName($sourceEntity) . '_' . - $this->classToTableName($targetEntity)); + return $this->prefix . substr( $className, strrpos( $className, '\\' ) + 1 ); } - public function joinKeyColumnName($entityName, $referencedColumnName = null) + public function joinKeyColumnName( $entityName, $referencedColumnName = null ) { - return strtolower($this->classToTableName($entityName) . '_' . - ($referencedColumnName ?: $this->referenceColumnName())); + return strtolower( $this->classToTableName( $entityName ) . '_' . + ( $referencedColumnName ?: $this->referenceColumnName() ) ); } - public function embeddedFieldToColumnName($propertyName, $embeddedColumnName, $className = null, $embeddedClassName = null) + public function embeddedFieldToColumnName( $propertyName, $embeddedColumnName, $className = null, $embeddedClassName = null ) { - return $propertyName.'_'.$embeddedColumnName; + return $propertyName . '_' . $embeddedColumnName; } } diff --git a/src/Entities/ActivityPubObject.php b/src/Entities/ActivityPubObject.php index c52ec99..5477e2e 100644 --- a/src/Entities/ActivityPubObject.php +++ b/src/Entities/ActivityPubObject.php @@ -58,8 +58,9 @@ class ActivityPubObject implements ArrayAccess */ protected $privateKey; - public function __construct( DateTime $time = null ) { - if ( ! $time ) { + public function __construct( DateTime $time = null ) + { + if ( !$time ) { $time = new DateTime( "now" ); } $this->fields = new ArrayCollection(); @@ -75,7 +76,8 @@ class ActivityPubObject implements ArrayAccess * * @return array|string Either the object or its id if $depth is < 0 */ - public function asArray( $depth = 1 ) { + public function asArray( $depth = 1 ) + { if ( $depth < 0 && $this->hasField( 'id' ) ) { return $this->getFieldValue( 'id' ); } @@ -91,9 +93,20 @@ class ActivityPubObject implements ArrayAccess return $arr; } - public function getId() + /** + * Returns true if the object contains a field with key $name + * + * @param mixed $name + * @return boolean + */ + public function hasField( $name ) { - return $this->id; + foreach ( $this->getFields() as $field ) { + if ( $field->getName() === $name ) { + return true; + } + } + return false; } /** @@ -107,13 +120,28 @@ class ActivityPubObject implements ArrayAccess } /** - * Returns the fields which reference this object + * Returns the value of the field with key $name * - * @return Field[] + * The value is either a string, another ActivityPubObject, or null + * if no such key exists. + * + * @param mixed $name + * @return string|ActivityPubObject|null The field's value, or null if + * the field is not found */ - public function getReferencingFields() + public function getFieldValue( $name ) { - return $this->referencingFields; + foreach ( $this->getFields() as $field ) { + if ( $field->getName() === $name ) { + return $field->getValueOrTargetObject(); + } + } + return null; + } + + public function getId() + { + return $this->id; } /** @@ -137,55 +165,14 @@ class ActivityPubObject implements ArrayAccess } /** - * Returns true if the object contains a field with key $name + * Sets the last updated timestamp + * + * @param DateTime $lastUpdated The new last updated timestamp * - * @param mixed $name - * @return boolean */ - public function hasField( $name ) + public function setLastUpdated( $lastUpdated ) { - foreach( $this->getFields() as $field ) { - if ( $field->getName() === $name ) { - return true; - } - } - return false; - } - - /** - * Returns the fields named $field, if it exists - * - * @param string $name The name of the field to get - * @return Field|null - */ - public function getField( $name ) - { - foreach( $this->getFields() as $field ) { - if ( $field->getName() === $name ) { - return $field; - } - } - return null; - } - - /** - * Returns the value of the field with key $name - * - * The value is either a string, another ActivityPubObject, or null - * if no such key exists. - * - * @param mixed $name - * @return string|ActivityPubObject|null The field's value, or null if - * the field is not found - */ - public function getFieldValue( $name ) - { - foreach( $this->getFields() as $field ) { - if ( $field->getName() === $name ) { - return $field->getValueOrTargetObject(); - } - } - return null; + $this->lastUpdated = $lastUpdated; } /** @@ -200,7 +187,7 @@ class ActivityPubObject implements ArrayAccess */ public function addField( Field $field, DateTime $time = null ) { - if ( ! $time ) { + if ( !$time ) { $time = new DateTime( "now" ); } $this->fields[] = $field; @@ -215,7 +202,7 @@ class ActivityPubObject implements ArrayAccess */ public function hasReferencingField( $name ) { - foreach( $this->getReferencingFields() as $field ) { + foreach ( $this->getReferencingFields() as $field ) { if ( $field->getName() === $name ) { return true; } @@ -223,6 +210,16 @@ class ActivityPubObject implements ArrayAccess return false; } + /** + * Returns the fields which reference this object + * + * @return Field[] + */ + public function getReferencingFields() + { + return $this->referencingFields; + } + /** * Returns the referencing field named $field, if it exists * @@ -231,7 +228,7 @@ class ActivityPubObject implements ArrayAccess */ public function getReferencingField( $name ) { - foreach( $this->getReferencingFields() as $field ) { + foreach ( $this->getReferencingFields() as $field ) { if ( $field->getName() === $name ) { return $field; } @@ -274,34 +271,13 @@ class ActivityPubObject implements ArrayAccess */ public function removeField( Field $field, DateTime $time = null ) { - if ( ! $time ) { + if ( !$time ) { $time = new DateTime( "now" ); } $this->fields->removeElement( $field ); $this->lastUpdated = $time; } - /** - * Sets the last updated timestamp - * - * @param DateTime $lastUpdated The new last updated timestamp - * - */ - public function setLastUpdated( $lastUpdated ) - { - $this->lastUpdated = $lastUpdated; - } - - /** - * Returns true if this object has an associated private key, false if otherwise - * - * @return bool - */ - public function hasPrivateKey() - { - return $this->privateKey !== null; - } - /** * Sets the object's private key * @@ -316,6 +292,16 @@ class ActivityPubObject implements ArrayAccess } } + /** + * Returns true if this object has an associated private key, false if otherwise + * + * @return bool + */ + public function hasPrivateKey() + { + return $this->privateKey !== null; + } + public function offsetExists( $offset ) { return $this->hasField( $offset ); @@ -344,21 +330,37 @@ class ActivityPubObject implements ArrayAccess * Returns true if $other has all the same fields as $this * * @param ActivityPubObject $other The other object to compare to - * @return bool Whether or not this object has the same fields and values as + * @return bool Whether or not this object has the same fields and values as * the other */ public function equals( ActivityPubObject $other ) { - foreach( $other->getFields() as $otherField ) { + foreach ( $other->getFields() as $otherField ) { $thisField = $this->getField( $otherField->getName() ); - if ( ! $thisField ) { + if ( !$thisField ) { return false; } - if ( ! $thisField->equals( $otherField ) ) { + if ( !$thisField->equals( $otherField ) ) { return false; } } return true; } + + /** + * Returns the fields named $field, if it exists + * + * @param string $name The name of the field to get + * @return Field|null + */ + public function getField( $name ) + { + foreach ( $this->getFields() as $field ) { + if ( $field->getName() === $name ) { + return $field; + } + } + return null; + } } diff --git a/src/Entities/Field.php b/src/Entities/Field.php index 1b8653b..00f221f 100644 --- a/src/Entities/Field.php +++ b/src/Entities/Field.php @@ -8,7 +8,7 @@ use DateTime; /** * The field table hold the JSON-LD object graph. - * + * * Its structure is based on https://changelog.com/posts/graph-databases-101: * Every row has a subject, which is a foreign key into the Objects table, * a predicate, which is a the JSON field that describes the graph edge relationship @@ -51,7 +51,7 @@ class Field protected $value; /** * @ManyToOne(targetEntity="ActivityPubObject", inversedBy="referencingFields") - * @var ActivityPubObject The value of the field if it holds another object; + * @var ActivityPubObject The value of the field if it holds another object; * mutually exclusive with $value */ protected $targetObject; @@ -72,7 +72,7 @@ class Field protected function __construct( DateTime $time = null ) { - if ( ! $time ) { + if ( !$time ) { $time = new DateTime( "now" ); } $this->created = $time; @@ -89,9 +89,9 @@ class Field * @return Field The new field * @throws \Exception */ - public static function withValue( ActivityPubObject $object, $name, $value, DateTime $time = null ) + public static function withValue( ActivityPubObject $object, $name, $value, DateTime $time = null ) { - if ( ! $time ) { + if ( !$time ) { $time = new DateTime( "now" ); } $field = new Field( $time ); @@ -116,7 +116,7 @@ class Field ActivityPubObject $targetObject, DateTime $time = null ) { - if ( ! $time ) { + if ( !$time ) { $time = new DateTime( "now" ); } $field = new Field( $time ); @@ -126,59 +126,6 @@ class Field return $field; } - protected function setObject( ActivityPubObject $object, DateTime $time = null ) - { - if ( ! $time ) { - $time = new DateTime( "now" ); - } - $object->addField( $this, $time ); - $this->object= $object; - } - - public function setTargetObject( ActivityPubObject $targetObject, DateTime $time = null ) - { - if ( ! $time ) { - $time = new DateTime( "now" ); - } - $this->value = null; - $oldTargetObject = $this->getTargetObject(); - if ( $oldTargetObject ) { - $oldTargetObject->removeReferencingField( $this ); - } - $targetObject->addReferencingField( $this ); - $this->targetObject = $targetObject; - $this->lastUpdated = $time; - } - - protected function setName( $name ) - { - $this->name= $name; - } - - public function setValue( $value, DateTime $time = null ) - { - if ( ! $time ) { - $time = new DateTime( "now" ); - } - $oldTargetObject = $this->getTargetObject(); - if ( $oldTargetObject ) { - $oldTargetObject->removeReferencingField( $this ); - } - $this->targetObject = null; - $this->value = $value; - $this->lastUpdated = $time; - } - - protected function setCreated( DateTime $timestamp ) - { - $this->created = $timestamp; - } - - protected function setLastUpdated( DateTime $timestamp ) - { - $this->lastUpdated = $timestamp; - } - /** * Returns the object to which this field belongs * @@ -189,54 +136,13 @@ class Field return $this->object; } - /** - * Returns the name of the field - * - * @return string - */ - public function getName() + protected function setObject( ActivityPubObject $object, DateTime $time = null ) { - return $this->name; - } - - /** - * Returns the target object of the field or null if there isn't one - * - * @return ActivityPubObject|null - */ - public function getTargetObject() - { - return $this->targetObject; - } - - /** - * Returns the value of the field or null if there isn't one - * - * @return string|null - */ - public function getValue() - { - return $this->value; - } - - /** - * Returns true if the field has a value - * - * @return bool - */ - public function hasValue() - { - return $this->value !== null; - } - - /** - * Returns true if the field has a target object - * - * @return bool - */ - public function hasTargetObject() - { - return $this->targetObject !== null; + if ( !$time ) { + $time = new DateTime( "now" ); + } + $object->addField( $this, $time ); + $this->object = $object; } /** @@ -246,7 +152,7 @@ class Field */ public function getValueOrTargetObject() { - if ( ! is_null( $this->targetObject) ) { + if ( !is_null( $this->targetObject ) ) { return $this->targetObject; } else { return $this->value; @@ -263,6 +169,11 @@ class Field return $this->created; } + protected function setCreated( DateTime $timestamp ) + { + $this->created = $timestamp; + } + /** * Returns the field's last updated timestamp * @@ -273,6 +184,11 @@ class Field return $this->lastUpdated; } + protected function setLastUpdated( DateTime $timestamp ) + { + $this->lastUpdated = $timestamp; + } + /** * Returns true if $this is equal to $other * @@ -291,5 +207,89 @@ class Field $this->getTargetObject()->equals( $other->getTargetObject() ); } } + + /** + * Returns the name of the field + * + * @return string + */ + public function getName() + { + return $this->name; + } + + protected function setName( $name ) + { + $this->name = $name; + } + + /** + * Returns true if the field has a value + * + * @return bool + */ + public function hasValue() + { + return $this->value !== null; + } + + /** + * Returns the value of the field or null if there isn't one + * + * @return string|null + */ + public function getValue() + { + return $this->value; + } + + public function setValue( $value, DateTime $time = null ) + { + if ( !$time ) { + $time = new DateTime( "now" ); + } + $oldTargetObject = $this->getTargetObject(); + if ( $oldTargetObject ) { + $oldTargetObject->removeReferencingField( $this ); + } + $this->targetObject = null; + $this->value = $value; + $this->lastUpdated = $time; + } + + /** + * Returns true if the field has a target object + * + * @return bool + */ + public function hasTargetObject() + { + return $this->targetObject !== null; + } + + /** + * Returns the target object of the field or null if there isn't one + * + * @return ActivityPubObject|null + */ + public function getTargetObject() + { + return $this->targetObject; + } + + public function setTargetObject( ActivityPubObject $targetObject, DateTime $time = null ) + { + if ( !$time ) { + $time = new DateTime( "now" ); + } + $this->value = null; + $oldTargetObject = $this->getTargetObject(); + if ( $oldTargetObject ) { + $oldTargetObject->removeReferencingField( $this ); + } + $targetObject->addReferencingField( $this ); + $this->targetObject = $targetObject; + $this->lastUpdated = $time; + } } diff --git a/src/Entities/PrivateKey.php b/src/Entities/PrivateKey.php index 1b17bee..276b4d2 100644 --- a/src/Entities/PrivateKey.php +++ b/src/Entities/PrivateKey.php @@ -1,4 +1,5 @@ getController = $getController; + $this->postController = $postController; + } + public static function getSubscribedEvents() { return array( @@ -28,12 +36,6 @@ class Router implements EventSubscriberInterface ); } - public function __construct( GetController $getController, - PostController $postController ) - { - $this->getController = $getController; - $this->postController = $postController; - } /** * Routes the request by setting the _controller attribute * diff --git a/src/Objects/CollectionsService.php b/src/Objects/CollectionsService.php index 21065ee..b3fba63 100644 --- a/src/Objects/CollectionsService.php +++ b/src/Objects/CollectionsService.php @@ -104,6 +104,89 @@ class CollectionsService return $colArr; } + private function getCollectionPage( ActivityPubObject $collection, + Request $request, + $offset, + $pageSize ) + { + $itemsKey = 'items'; + $pageType = 'CollectionPage'; + $isOrdered = $this->isOrdered( $collection ); + if ( $isOrdered ) { + $itemsKey = 'orderedItems'; + $pageType = 'OrderedCollectionPage'; + } + if ( !$collection->hasField( $itemsKey ) ) { + throw new InvalidArgumentException( + "Collection does not have an \"$itemsKey\" key" + ); + } + $collectionItems = $collection->getFieldValue( $itemsKey ); + $pageItems = array(); + $idx = $offset; + $count = 0; + while ( $count < $pageSize ) { + $item = $collectionItems->getFieldValue( $idx ); + if ( !$item ) { + break; + } + if ( is_string( $item ) ) { + $pageItems[] = $item; + $count++; + } else if ( $this->authService->isAuthorized( $request, $item ) ) { + $pageItems[] = $item->asArray( 1 ); + $count++; + } + $idx++; + } + if ( $count === 0 ) { + throw new NotFoundHttpException(); + } + $page = array( + '@context' => $this->contextProvider->getContext(), + 'id' => $collection['id'] . "?offset=$offset", + 'type' => $pageType, + $itemsKey => $pageItems, + 'partOf' => $collection['id'], + ); + // TODO set 'first' and 'last' on the page + $nextIdx = $this->hasNextItem( $request, $collectionItems, $idx ); + if ( $nextIdx ) { + $page['next'] = $collection['id'] . "?offset=$nextIdx"; + } + if ( $isOrdered ) { + $page['startIndex'] = $offset; + } + return $page; + } + + private function isOrdered( ActivityPubObject $collection ) + { + if ( $collection->hasField( 'type' ) && + $collection['type'] === 'OrderedCollection' ) { + return true; + } else if ( $collection->hasField( 'type' ) && + $collection['type'] === 'Collection' ) { + return false; + } else { + throw new InvalidArgumentException( 'Not a collection' ); + } + } + + private function hasNextItem( Request $request, ActivityPubObject $collectionItems, $idx ) + { + $next = $collectionItems->getFieldValue( $idx ); + while ( $next ) { + if ( is_string( $next ) || + $this->authService->isAuthorized( $request, $next ) ) { + return $idx; + } + $idx++; + $next = $collectionItems->getFieldValue( $idx ); + } + return false; + } + /** * Given a collection as an array, normalize the collection by collapsing * collection pages into a single `items` or `orderedItems` array @@ -139,6 +222,38 @@ class CollectionsService return $collection; } + private function fetchPage( $pageId ) + { + $request = new Psr7Request( 'GET', $pageId, array( + 'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' + ) ); + $response = $this->httpClient->send( $request ); + if ( $response->getStatusCode() !== 200 || empty( $response->getBody() ) ) { + return null; + } + return json_decode( $response->getBody(), true ); + } + + private function getPageItems( array $collectionPage ) + { + $items = array(); + if ( array_key_exists( 'items', $collectionPage ) ) { + $items = array_merge( $items, $collectionPage['items'] ); + } else if ( array_key_exists( 'orderedItems', $collectionPage ) ) { + $items = array_merge( $items, $collectionPage['orderedItems'] ); + } + if ( array_key_exists( 'next', $collectionPage ) ) { + $nextPage = $collectionPage['next']; + if ( is_string( $nextPage ) ) { + $nextPage = $this->fetchPage( $nextPage ); + } + if ( $nextPage ) { + $items = array_merge( $items, $this->getPageItems( $nextPage ) ); + } + } + return $items; + } + /** * Adds $item to $collection * @@ -195,120 +310,5 @@ class CollectionsService $this->entityManager->persist( $collection ); $this->entityManager->flush(); } - - private function getPageItems( array $collectionPage ) - { - $items = array(); - if ( array_key_exists( 'items', $collectionPage ) ) { - $items = array_merge( $items, $collectionPage['items'] ); - } else if ( array_key_exists( 'orderedItems', $collectionPage ) ) { - $items = array_merge( $items, $collectionPage['orderedItems'] ); - } - if ( array_key_exists( 'next', $collectionPage ) ) { - $nextPage = $collectionPage['next']; - if ( is_string( $nextPage ) ) { - $nextPage = $this->fetchPage( $nextPage ); - } - if ( $nextPage ) { - $items = array_merge( $items, $this->getPageItems( $nextPage ) ); - } - } - return $items; - } - - private function fetchPage( $pageId ) - { - $request = new Psr7Request( 'GET', $pageId, array( - 'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' - ) ); - $response = $this->httpClient->send( $request ); - if ( $response->getStatusCode() !== 200 || empty( $response->getBody() ) ) { - return null; - } - return json_decode( $response->getBody(), true ); - } - - private function getCollectionPage( ActivityPubObject $collection, - Request $request, - $offset, - $pageSize ) - { - $itemsKey = 'items'; - $pageType = 'CollectionPage'; - $isOrdered = $this->isOrdered( $collection ); - if ( $isOrdered ) { - $itemsKey = 'orderedItems'; - $pageType = 'OrderedCollectionPage'; - } - if ( !$collection->hasField( $itemsKey ) ) { - throw new InvalidArgumentException( - "Collection does not have an \"$itemsKey\" key" - ); - } - $collectionItems = $collection->getFieldValue( $itemsKey ); - $pageItems = array(); - $idx = $offset; - $count = 0; - while ( $count < $pageSize ) { - $item = $collectionItems->getFieldValue( $idx ); - if ( !$item ) { - break; - } - if ( is_string( $item ) ) { - $pageItems[] = $item; - $count++; - } else if ( $this->authService->isAuthorized( $request, $item ) ) { - $pageItems[] = $item->asArray( 1 ); - $count++; - } - $idx++; - } - if ( $count === 0 ) { - throw new NotFoundHttpException(); - } - $page = array( - '@context' => $this->contextProvider->getContext(), - 'id' => $collection['id'] . "?offset=$offset", - 'type' => $pageType, - $itemsKey => $pageItems, - 'partOf' => $collection['id'], - ); - // TODO set 'first' and 'last' on the page - $nextIdx = $this->hasNextItem( $request, $collectionItems, $idx ); - if ( $nextIdx ) { - $page['next'] = $collection['id'] . "?offset=$nextIdx"; - } - if ( $isOrdered ) { - $page['startIndex'] = $offset; - } - return $page; - } - - private function hasNextItem( Request $request, ActivityPubObject $collectionItems, $idx ) - { - $next = $collectionItems->getFieldValue( $idx ); - while ( $next ) { - if ( is_string( $next ) || - $this->authService->isAuthorized( $request, $next ) ) { - return $idx; - } - $idx++; - $next = $collectionItems->getFieldValue( $idx ); - } - return false; - } - - private function isOrdered( ActivityPubObject $collection ) - { - if ( $collection->hasField( 'type' ) && - $collection['type'] === 'OrderedCollection' ) { - return true; - } else if ( $collection->hasField( 'type' ) && - $collection['type'] === 'Collection' ) { - return false; - } else { - throw new InvalidArgumentException( 'Not a collection' ); - } - } } diff --git a/src/Objects/ContextProvider.php b/src/Objects/ContextProvider.php index b70b7ca..2a72b83 100644 --- a/src/Objects/ContextProvider.php +++ b/src/Objects/ContextProvider.php @@ -1,23 +1,19 @@ ctx = $ctx; } - public function getContext() - { - return $this->ctx; - } - public static function getDefaultContext() { return array( @@ -25,5 +21,10 @@ class ContextProvider 'https://w3id.org/security/v1', ); } + + public function getContext() + { + return $this->ctx; + } } diff --git a/src/Objects/IdProvider.php b/src/Objects/IdProvider.php index dfa14d1..2bc1bf8 100644 --- a/src/Objects/IdProvider.php +++ b/src/Objects/IdProvider.php @@ -1,4 +1,5 @@ getSchemeAndHttpHost(); - if ( ! empty( $path ) ) { + if ( !empty( $path ) ) { $baseUri = $baseUri . "/{$this->pathPrefix}/$path"; } $rnd = $this->randomProvider->randomString( self::ID_LENGTH ); diff --git a/src/Objects/ObjectsService.php b/src/Objects/ObjectsService.php index e82ef13..e8176a7 100644 --- a/src/Objects/ObjectsService.php +++ b/src/Objects/ObjectsService.php @@ -14,28 +14,207 @@ use GuzzleHttp\Psr7\Request; class ObjectsService { - /** - * @var EntityManager + /** + * @var EntityManager */ protected $entityManager; - /** - * @var DateTimeProvider + /** + * @var DateTimeProvider */ protected $dateTimeProvider; - /** - * @var Client + /** + * @var Client */ protected $httpClient; public function __construct( EntityManager $entityManager, DateTimeProvider $dateTimeProvider, - Client $client) + Client $client ) { $this->entityManager = $entityManager; $this->dateTimeProvider = $dateTimeProvider; $this->httpClient = $client; } + /** + * Fully replaces the object referenced by $id by the new $fields + * + * @param string $id The id of the object to replace + * @param array $replacement The new fields to replace the object with + * @return ActivityPubObject|null The replaced object, or null + * if no object with $id exists + */ + public function replace( $id, $replacement ) + { + $existing = $this->getObject( $id ); + if ( !$existing ) { + return null; + } + foreach ( $existing->getFields() as $field ) { + if ( !array_key_exists( $field->getName(), $replacement ) ) { + $replacement[$field->getName()] = null; + } + } + return $this->update( $id, $replacement ); + }/** @noinspection PhpDocMissingThrowsInspection */ + + /** + * Gets an object from the DB by its ActivityPub id + * + * For internal use only - external callers should use dereference() + * + * @param string $id The object's id + * @return ActivityPubObject|null The object or null + * if no object exists with that id + */ + protected function getObject( $id ) + { + $results = $this->query( array( 'id' => $id ) ); + if ( !empty( $results ) ) { + return $results[0]; + } + return null; + } + + /** + * Queries for an object with certain field values + * + * @param array $queryTerms An associative array where the keys are field + * names and the values are the values to query for. The value for a key + * can also be another associative array, which represents a field + * containing a target object that matches the given nested query. + * Finally, the value could be a sequential array, which represents a field + * containing all of the specified values (the field could also contain more + * values). + * + * @return ActivityPubObject[] The objects that match the query, if any, + * ordered by created timestamp from newest to oldest + */ + public function query( $queryTerms ) + { + $qb = $this->getObjectQuery( $queryTerms ); + $query = $qb->getQuery(); + return $query->getResult(); + } + + /** + * Generates the Doctrine QueryBuilder that represents the query + * + * This function is recursive; it traverses the query tree to build up the + * final expression + * + * @param array $queryTerms The query terms from which to generate the expressions + * @param int $nonce A nonce value to differentiate field names + * @return QueryBuilder The expression + */ + protected function getObjectQuery( $queryTerms, $nonce = 0 ) + { + $qb = $this->entityManager->createQueryBuilder(); + $exprs = array(); + foreach ( $queryTerms as $fieldName => $fieldValue ) { + if ( is_array( $fieldValue ) ) { + $subQuery = $this->getObjectQuery( $fieldValue, $nonce + 1 ); + $exprs[] = $qb->expr()->andX( + $qb->expr()->like( + "field$nonce.name", + $qb->expr()->literal( (string)$fieldName ) + ), + $qb->expr()->in( "field$nonce.targetObject", $subQuery->getDql() ) + ); + } else { + $exprs[] = $qb->expr()->andX( + $qb->expr()->like( + "field$nonce.name", + $qb->expr()->literal( (string)$fieldName ) + ), + $qb->expr()->like( + "field$nonce.value", + $qb->expr()->literal( $fieldValue ) + ) + ); + } + } + return $qb->select( "object$nonce" ) + ->from( 'ActivityPub\Entities\ActivityPubObject', "object$nonce" ) + ->join( "object{$nonce}.fields", "field$nonce" ) + ->where( call_user_func_array( + array( $qb->expr(), 'orX' ), + $exprs + ) ) + ->groupBy( "object$nonce" ) + ->having( $qb->expr()->eq( + $qb->expr()->count( "field$nonce" ), + count( $queryTerms ) + ) ); + } + + /** + * Updates $object + * + * @param string $id The ActivityPub id of the object to update + * @param array $updatedFields An array where the key is a field name + * to update and the value is the field's new value. If the value is + * null, the field will be deleted. + * + * If the update results in an orphaned anonymous node (an ActivityPubObject + * with no 'id' field that no longer has any references to it), then the + * orphaned node will be deleted. + * + * @return ActivityPubObject|null The updated object, + * or null if an object with that id isn't in the DB + */ + public function update( $id, $updatedFields ) + { + $object = $this->getObject( $id ); + if ( !$object ) { + return null; + } + foreach ( $updatedFields as $fieldName => $newValue ) { + if ( $newValue === null && $object->hasField( $fieldName ) ) { + $field = $object->getField( $fieldName ); + if ( $field->hasTargetObject() && !$field->getTargetObject()->hasField( 'id' ) ) { + $targetObject = $field->getTargetObject(); + // Clear the target object by setting a dummy value + $field->setValue( '' ); + $this->entityManager->remove( $targetObject ); + } + $object->removeField( $field ); + $this->entityManager->persist( $object ); + $this->entityManager->remove( $field ); + } else if ( $object->hasField( $fieldName ) ) { + $field = $object->getField( $fieldName ); + $oldTargetObject = $field->getTargetObject(); + if ( is_array( $newValue ) ) { + $newTargetObject = $this->persist( $newValue, 'objects-service.update' ); + $field->setTargetObject( + $newTargetObject, + $this->dateTimeProvider->getTime( 'objects-service.update' ) + ); + } else { + $field->setValue( + $newValue, $this->dateTimeProvider->getTime( 'objects-service.update' ) + ); + } + if ( $oldTargetObject && !$oldTargetObject->hasField( 'id' ) ) { + $this->entityManager->remove( $oldTargetObject ); + } + $this->entityManager->persist( $field ); + } else { + if ( is_array( $newValue ) ) { + $newTargetObject = $this->persist( $newValue ); + $field = Field::withObject( $object, $fieldName, $newTargetObject ); + } else { + $field = Field::withValue( $object, $fieldName, $newValue ); + } + $this->entityManager->persist( $field ); + } + } + $object->setLastUpdated( $this->dateTimeProvider->getTime( 'objects-service.update' ) ); + $this->entityManager->persist( $object ); + $this->entityManager->flush(); + return $object; + } + /** * Persists a new object to the database with fields defined by $fields * @@ -44,7 +223,7 @@ class ObjectsService * The existing object will not have its fields modified. * * @param array $fields The fields that define the new object - * @param string $context The context to retrieve the current time in. + * @param string $context The context to retrieve the current time in. * Used for fixing the time in tests. * * @return ActivityPubObject The created object @@ -67,7 +246,7 @@ class ObjectsService /** @noinspection PhpUnhandledExceptionInspection */ $this->entityManager->flush(); return $object; - }/** @noinspection PhpDocMissingThrowsInspection */ + } /** * Persists a field. @@ -89,7 +268,7 @@ class ObjectsService $this->entityManager->persist( $fieldEntity ); } else { if ( $fieldName !== 'id' && - filter_var( $fieldValue, FILTER_VALIDATE_URL ) !== false ) { + filter_var( $fieldValue, FILTER_VALIDATE_URL ) !== false ) { $dereferenced = $this->dereference( $fieldValue ); if ( $dereferenced ) { $fieldEntity = Field::withObject( @@ -102,7 +281,7 @@ class ObjectsService $fieldEntity = Field::withValue( $object, $fieldName, $fieldValue, $this->dateTimeProvider->getTime( $context ) ); - $this->entityManager->persist( $fieldEntity); + $this->entityManager->persist( $fieldEntity ); } } @@ -135,189 +314,10 @@ class ObjectsService return null; } $object = json_decode( $response->getBody(), true ); - if ( ! $object ) { + if ( !$object ) { return null; } return $this->persist( $object ); } - - /** - * Queries for an object with certain field values - * - * @param array $queryTerms An associative array where the keys are field - * names and the values are the values to query for. The value for a key - * can also be another associative array, which represents a field - * containing a target object that matches the given nested query. - * Finally, the value could be a sequential array, which represents a field - * containing all of the specified values (the field could also contain more - * values). - * - * @return ActivityPubObject[] The objects that match the query, if any, - * ordered by created timestamp from newest to oldest - */ - public function query( $queryTerms ) - { - $qb = $this->getObjectQuery( $queryTerms ); - $query = $qb->getQuery(); - return $query->getResult(); - } - - /** - * Generates the Doctrine QueryBuilder that represents the query - * - * This function is recursive; it traverses the query tree to build up the - * final expression - * - * @param array $queryTerms The query terms from which to generate the expressions - * @param int $nonce A nonce value to differentiate field names - * @return QueryBuilder The expression - */ - protected function getObjectQuery( $queryTerms, $nonce = 0 ) - { - $qb = $this->entityManager->createQueryBuilder(); - $exprs = array(); - foreach( $queryTerms as $fieldName => $fieldValue ) { - if ( is_array( $fieldValue ) ) { - $subQuery = $this->getObjectQuery( $fieldValue, $nonce + 1 ); - $exprs[] = $qb->expr()->andX( - $qb->expr()->like( - "field$nonce.name", - $qb->expr()->literal( (string) $fieldName ) - ), - $qb->expr()->in( "field$nonce.targetObject", $subQuery->getDql()) - ); - } else { - $exprs[] = $qb->expr()->andX( - $qb->expr()->like( - "field$nonce.name", - $qb->expr()->literal( (string) $fieldName ) - ), - $qb->expr()->like( - "field$nonce.value", - $qb->expr()->literal( $fieldValue ) - ) - ); - } - } - return $qb->select( "object$nonce" ) - ->from( 'ActivityPub\Entities\ActivityPubObject', "object$nonce" ) - ->join( "object{$nonce}.fields", "field$nonce" ) - ->where( call_user_func_array( - array( $qb->expr(), 'orX' ), - $exprs - ) ) - ->groupBy( "object$nonce" ) - ->having( $qb->expr()->eq( - $qb->expr()->count( "field$nonce" ), - count( $queryTerms ) - ) ); - } - - /** - * Gets an object from the DB by its ActivityPub id - * - * For internal use only - external callers should use dereference() - * - * @param string $id The object's id - * @return ActivityPubObject|null The object or null - * if no object exists with that id - */ - protected function getObject( $id ) - { - $results = $this->query( array( 'id' => $id ) ); - if ( ! empty( $results ) ) { - return $results[0]; - } - return null; - } - - /** - * Updates $object - * - * @param string $id The ActivityPub id of the object to update - * @param array $updatedFields An array where the key is a field name - * to update and the value is the field's new value. If the value is - * null, the field will be deleted. - * - * If the update results in an orphaned anonymous node (an ActivityPubObject - * with no 'id' field that no longer has any references to it), then the - * orphaned node will be deleted. - * - * @return ActivityPubObject|null The updated object, - * or null if an object with that id isn't in the DB - */ - public function update( $id, $updatedFields ) - { - $object = $this->getObject( $id ); - if ( ! $object ) { - return null; - } - foreach( $updatedFields as $fieldName => $newValue ) { - if ( $newValue === null && $object->hasField( $fieldName ) ) { - $field = $object->getField( $fieldName ); - if ( $field->hasTargetObject() && ! $field->getTargetObject()->hasField( 'id' ) ) { - $targetObject = $field->getTargetObject(); - // Clear the target object by setting a dummy value - $field->setValue( '' ); - $this->entityManager->remove( $targetObject ); - } - $object->removeField( $field ); - $this->entityManager->persist( $object ); - $this->entityManager->remove( $field ); - } else if ( $object->hasField( $fieldName ) ) { - $field = $object->getField( $fieldName ); - $oldTargetObject = $field->getTargetObject(); - if ( is_array( $newValue ) ) { - $newTargetObject = $this->persist( $newValue, 'objects-service.update' ); - $field->setTargetObject( - $newTargetObject, - $this->dateTimeProvider->getTime( 'objects-service.update' ) - ); - } else { - $field->setValue( - $newValue, $this->dateTimeProvider->getTime( 'objects-service.update' ) - ); - } - if ( $oldTargetObject && ! $oldTargetObject->hasField( 'id' ) ) { - $this->entityManager->remove( $oldTargetObject ); - } - $this->entityManager->persist( $field ); - } else { - if ( is_array( $newValue ) ) { - $newTargetObject = $this->persist( $newValue ); - $field = Field::withObject( $object, $fieldName, $newTargetObject ); - } else { - $field = Field::withValue( $object, $fieldName, $newValue ); - } - $this->entityManager->persist( $field ); - } - } - $object->setLastUpdated( $this->dateTimeProvider->getTime( 'objects-service.update' ) ); - $this->entityManager->persist( $object ); - $this->entityManager->flush(); - return $object; - } - - /** - * Fully replaces the object referenced by $id by the new $fields - * - * @param string $id The id of the object to replace - * @param array $replacement The new fields to replace the object with - * @return ActivityPubObject|null The replaced object, or null - * if no object with $id exists - */ - public function replace( $id, $replacement ) - { - $existing = $this->getObject( $id ); - if ( ! $existing ) { - return null; - } - foreach ( $existing->getFields() as $field ) { - if ( ! array_key_exists( $field->getName(), $replacement ) ) { - $replacement[$field->getName()] = null; - } - } - return $this->update( $id, $replacement ); - } } diff --git a/src/Utils/DateTimeProvider.php b/src/Utils/DateTimeProvider.php index e73c2e5..d370b95 100644 --- a/src/Utils/DateTimeProvider.php +++ b/src/Utils/DateTimeProvider.php @@ -1,4 +1,5 @@ ['da'], ['en-gb', 'q=0.8']] * - * @param string $header HTTP header value + * @param string $header HTTP header value * @param string $separators List of characters to split on, ordered by * precedence, e.g. ",", ";=", or ",;=" * * @return array Nested array with as many levels as there are characters in * $separators */ - public static function split($header, $separators) + public static function split( $header, $separators ) { - $quotedSeparators = preg_quote($separators, '/'); - preg_match_all(' + $quotedSeparators = preg_quote( $separators, '/' ); + preg_match_all( ' / (?!\s) (?: @@ -52,16 +55,55 @@ class HeaderUtils "(?:[^"\\\\]|\\\\.)*(?:"|\\\\|$) | # token - [^"'.$quotedSeparators.']+ + [^"' . $quotedSeparators . ']+ )+ (?['.$quotedSeparators.']) + (?[' . $quotedSeparators . ']) \s* - /x', trim($header), $matches, PREG_SET_ORDER); - return self::groupParts($matches, $separators); + /x', trim( $header ), $matches, PREG_SET_ORDER ); + return self::groupParts( $matches, $separators ); + } + + private static function groupParts( array $matches, $separators ) + { + $separator = $separators[0]; + $partSeparators = substr( $separators, 1 ); + $i = 0; + $partMatches = []; + foreach ( $matches as $match ) { + if ( isset( $match['separator'] ) && $match['separator'] === $separator ) { + ++$i; + } else { + $partMatches[$i][] = $match; + } + } + $parts = []; + if ( $partSeparators ) { + foreach ( $partMatches as $matches ) { + $parts[] = self::groupParts( $matches, $partSeparators ); + } + } else { + foreach ( $partMatches as $matches ) { + $parts[] = self::unquote( $matches[0][0] ); + } + } + return $parts; + } + + /** + * Decodes a quoted string. + * + * If passed an unquoted string that matches the "token" construct (as + * defined in the HTTP specification), it is passed through verbatimly. + * @param $s + * @return string|string[]|null + */ + public static function unquote( $s ) + { + return preg_replace( '/\\\\(.)|"/', '$1', $s ); } /** @@ -79,12 +121,12 @@ class HeaderUtils * @param array $parts * @return array */ - public static function combine(array $parts) + public static function combine( array $parts ) { $assoc = []; - foreach ($parts as $part) { - $name = strtolower($part[0]); - if (isset($part[1])) { + foreach ( $parts as $part ) { + $name = strtolower( $part[0] ); + if ( isset( $part[1] ) ) { $value = $part[1]; } else { $value = true; @@ -94,6 +136,48 @@ class HeaderUtils return $assoc; } + /** + * Generates a HTTP Content-Disposition field-value. + * + * @param string $disposition One of "inline" or "attachment" + * @param string $filename A unicode string + * @param string $filenameFallback A string containing only ASCII characters that + * is semantically equivalent to $filename. If the filename is already ASCII, + * it can be omitted, or just copied from $filename + * + * @return string A string suitable for use as a Content-Disposition field-value + * + * @throws \InvalidArgumentException + * + * @see RFC 6266 + */ + public static function makeDisposition( $disposition, $filename, $filenameFallback = '' ) + { + if ( !\in_array( $disposition, [ self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE ] ) ) { + throw new \InvalidArgumentException( sprintf( 'The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE ) ); + } + if ( '' === $filenameFallback ) { + $filenameFallback = $filename; + } + // filenameFallback is not ASCII. + if ( !preg_match( '/^[\x20-\x7e]*$/', $filenameFallback ) ) { + throw new \InvalidArgumentException( 'The filename fallback must only contain ASCII characters.' ); + } + // percent characters aren't safe in fallback. + if ( false !== strpos( $filenameFallback, '%' ) ) { + throw new \InvalidArgumentException( 'The filename fallback cannot contain the "%" character.' ); + } + // path separators aren't allowed in either. + if ( false !== strpos( $filename, '/' ) || false !== strpos( $filename, '\\' ) || false !== strpos( $filenameFallback, '/' ) || false !== strpos( $filenameFallback, '\\' ) ) { + throw new \InvalidArgumentException( 'The filename and the fallback cannot contain the "/" and "\\" characters.' ); + } + $params = [ 'filename' => $filenameFallback ]; + if ( $filename !== $filenameFallback ) { + $params['filename*'] = "utf-8''" . rawurlencode( $filename ); + } + return $disposition . '; ' . self::toString( $params, ';' ); + } + /** * Joins an associative array into a string for use in an HTTP header. * @@ -109,17 +193,17 @@ class HeaderUtils * @param $separator * @return string */ - public static function toString(array $assoc, $separator) + public static function toString( array $assoc, $separator ) { $parts = []; - foreach ($assoc as $name => $value) { - if (true === $value) { + foreach ( $assoc as $name => $value ) { + if ( true === $value ) { $parts[] = $name; } else { - $parts[] = $name.'='.self::quote($value); + $parts[] = $name . '=' . self::quote( $value ); } } - return implode($separator.' ', $parts); + return implode( $separator . ' ', $parts ); } /** @@ -131,90 +215,11 @@ class HeaderUtils * @param $s * @return string */ - public static function quote($s) + public static function quote( $s ) { - if (preg_match('/^[a-z0-9!#$%&\'*.^_`|~-]+$/i', $s)) { + if ( preg_match( '/^[a-z0-9!#$%&\'*.^_`|~-]+$/i', $s ) ) { return $s; } - return '"'.addcslashes($s, '"\\"').'"'; - } - - /** - * Decodes a quoted string. - * - * If passed an unquoted string that matches the "token" construct (as - * defined in the HTTP specification), it is passed through verbatimly. - * @param $s - * @return string|string[]|null - */ - public static function unquote($s) - { - return preg_replace('/\\\\(.)|"/', '$1', $s); - } - /** - * Generates a HTTP Content-Disposition field-value. - * - * @param string $disposition One of "inline" or "attachment" - * @param string $filename A unicode string - * @param string $filenameFallback A string containing only ASCII characters that - * is semantically equivalent to $filename. If the filename is already ASCII, - * it can be omitted, or just copied from $filename - * - * @return string A string suitable for use as a Content-Disposition field-value - * - * @throws \InvalidArgumentException - * - * @see RFC 6266 - */ - public static function makeDisposition($disposition, $filename, $filenameFallback = '') - { - if (!\in_array($disposition, [self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE])) { - throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE)); - } - if ('' === $filenameFallback) { - $filenameFallback = $filename; - } - // filenameFallback is not ASCII. - if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) { - throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.'); - } - // percent characters aren't safe in fallback. - if (false !== strpos($filenameFallback, '%')) { - throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.'); - } - // path separators aren't allowed in either. - if (false !== strpos($filename, '/') || false !== strpos($filename, '\\') || false !== strpos($filenameFallback, '/') || false !== strpos($filenameFallback, '\\')) { - throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.'); - } - $params = ['filename' => $filenameFallback]; - if ($filename !== $filenameFallback) { - $params['filename*'] = "utf-8''".rawurlencode($filename); - } - return $disposition.'; '.self::toString($params, ';'); - } - private static function groupParts(array $matches, $separators) - { - $separator = $separators[0]; - $partSeparators = substr($separators, 1); - $i = 0; - $partMatches = []; - foreach ($matches as $match) { - if (isset($match['separator']) && $match['separator'] === $separator) { - ++$i; - } else { - $partMatches[$i][] = $match; - } - } - $parts = []; - if ($partSeparators) { - foreach ($partMatches as $matches) { - $parts[] = self::groupParts($matches, $partSeparators); - } - } else { - foreach ($partMatches as $matches) { - $parts[] = self::unquote($matches[0][0]); - } - } - return $parts; + return '"' . addcslashes( $s, '"\\"' ) . '"'; } } diff --git a/src/Utils/RandomProvider.php b/src/Utils/RandomProvider.php index f95954c..b6a773a 100644 --- a/src/Utils/RandomProvider.php +++ b/src/Utils/RandomProvider.php @@ -1,4 +1,5 @@ getMock( IdProvider::class ); // TODO provision mocks $collectionsService = new CollectionsService( - 4, + 4, $this->getMock( AuthService::class ), new ContextProvider(), $this->getMock( Client::class ), diff --git a/test/Activities/DeleteHandlerTest.php b/test/Activities/DeleteHandlerTest.php index 5fb75d2..1bfe38e 100644 --- a/test/Activities/DeleteHandlerTest.php +++ b/test/Activities/DeleteHandlerTest.php @@ -1,36 +1,21 @@ array( - 'id' => 'https://elsewhere.com/objects/1', - 'type' => 'Note', - 'attributedTo' => 'https://elsewhere.com/actors/1', - ), - 'https://example.com/objects/1' => array( - 'id' => 'https://example.com/objects/1', - 'type' => 'Note', - 'attributedTo' => 'https://example.com/actors/1', - ) - ); - } - public function testDeleteHandler() { $testCases = array( @@ -139,12 +124,12 @@ class DeleteHandlerTest extends APTestCase ), ) ); $objectsService = $this->getMockBuilder( ObjectsService::class ) - ->disableOriginalConstructor() - ->setMethods( array( 'dereference', 'replace' ) ) - ->getMock(); - $objectsService->method( 'dereference' )->will( $this->returnCallback( - function( $id ) { - if ( array_key_exists( $id, self::getObjects()) ) { + ->disableOriginalConstructor() + ->setMethods( array( 'dereference', 'replace' ) ) + ->getMock(); + $objectsService->method( 'dereference' )->will( $this->returnCallback( + function ( $id ) { + if ( array_key_exists( $id, self::getObjects() ) ) { $objects = self::getObjects(); return TestActivityPubObject::fromArray( $objects[$id] ); } @@ -173,5 +158,21 @@ class DeleteHandlerTest extends APTestCase $request->attributes->add( $attributes ); return $request; } + + private static function getObjects() + { + return array( + 'https://elsewhere.com/objects/1' => array( + 'id' => 'https://elsewhere.com/objects/1', + 'type' => 'Note', + 'attributedTo' => 'https://elsewhere.com/actors/1', + ), + 'https://example.com/objects/1' => array( + 'id' => 'https://example.com/objects/1', + 'type' => 'Note', + 'attributedTo' => 'https://example.com/actors/1', + ) + ); + } } diff --git a/test/Activities/FollowHandlerTest.php b/test/Activities/FollowHandlerTest.php index f948ffd..670240a 100644 --- a/test/Activities/FollowHandlerTest.php +++ b/test/Activities/FollowHandlerTest.php @@ -1,12 +1,13 @@ 'Follow', 'object' => 'https://example.com/actor/1', ); - $eventDispatcher->addListener( OutboxActivityEvent::NAME, function( $event, $name ) - use ( &$outboxDispatched, $actor, $follow ) - { + $eventDispatcher->addListener( OutboxActivityEvent::NAME, function ( $event, $name ) + use ( &$outboxDispatched, $actor, $follow ) { $this->assertEquals( OutboxActivityEvent::NAME, $name ); $outboxDispatched = true; $accept = array( @@ -81,11 +81,10 @@ class FollowHandlerTest extends APTestCase 'type' => 'Follow', 'object' => 'https://example.com/actor/2', ); - $eventDispatcher->addListener( OutboxActivityEvent::NAME, function() - use ( &$outboxDispatched ) - { - $outboxDispatched = true; - } ); + $eventDispatcher->addListener( OutboxActivityEvent::NAME, function () + use ( &$outboxDispatched ) { + $outboxDispatched = true; + } ); $eventDispatcher->dispatch( InboxActivityEvent::NAME, new InboxActivityEvent( $follow, $actor, diff --git a/test/Activities/NonActivityHandlerTest.php b/test/Activities/NonActivityHandlerTest.php index 7eed74f..6998820 100644 --- a/test/Activities/NonActivityHandlerTest.php +++ b/test/Activities/NonActivityHandlerTest.php @@ -1,11 +1,12 @@ array( - 'id' => 'https://elsewhere.com/objects/1', - 'attributedTo' => 'https://elsewhere.com/actors/1', - ), - 'https://example.com/objects/1' => array( - 'id' => 'https://example.com/objects/1', - 'attributedTo' => 'https://example.com/actors/1', - 'type' => 'Note', - 'content' => 'This is a note', - ), - ); - } - /** * @var EventDispatcher */ private $eventDispatcher; - /** * @var array */ @@ -44,7 +28,7 @@ class UpdateHandlerTest extends APTestCase $this->objects = self::getObjects(); $objectsService = $this->getMock( ObjectsService::class ); $objectsService->method( 'dereference' )->will( $this->returnCallback( - function( $id ) { + function ( $id ) { if ( array_key_exists( $id, $this->objects ) ) { return TestActivityPubObject::fromArray( $this->objects[$id] ); } @@ -52,7 +36,7 @@ class UpdateHandlerTest extends APTestCase } ) ); $objectsService->method( 'update' )->will( $this->returnCallback( - function( $id, $updateFields ) { + function ( $id, $updateFields ) { if ( array_key_exists( $id, $this->objects ) ) { $existing = $this->objects[$id]; foreach ( $updateFields as $field => $newValue ) { @@ -72,6 +56,22 @@ class UpdateHandlerTest extends APTestCase $this->eventDispatcher->addSubscriber( $updateHandler ); } + private static function getObjects() + { + return array( + 'https://elsewhere.com/objects/1' => array( + 'id' => 'https://elsewhere.com/objects/1', + 'attributedTo' => 'https://elsewhere.com/actors/1', + ), + 'https://example.com/objects/1' => array( + 'id' => 'https://example.com/objects/1', + 'attributedTo' => 'https://example.com/actors/1', + 'type' => 'Note', + 'content' => 'This is a note', + ), + ); + } + public function testUpdateHandler() { $testCases = array( diff --git a/test/Activities/ValidationHandlerTest.php b/test/Activities/ValidationHandlerTest.php index 6e2e740..f1f9888 100644 --- a/test/Activities/ValidationHandlerTest.php +++ b/test/Activities/ValidationHandlerTest.php @@ -1,11 +1,12 @@ eventDispatcher = new EventDispatcher(); $validationHandler = new ValidationHandler(); $this->eventDispatcher->addSubscriber( $validationHandler ); } + public function testValidationHandler() { $testCases = array( @@ -162,7 +164,7 @@ class ValidationHandlerTest extends APTestCase $event = $testCase['event']; if ( array_key_exists( 'expectedException', $testCase ) ) { $expectedExceptionMessage = ''; - if ( array_key_exists( 'expectedExceptionMessage', $testCase )) { + if ( array_key_exists( 'expectedExceptionMessage', $testCase ) ) { $expectedExceptionMessage = $testCase['expectedExceptionMessage']; } $this->setExpectedException( diff --git a/test/ActivityPubTest.php b/test/ActivityPubTest.php index 6c45213..da8746b 100644 --- a/test/ActivityPubTest.php +++ b/test/ActivityPubTest.php @@ -1,39 +1,43 @@ assertTrue( file_exists( $this->getDbPath() ) ); } + protected function getDbPath() + { + return dirname( __FILE__ ) . '/db.sqlite'; + } + /** * @depends testItCreatesSchema */ - public function testItUpdatesSchema() { + public function testItUpdatesSchema() + { $config = ActivityPubConfig::createBuilder() - ->setDbConnectionParams( array( - 'driver' => 'pdo_sqlite', - 'path' => $this->getDbPath(), - ) ) - ->build(); + ->setDbConnectionParams( array( + 'driver' => 'pdo_sqlite', + 'path' => $this->getDbPath(), + ) ) + ->build(); $activityPub = new ActivityPub( $config ); $activityPub->updateSchema(); $this->assertTrue( file_exists( $this->getDbPath() ) ); } - - protected function getDbPath() { - return dirname( __FILE__ ) . '/db.sqlite'; - } } diff --git a/test/Auth/AuthListenerTest.php b/test/Auth/AuthListenerTest.php index 39da94c..5d42fc3 100644 --- a/test/Auth/AuthListenerTest.php +++ b/test/Auth/AuthListenerTest.php @@ -3,13 +3,13 @@ namespace ActivityPub\Test\Auth; use ActivityPub\Auth\AuthListener; -use ActivityPub\Objects\ObjectsService; use ActivityPub\Entities\ActivityPubObject; +use ActivityPub\Objects\ObjectsService; +use ActivityPub\Test\TestConfig\APTestCase; use ActivityPub\Test\TestUtils\TestActivityPubObject; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; -use ActivityPub\Test\TestConfig\APTestCase; +use Symfony\Component\HttpKernel\HttpKernelInterface; class AuthListenerTest extends APTestCase { @@ -28,21 +28,12 @@ class AuthListenerTest extends APTestCase ) ) ); } - public function getEvent() - { - $kernel = $this->getMock( HttpKernelInterface::class ); - $request = Request::create( 'https://example.com/foo', Request::METHOD_GET ); - return new GetResponseEvent( - $kernel, $request, HttpKernelInterface::MASTER_REQUEST - ); - } - public function testAuthListener() { $testCases = array( array( 'id' => 'basicTest', - 'authFunction' => function() { + 'authFunction' => function () { return 'https://example.com/actor/1'; }, 'expectedAttributes' => array( @@ -53,7 +44,7 @@ class AuthListenerTest extends APTestCase ), array( 'id' => 'existingActorTest', - 'authFunction' => function() { + 'authFunction' => function () { return 'https://example.com/actor/1'; }, 'requestAttributes' => array( @@ -69,7 +60,7 @@ class AuthListenerTest extends APTestCase ), array( 'id' => 'defaultAuthTest', - 'authFunction' => function() { + 'authFunction' => function () { return false; }, 'expectedAttributes' => array(), @@ -108,5 +99,14 @@ class AuthListenerTest extends APTestCase } } } + + public function getEvent() + { + $kernel = $this->getMock( HttpKernelInterface::class ); + $request = Request::create( 'https://example.com/foo', Request::METHOD_GET ); + return new GetResponseEvent( + $kernel, $request, HttpKernelInterface::MASTER_REQUEST + ); + } } diff --git a/test/Auth/AuthServiceTest.php b/test/Auth/AuthServiceTest.php index c0f8794..5230e6e 100644 --- a/test/Auth/AuthServiceTest.php +++ b/test/Auth/AuthServiceTest.php @@ -1,9 +1,10 @@ self::ACTOR_ID ); - } - - private static function getKey() - { - return array( - 'id' => self::KEY_ID, - 'owner' => 'https://example.com/actor/1', - 'publicKeyPem' => self::PUBLIC_KEY, - ); - } - public function setUp() { $dateTimeProvider = new TestDateTimeProvider( array( @@ -53,35 +40,26 @@ oYi+1hqp1fIekaxsyQIDAQAB $objectsService = $this->getMock( ObjectsService::class ); $objectsService->method( 'dereference' ) ->will( $this->returnValueMap( array( - array( self::KEY_ID, TestActivityPubObject::fromArray( self::getKey()) ), - array( self::ACTOR_ID, TestActivityPubObject::fromArray( self::getActor()) ), + array( self::KEY_ID, TestActivityPubObject::fromArray( self::getKey() ) ), + array( self::ACTOR_ID, TestActivityPubObject::fromArray( self::getActor() ) ), ) ) ); $this->signatureListener = new SignatureListener( $httpSignatureService, $objectsService ); } - private function getEvent() + private static function getKey() { - $kernel = $this->getMock( HttpKernelInterface::class ); - $request = Request::create( - 'https://example.com/foo?param=value&pet=dog', - Request::METHOD_POST, - array(), - array(), - array(), - array(), - '{"hello": "world"}' + return array( + 'id' => self::KEY_ID, + 'owner' => 'https://example.com/actor/1', + 'publicKeyPem' => self::PUBLIC_KEY, ); - $request->headers->set( 'host', 'example.com' ); - $request->headers->set( 'content-type', 'application/json' ); - $request->headers->set( - 'digest', 'SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=' - ); - $request->headers->set( 'content-length', 18 ); - $request->headers->set( 'date', 'Sun, 05 Jan 2014 21:31:40 GMT' ); - $event = new GetResponseEvent( $kernel, $request, HttpKernelInterface::MASTER_REQUEST ); - return $event; + } + + private static function getActor() + { + return array( 'id' => self::ACTOR_ID ); } public function testSignatureListener() @@ -136,12 +114,12 @@ oYi+1hqp1fIekaxsyQIDAQAB foreach ( $testCases as $testCase ) { $event = $this->getEvent(); if ( array_key_exists( 'headers', $testCase ) ) { - foreach( $testCase['headers'] as $header => $value ) { + foreach ( $testCase['headers'] as $header => $value ) { $event->getRequest()->headers->set( $header, $value ); } } if ( array_key_exists( 'requestAttributes', $testCase ) ) { - foreach( $testCase['requestAttributes'] as $attribute => $value ) { + foreach ( $testCase['requestAttributes'] as $attribute => $value ) { $event->getRequest()->attributes->set( $attribute, $value ); } } @@ -153,5 +131,28 @@ oYi+1hqp1fIekaxsyQIDAQAB ); } } + + private function getEvent() + { + $kernel = $this->getMock( HttpKernelInterface::class ); + $request = Request::create( + 'https://example.com/foo?param=value&pet=dog', + Request::METHOD_POST, + array(), + array(), + array(), + array(), + '{"hello": "world"}' + ); + $request->headers->set( 'host', 'example.com' ); + $request->headers->set( 'content-type', 'application/json' ); + $request->headers->set( + 'digest', 'SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=' + ); + $request->headers->set( 'content-length', 18 ); + $request->headers->set( 'date', 'Sun, 05 Jan 2014 21:31:40 GMT' ); + $event = new GetResponseEvent( $kernel, $request, HttpKernelInterface::MASTER_REQUEST ); + return $event; + } } diff --git a/test/Config/ActivityPubModuleTest.php b/test/Config/ActivityPubModuleTest.php index 13edf7c..b5d7e31 100644 --- a/test/Config/ActivityPubModuleTest.php +++ b/test/Config/ActivityPubModuleTest.php @@ -5,8 +5,8 @@ namespace ActivityPub\Test\Config; use ActivityPub\Config\ActivityPubConfig; use ActivityPub\Config\ActivityPubModule; use ActivityPub\Http\Router; -use Doctrine\ORM\EntityManager; use ActivityPub\Test\TestConfig\APTestCase; +use Doctrine\ORM\EntityManager; class ActivityPubModuleTest extends APTestCase { @@ -18,14 +18,14 @@ class ActivityPubModuleTest extends APTestCase public function setUp() { $config = ActivityPubConfig::createBuilder() - ->setDbConnectionParams( array( - 'driver' => 'pdo_sqlite', - 'path' => ':memory:', - ) ) - ->build(); + ->setDbConnectionParams( array( + 'driver' => 'pdo_sqlite', + 'path' => ':memory:', + ) ) + ->build(); $this->module = new ActivityPubModule( $config ); } - + public function testItInjects() { $entityManager = $this->module->get( EntityManager::class ); diff --git a/test/Controllers/GetControllerTest.php b/test/Controllers/GetControllerTest.php index 68ffc7d..d29918a 100644 --- a/test/Controllers/GetControllerTest.php +++ b/test/Controllers/GetControllerTest.php @@ -1,21 +1,54 @@ objects = self::getObjects(); + $objectsService = $this->getMock( ObjectsService::class ); + $objectsService->method( 'dereference' )->will( + $this->returnCallback( function ( $uri ) { + if ( array_key_exists( $uri, $this->objects ) ) { + return TestActivityPubObject::fromArray( $this->objects[$uri] ); + } + return null; + } ) + ); + $authService = new AuthService(); + $contextProvider = new ContextProvider(); + $httpClient = $this->getMock( Client::class ); + $collectionsService = new CollectionsService( + 4, $authService, $contextProvider, $httpClient, new SimpleDateTimeProvider() + ); + $this->getController = new GetController( + $objectsService, $collectionsService, $authService + ); + } + private static function getObjects() { return array( @@ -58,39 +91,6 @@ class GetControllerTest extends APTestCase ); } - /** - * @var GetController - */ - private $getController; - - /** - * @var array - */ - private $objects; - - public function setUp() - { - $this->objects = self::getObjects(); - $objectsService = $this->getMock( ObjectsService::class ); - $objectsService->method( 'dereference' )->will( - $this->returnCallback( function( $uri ) { - if ( array_key_exists( $uri, $this->objects) ) { - return TestActivityPubObject::fromArray( $this->objects[$uri] ); - } - return null; - }) - ); - $authService = new AuthService(); - $contextProvider = new ContextProvider(); - $httpClient = $this->getMock( Client::class ); - $collectionsService = new CollectionsService( - 4, $authService, $contextProvider, $httpClient, new SimpleDateTimeProvider() - ); - $this->getController = new GetController( - $objectsService, $collectionsService, $authService - ); - } - public function testItRendersPersistedObject() { $request = Request::create( 'https://example.com/objects/1' ); diff --git a/test/Controllers/PostControllerTest.php b/test/Controllers/PostControllerTest.php index 7d2d6da..5ed30e9 100644 --- a/test/Controllers/PostControllerTest.php +++ b/test/Controllers/PostControllerTest.php @@ -1,12 +1,13 @@ array( - 'id' => 'https://example.com/actor/1/inbox', - ), - 'https://example.com/actor/1/outbox' => array( - 'id' => 'https://example.com/actor/1/outbox', - ), - 'https://example.com/actor/1' => array( - 'id' => 'https://example.com/actor/1', - 'inbox' => array( - 'id' => 'https://example.com/actor/1/inbox', - ), - 'outbox' => array( - 'id' => 'https://example.com/actor/1/outbox', - ), - ), - 'https://elsewhere.com/actor/1' => array( - 'id' => 'https://elsewhere.com/actor/1', - ), - ); - } - private static function getRefs() - { - return array( - 'https://example.com/actor/1/inbox' => array( - 'field' => 'inbox', - 'referencingObject' => 'https://example.com/actor/1', - ), - 'https://example.com/actor/1/outbox' => array( - 'field' => 'outbox', - 'referencingObject' => 'https://example.com/actor/1', - ), - ); - } - /** * @var array */ private $objects; - /** * @var array */ @@ -68,9 +31,9 @@ class PostControllerTest extends APTestCase $this->refs = self::getRefs(); $objectsService = $this->getMock( ObjectsService::class ); $objectsService->method( 'query' )->will( - $this->returnCallback( function( $query ) { + $this->returnCallback( function ( $query ) { if ( array_key_exists( 'id', $query ) && - array_key_exists( $query['id'], $this->objects ) ) { + array_key_exists( $query['id'], $this->objects ) ) { $object = TestActivityPubObject::fromArray( $this->objects[$query['id']] ); @@ -89,7 +52,7 @@ class PostControllerTest extends APTestCase } ) ); $objectsService->method( 'dereference' )->will( - $this->returnCallback( function( $id ) { + $this->returnCallback( function ( $id ) { if ( array_key_exists( $id, $this->objects ) ) { return TestActivityPubObject::fromArray( $this->objects[$id] ); } else { @@ -235,14 +198,14 @@ class PostControllerTest extends APTestCase ); foreach ( $testCases as $testCase ) { $eventDispatcher = $this->getMockBuilder( EventDispatcher::class ) - ->setMethods( array( 'dispatch' ) ) - ->getMock(); + ->setMethods( array( 'dispatch' ) ) + ->getMock(); if ( array_key_exists( 'expectedEvent', $testCase ) ) { $eventDispatcher->expects( $this->once() ) ->method( 'dispatch' ) ->with( - $this->equalTo($testCase['expectedEventName']), - $this->equalTo($testCase['expectedEvent']) + $this->equalTo( $testCase['expectedEventName'] ), + $this->equalTo( $testCase['expectedEvent'] ) ); } $postController = new PostController( $eventDispatcher, $objectsService ); @@ -254,6 +217,44 @@ class PostControllerTest extends APTestCase } } + private static function getObjects() + { + return array( + 'https://example.com/actor/1/inbox' => array( + 'id' => 'https://example.com/actor/1/inbox', + ), + 'https://example.com/actor/1/outbox' => array( + 'id' => 'https://example.com/actor/1/outbox', + ), + 'https://example.com/actor/1' => array( + 'id' => 'https://example.com/actor/1', + 'inbox' => array( + 'id' => 'https://example.com/actor/1/inbox', + ), + 'outbox' => array( + 'id' => 'https://example.com/actor/1/outbox', + ), + ), + 'https://elsewhere.com/actor/1' => array( + 'id' => 'https://elsewhere.com/actor/1', + ), + ); + } + + private static function getRefs() + { + return array( + 'https://example.com/actor/1/inbox' => array( + 'field' => 'inbox', + 'referencingObject' => 'https://example.com/actor/1', + ), + 'https://example.com/actor/1/outbox' => array( + 'field' => 'outbox', + 'referencingObject' => 'https://example.com/actor/1', + ), + ); + } + private function makeRequest( $uri, $method, $body, $attributes ) { $request = Request::create( diff --git a/test/Crypto/HttpSignatureServiceTest.php b/test/Crypto/HttpSignatureServiceTest.php index cd9e34d..47dc5c3 100644 --- a/test/Crypto/HttpSignatureServiceTest.php +++ b/test/Crypto/HttpSignatureServiceTest.php @@ -1,11 +1,12 @@ httpSignatureService = new HttpSignatureService( $dateTimeProvider ); } - private static function getSymfonyRequest() - { - $request = Request::create( - 'https://example.com/foo?param=value&pet=dog', - Request::METHOD_POST, - array(), - array(), - array(), - array(), - '{"hello": "world"}' - ); - $request->headers->set( 'host', 'example.com' ); - $request->headers->set( 'content-type', 'application/json' ); - $request->headers->set( - 'digest', 'SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=' - ); - $request->headers->set( 'content-length', 18 ); - $request->headers->set( 'date', 'Sun, 05 Jan 2014 21:31:40 GMT' ); - return $request; - } - - private static function getPsrRequest() - { - $headers = array( - 'Host' => 'example.com', - 'Content-Type' => 'application/json', - 'Digest' => 'SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=', - 'Content-Length' => 18, - 'Date' => 'Sun, 05 Jan 2014 21:31:40 GMT' - ); - $body = '{"hello": "world"}'; - return new PsrRequest( - 'POST', 'https://example.com/foo?param=value&pet=dog', $headers, $body - ); - } - public function testItVerifies() { $testCases = array( @@ -138,7 +103,7 @@ G6aFKaqQfOXKCyWoUiVknQJAXrlgySFci/2ueKlIE1QqIiLSZ8V8OlpFLRnb1pzI 'id' => 'headerMissing', 'headers' => array( 'Authorization' => 'Signature keyId="Test",algorithm="rsa-sha256",headers="(request-target) host date content-type digest content-length x-foo-header",signature="vSdrb+dS3EceC9bcwHSo4MlyKS59iFIrhgYkz8+oVLEEzmYZZvRs8rgOp+63LEM3v+MFHB32NfpB2bEKBIvB1q52LaEUHFv120V01IL+TAD48XaERZFukWgHoBTLMhYS2Gb51gWxpeIq8knRmPnYePbF5MOkR0Zkly4zKH7s1dE="', - ), + ), 'expectedResult' => false, ), array( @@ -194,6 +159,27 @@ G6aFKaqQfOXKCyWoUiVknQJAXrlgySFci/2ueKlIE1QqIiLSZ8V8OlpFLRnb1pzI } } + private static function getSymfonyRequest() + { + $request = Request::create( + 'https://example.com/foo?param=value&pet=dog', + Request::METHOD_POST, + array(), + array(), + array(), + array(), + '{"hello": "world"}' + ); + $request->headers->set( 'host', 'example.com' ); + $request->headers->set( 'content-type', 'application/json' ); + $request->headers->set( + 'digest', 'SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=' + ); + $request->headers->set( 'content-length', 18 ); + $request->headers->set( 'date', 'Sun, 05 Jan 2014 21:31:40 GMT' ); + return $request; + } + public function testItSigns() { $testCases = array( @@ -223,7 +209,7 @@ G6aFKaqQfOXKCyWoUiVknQJAXrlgySFci/2ueKlIE1QqIiLSZ8V8OlpFLRnb1pzI $request, self::PRIVATE_KEY, $testCase['keyId'], $testCase['headers'] ); } else { - $actual= $this->httpSignatureService->sign( + $actual = $this->httpSignatureService->sign( $request, self::PRIVATE_KEY, $testCase['keyId'] ); } @@ -232,5 +218,20 @@ G6aFKaqQfOXKCyWoUiVknQJAXrlgySFci/2ueKlIE1QqIiLSZ8V8OlpFLRnb1pzI ); } } + + private static function getPsrRequest() + { + $headers = array( + 'Host' => 'example.com', + 'Content-Type' => 'application/json', + 'Digest' => 'SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=', + 'Content-Length' => 18, + 'Date' => 'Sun, 05 Jan 2014 21:31:40 GMT' + ); + $body = '{"hello": "world"}'; + return new PsrRequest( + 'POST', 'https://example.com/foo?param=value&pet=dog', $headers, $body + ); + } } diff --git a/test/Crypto/RsaKeypairTest.php b/test/Crypto/RsaKeypairTest.php index 7c41e65..3592dc8 100644 --- a/test/Crypto/RsaKeypairTest.php +++ b/test/Crypto/RsaKeypairTest.php @@ -1,4 +1,5 @@ array(), - 'fields' => array(), - 'keys' => array(), - ) ); - } - - protected function setUp() - { - parent::setUp(); - $dbConfig = Setup::createAnnotationMetadataConfiguration( - array( __DIR__ . '/../../src/Entities' ), true - ); - $namingStrategy = new PrefixNamingStrategy( '' ); - $dbConfig->setNamingStrategy( $namingStrategy ); - $dbParams = array( - 'driver' => 'pdo_sqlite', - 'path' => $this->getDbPath(), - ); - $this->entityManager = EntityManager::create( $dbParams, $dbConfig ); - $this->dateTimeProvider = new TestDateTimeProvider( array( - 'objects-service.create' => new DateTime( "12:00" ), - 'objects-service.update' => new DateTime( "12:01" ), - ) ); - } - - private function getTime( $context ) { - return $this->dateTimeProvider - ->getTime( $context ) - ->format( "Y-m-d H:i:s" ); - } - public function testItCreatesAnObjectWithAPrivateKey() { $object = new ActivityPubObject( $this->dateTimeProvider->getTime( 'objects-service.create' ) ); @@ -85,6 +51,13 @@ class EntityTest extends SQLiteTestCase $this->assertTablesEqual( $expectedKeysTable, $keysQueryTable ); } + private function getTime( $context ) + { + return $this->dateTimeProvider + ->getTime( $context ) + ->format( "Y-m-d H:i:s" ); + } + public function itUpdatesAPrivateKey() { $object = new ActivityPubObject( $this->dateTimeProvider->getTime( 'objects-service.create' ) ); @@ -116,5 +89,33 @@ class EntityTest extends SQLiteTestCase $this->assertTablesEqual( $expectedObjectsTable, $objectsQueryTable ); $this->assertTablesEqual( $expectedKeysTable, $keysQueryTable ); } + + protected function getDataSet() + { + return new ArrayDataSet( array( + 'objects' => array(), + 'fields' => array(), + 'keys' => array(), + ) ); + } + + protected function setUp() + { + parent::setUp(); + $dbConfig = Setup::createAnnotationMetadataConfiguration( + array( __DIR__ . '/../../src/Entities' ), true + ); + $namingStrategy = new PrefixNamingStrategy( '' ); + $dbConfig->setNamingStrategy( $namingStrategy ); + $dbParams = array( + 'driver' => 'pdo_sqlite', + 'path' => $this->getDbPath(), + ); + $this->entityManager = EntityManager::create( $dbParams, $dbConfig ); + $this->dateTimeProvider = new TestDateTimeProvider( array( + 'objects-service.create' => new DateTime( "12:00" ), + 'objects-service.update' => new DateTime( "12:01" ), + ) ); + } } diff --git a/test/Http/RouterTest.php b/test/Http/RouterTest.php index a82b861..a3dc417 100644 --- a/test/Http/RouterTest.php +++ b/test/Http/RouterTest.php @@ -1,4 +1,5 @@ router = new Router( $this->getController, $this->postController ); $this->kernel = $this->getMock( HttpKernel::class ); } - + public function testRouter() { $testCases = array( @@ -49,7 +50,7 @@ class RouterTest extends APTestCase 'expectedException' => MethodNotAllowedHttpException::class, ), ); - foreach( $testCases as $testCase ) { + foreach ( $testCases as $testCase ) { $request = $testCase['request']; $event = new GetResponseEvent( $this->kernel, $request, HttpKernelInterface::MASTER_REQUEST diff --git a/test/Objects/CollectionsServiceTest.php b/test/Objects/CollectionsServiceTest.php index 2f39e86..fae4b64 100644 --- a/test/Objects/CollectionsServiceTest.php +++ b/test/Objects/CollectionsServiceTest.php @@ -1,14 +1,15 @@ objectsService = $this->getMock( ObjectsService::class ); $this->objectsService->method( 'query' ) - ->will( $this->returnCallback( function( $query) { + ->will( $this->returnCallback( function ( $query ) { $existsId = sprintf( 'https://example.com/ap/objects/%s', self::EXISTING_ID_STR ); diff --git a/test/Objects/ObjectsServiceTest.php b/test/Objects/ObjectsServiceTest.php index ab125ac..5c659b8 100644 --- a/test/Objects/ObjectsServiceTest.php +++ b/test/Objects/ObjectsServiceTest.php @@ -2,16 +2,16 @@ namespace ActivityPub\Test\Objects; -use ActivityPub\Utils\DateTimeProvider; -use DateTime; -use BadMethodCallException; -use ActivityPub\Test\TestConfig\SQLiteTestCase; -use ActivityPub\Test\TestConfig\ArrayDataSet; -use ActivityPub\Entities\ActivityPubObject; -use Doctrine\ORM\EntityManager; -use ActivityPub\Objects\ObjectsService; use ActivityPub\Database\PrefixNamingStrategy; +use ActivityPub\Entities\ActivityPubObject; +use ActivityPub\Objects\ObjectsService; +use ActivityPub\Test\TestConfig\ArrayDataSet; +use ActivityPub\Test\TestConfig\SQLiteTestCase; use ActivityPub\Test\TestUtils\TestDateTimeProvider; +use ActivityPub\Utils\DateTimeProvider; +use BadMethodCallException; +use DateTime; +use Doctrine\ORM\EntityManager; use Doctrine\ORM\Tools\Setup; use GuzzleHttp\Client; use GuzzleHttp\Psr7\Response; @@ -35,42 +35,6 @@ class ObjectsServiceTest extends SQLiteTestCase */ protected $httpClient; - protected function getDataSet() - { - return new ArrayDataSet( array( 'objects' => array(), 'fields' => array() ) ); - } - - protected function setUp() - { - parent::setUp(); - $dbConfig = Setup::createAnnotationMetadataConfiguration( - array( __DIR__ . '/../../src/Entities' ), true - ); - $namingStrategy = new PrefixNamingStrategy( '' ); - $dbConfig->setNamingStrategy( $namingStrategy ); - $dbParams = array( - 'driver' => 'pdo_sqlite', - 'path' => $this->getDbPath(), - ); - $this->entityManager = EntityManager::create( $dbParams, $dbConfig ); - $this->dateTimeProvider = new TestDateTimeProvider( array( - 'objects-service.create' => new DateTime( "12:00" ), - 'objects-service.update' => new DateTime( "12:01" ), - ) ); - $this->httpClient = $this->getMock( Client::class ); - $this->httpClient->method( 'send' ) - ->willReturn( new Response( 404 ) ); - $this->objectsService = new ObjectsService( - $this->entityManager, $this->dateTimeProvider, $this->httpClient - ); - } - - private function getTime( $context ) { - return $this->dateTimeProvider - ->getTime( $context ) - ->format( "Y-m-d H:i:s" ); - } - public function testItCreatesObject() { $fields = array( @@ -114,8 +78,8 @@ class ObjectsServiceTest extends SQLiteTestCase ), ), ) ); - $expectedObjectsTable = $expected->getTable('objects'); - $expectedFieldsTable = $expected->getTable('fields'); + $expectedObjectsTable = $expected->getTable( 'objects' ); + $expectedFieldsTable = $expected->getTable( 'fields' ); $objectsQueryTable = $this->getConnection()->createQueryTable( 'objects', 'SELECT * FROM objects' ); @@ -126,6 +90,13 @@ class ObjectsServiceTest extends SQLiteTestCase $this->assertTablesEqual( $expectedFieldsTable, $fieldsQueryTable ); } + private function getTime( $context ) + { + return $this->dateTimeProvider + ->getTime( $context ) + ->format( "Y-m-d H:i:s" ); + } + public function testObjectFieldsSet() { $fields = array( @@ -241,8 +212,8 @@ class ObjectsServiceTest extends SQLiteTestCase ), ), ) ); - $expectedObjectsTable = $expected->getTable('objects'); - $expectedFieldsTable = $expected->getTable('fields'); + $expectedObjectsTable = $expected->getTable( 'objects' ); + $expectedFieldsTable = $expected->getTable( 'fields' ); $objectsQueryTable = $this->getConnection()->createQueryTable( 'objects', 'SELECT * FROM objects' ); @@ -333,8 +304,8 @@ class ObjectsServiceTest extends SQLiteTestCase ), ), ) ); - $expectedObjectsTable = $expected->getTable('objects'); - $expectedFieldsTable = $expected->getTable('fields'); + $expectedObjectsTable = $expected->getTable( 'objects' ); + $expectedFieldsTable = $expected->getTable( 'fields' ); $objectsQueryTable = $this->getConnection()->createQueryTable( 'objects', 'SELECT * FROM objects' ); @@ -380,11 +351,11 @@ class ObjectsServiceTest extends SQLiteTestCase $now = $this->getTime( 'objects-service.create' ); $this->objectsService->persist( $fields ); $expected = new ArrayDataSet( array( - 'objects' => array( - array( 'id' => 1, 'created' => $now, 'lastUpdated' => $now ), - array( 'id' => 2, 'created' => $now, 'lastUpdated' => $now ), - array( 'id' => 3, 'created' => $now, 'lastUpdated' => $now ), - array( 'id' => 4, 'created' => $now, 'lastUpdated' => $now ), + 'objects' => array( + array( 'id' => 1, 'created' => $now, 'lastUpdated' => $now ), + array( 'id' => 2, 'created' => $now, 'lastUpdated' => $now ), + array( 'id' => 3, 'created' => $now, 'lastUpdated' => $now ), + array( 'id' => 4, 'created' => $now, 'lastUpdated' => $now ), ), 'fields' => array( array( @@ -488,8 +459,8 @@ class ObjectsServiceTest extends SQLiteTestCase ), ), ) ); - $expectedObjectsTable = $expected->getTable('objects'); - $expectedFieldsTable = $expected->getTable('fields'); + $expectedObjectsTable = $expected->getTable( 'objects' ); + $expectedFieldsTable = $expected->getTable( 'fields' ); $objectsQueryTable = $this->getConnection()->createQueryTable( 'objects', 'SELECT * FROM objects' ); @@ -714,12 +685,12 @@ class ObjectsServiceTest extends SQLiteTestCase public function testItDoesNotStoreObjectsWithTheSameId() { - $fieldsOne = array( + $fieldsOne = array( 'id' => 'https://example.com/notes/1', 'type' => 'Note', 'content' => 'This is a note', - ); - $fieldsTwo = array( + ); + $fieldsTwo = array( 'id' => 'https://example.com/notes/1', 'type' => 'Note', 'content' => 'This is another note', @@ -762,8 +733,8 @@ class ObjectsServiceTest extends SQLiteTestCase ), ), ) ); - $expectedObjectsTable = $expected->getTable('objects'); - $expectedFieldsTable = $expected->getTable('fields'); + $expectedObjectsTable = $expected->getTable( 'objects' ); + $expectedFieldsTable = $expected->getTable( 'fields' ); $objectsQueryTable = $this->getConnection()->createQueryTable( 'objects', 'SELECT * FROM objects' ); @@ -849,8 +820,8 @@ class ObjectsServiceTest extends SQLiteTestCase ), ), ) ); - $expectedObjectsTable = $expected->getTable('objects'); - $expectedFieldsTable = $expected->getTable('fields'); + $expectedObjectsTable = $expected->getTable( 'objects' ); + $expectedFieldsTable = $expected->getTable( 'fields' ); $objectsQueryTable = $this->getConnection()->createQueryTable( 'objects', 'SELECT * FROM objects' ); @@ -953,8 +924,8 @@ class ObjectsServiceTest extends SQLiteTestCase ), ), ) ); - $expectedObjectsTable = $expected->getTable('objects'); - $expectedFieldsTable = $expected->getTable('fields'); + $expectedObjectsTable = $expected->getTable( 'objects' ); + $expectedFieldsTable = $expected->getTable( 'fields' ); $objectsQueryTable = $this->getConnection()->createQueryTable( 'objects', 'SELECT * FROM objects' ); @@ -1054,8 +1025,8 @@ class ObjectsServiceTest extends SQLiteTestCase ), ), ) ); - $expectedObjectsTable = $expected->getTable('objects'); - $expectedFieldsTable = $expected->getTable('fields'); + $expectedObjectsTable = $expected->getTable( 'objects' ); + $expectedFieldsTable = $expected->getTable( 'fields' ); $objectsQueryTable = $this->getConnection()->createQueryTable( 'objects', 'SELECT * FROM objects' ); @@ -1107,8 +1078,8 @@ class ObjectsServiceTest extends SQLiteTestCase ), ), ) ); - $expectedObjectsTable = $expected->getTable('objects'); - $expectedFieldsTable = $expected->getTable('fields'); + $expectedObjectsTable = $expected->getTable( 'objects' ); + $expectedFieldsTable = $expected->getTable( 'fields' ); $objectsQueryTable = $this->getConnection()->createQueryTable( 'objects', 'SELECT * FROM objects' ); @@ -1279,14 +1250,46 @@ class ObjectsServiceTest extends SQLiteTestCase if ( array_key_exists( 'expectedQueryResults', $testCase ) ) { foreach ( $testCase['expectedQueryResults'] as $expectedQueryResult ) { $result = array_map( - function( ActivityPubObject $obj ) { return $obj->asArray(); }, + function ( ActivityPubObject $obj ) { + return $obj->asArray(); + }, $this->objectsService->query( $expectedQueryResult['query'] ) ); $this->assertEquals( $expectedQueryResult['expectedResult'], $result ); - } + } } } } + + protected function setUp() + { + parent::setUp(); + $dbConfig = Setup::createAnnotationMetadataConfiguration( + array( __DIR__ . '/../../src/Entities' ), true + ); + $namingStrategy = new PrefixNamingStrategy( '' ); + $dbConfig->setNamingStrategy( $namingStrategy ); + $dbParams = array( + 'driver' => 'pdo_sqlite', + 'path' => $this->getDbPath(), + ); + $this->entityManager = EntityManager::create( $dbParams, $dbConfig ); + $this->dateTimeProvider = new TestDateTimeProvider( array( + 'objects-service.create' => new DateTime( "12:00" ), + 'objects-service.update' => new DateTime( "12:01" ), + ) ); + $this->httpClient = $this->getMock( Client::class ); + $this->httpClient->method( 'send' ) + ->willReturn( new Response( 404 ) ); + $this->objectsService = new ObjectsService( + $this->entityManager, $this->dateTimeProvider, $this->httpClient + ); + } + + protected function getDataSet() + { + return new ArrayDataSet( array( 'objects' => array(), 'fields' => array() ) ); + } } diff --git a/test/TestConfig/APTestCase.php b/test/TestConfig/APTestCase.php index e0df3f5..f0e578e 100644 --- a/test/TestConfig/APTestCase.php +++ b/test/TestConfig/APTestCase.php @@ -1,12 +1,13 @@ $rows) { + foreach ( $data as $tableName => $rows ) { $columns = []; - if (isset($rows[0])) { - $columns = array_keys($rows[0]); + if ( isset( $rows[0] ) ) { + $columns = array_keys( $rows[0] ); } - $metaData = new \PHPUnit_Extensions_Database_DataSet_DefaultTableMetaData($tableName, $columns); - $table = new \PHPUnit_Extensions_Database_DataSet_DefaultTable($metaData); + $metaData = new \PHPUnit_Extensions_Database_DataSet_DefaultTableMetaData( $tableName, $columns ); + $table = new \PHPUnit_Extensions_Database_DataSet_DefaultTable( $metaData ); - foreach ($rows as $row) { - $table->addRow($row); + foreach ( $rows as $row ) { + $table->addRow( $row ); } $this->tables[$tableName] = $table; } } - protected function createIterator($reverse = false) + public function getTable( $tableName ) { - return new \PHPUnit_Extensions_Database_DataSet_DefaultTableIterator($this->tables, $reverse); - } - - public function getTable($tableName) - { - if (!isset($this->tables[$tableName])) { - throw new InvalidArgumentException("$tableName is not a table in the current database."); + if ( !isset( $this->tables[$tableName] ) ) { + throw new InvalidArgumentException( "$tableName is not a table in the current database." ); } return $this->tables[$tableName]; } + + protected function createIterator( $reverse = false ) + { + return new \PHPUnit_Extensions_Database_DataSet_DefaultTableIterator( $this->tables, $reverse ); + } } diff --git a/test/TestConfig/SQLiteTestCase.php b/test/TestConfig/SQLiteTestCase.php index aeaa6dc..93c5be9 100644 --- a/test/TestConfig/SQLiteTestCase.php +++ b/test/TestConfig/SQLiteTestCase.php @@ -16,36 +16,6 @@ abstract class SQLiteTestCase extends APTestCase private $conn = null; private $dbPath = ''; - protected function setUp() - { - parent::setUp(); - $dbPath = $this->getDbPath(); - if ( file_exists( $dbPath ) ) { - unlink( $dbPath ); - } - $config = ActivityPubConfig::createBuilder() - ->setDbConnectionParams( array( - 'driver' => 'pdo_sqlite', - 'path' => $dbPath, - ) ) - ->build(); - $activityPub = new ActivityPub( $config ); - $activityPub->updateSchema(); - } - - protected function tearDown() - { - parent::tearDown(); - unlink( $this->getDbPath() ); - unset( $this->conn ); - unset( $this->pdo ); - } - - protected function getDbPath() - { - return dirname( __FILE__ ) . '/db.sqlite'; - } - final public function getConnection() { if ( $this->conn === null ) { @@ -57,5 +27,35 @@ abstract class SQLiteTestCase extends APTestCase } return $this->conn; } + + protected function getDbPath() + { + return dirname( __FILE__ ) . '/db.sqlite'; + } + + protected function setUp() + { + parent::setUp(); + $dbPath = $this->getDbPath(); + if ( file_exists( $dbPath ) ) { + unlink( $dbPath ); + } + $config = ActivityPubConfig::createBuilder() + ->setDbConnectionParams( array( + 'driver' => 'pdo_sqlite', + 'path' => $dbPath, + ) ) + ->build(); + $activityPub = new ActivityPub( $config ); + $activityPub->updateSchema(); + } + + protected function tearDown() + { + parent::tearDown(); + unlink( $this->getDbPath() ); + unset( $this->conn ); + unset( $this->pdo ); + } } diff --git a/test/TestUtils/TestActivityPubObject.php b/test/TestUtils/TestActivityPubObject.php index 7a51f4e..5076c35 100644 --- a/test/TestUtils/TestActivityPubObject.php +++ b/test/TestUtils/TestActivityPubObject.php @@ -11,21 +11,39 @@ use DateTime; */ class TestActivityPubObject extends ActivityPubObject { - public static function getDefaultTime() { + private $fixedTime; + + public function __construct( DateTime $time = null ) + { + if ( !$time ) { + $time = self::getDefaultTime(); + } + $this->fixedTime = $time; + parent::__construct( $time ); + } + + public static function getDefaultTime() + { return DateTime::createFromFormat( DateTime::RFC2822, 'Sun, 05 Jan 2014 21:31:40 GMT' ); } - private $fixedTime; - - public function __construct( DateTime $time = null ) + public static function fromArray( array $arr, DateTime $time = null ) { - if ( ! $time ) { + if ( !$time ) { $time = self::getDefaultTime(); } - $this->fixedTime = $time; - parent::__construct( $time ); + $object = new TestActivityPubObject( $time ); + foreach ( $arr as $name => $value ) { + if ( is_array( $value ) ) { + $child = self::fromArray( $value, $time ); + TestField::withObject( $object, $name, $child, $time ); + } else { + TestField::withValue( $object, $name, $value, $time ); + } + } + return $object; } public function addField( Field $field, DateTime $time = null ) @@ -44,22 +62,5 @@ class TestActivityPubObject extends ActivityPubObject { // do not change lastUpdated } - - public static function fromArray( array $arr, DateTime $time = null ) - { - if ( ! $time ) { - $time = self::getDefaultTime(); - } - $object = new TestActivityPubObject( $time ); - foreach ( $arr as $name => $value ) { - if ( is_array( $value ) ) { - $child = self::fromArray( $value, $time ); - TestField::withObject( $object, $name, $child, $time ); - } else { - TestField::withValue( $object, $name, $value, $time ); - } - } - return $object; - } } diff --git a/test/TestUtils/TestDateTimeProvider.php b/test/TestUtils/TestDateTimeProvider.php index c95a7a6..8b2cabe 100644 --- a/test/TestUtils/TestDateTimeProvider.php +++ b/test/TestUtils/TestDateTimeProvider.php @@ -2,8 +2,8 @@ namespace ActivityPub\Test\TestUtils; -use DateTime; use ActivityPub\Utils\DateTimeProvider; +use DateTime; /** * A DateTimeProvider that returns fixed values for create and update times @@ -19,10 +19,10 @@ class TestDateTimeProvider implements DateTimeProvider { $this->context = $context; } - + public function getTime( $context = '' ) { - if ( array_key_exists( $context, $this->context )) { + if ( array_key_exists( $context, $this->context ) ) { return $this->context[$context]; } else { return new DateTime( 'now' ); diff --git a/test/TestUtils/TestField.php b/test/TestUtils/TestField.php index 48d46e9..0e5b876 100644 --- a/test/TestUtils/TestField.php +++ b/test/TestUtils/TestField.php @@ -1,4 +1,5 @@