diff --git a/composer.json b/composer.json index 8f4fb1bb1284ef163e772d4fae1ac5a83da9b885..f759bf4e1b94283975d92d71223e16f5f02f7db6 100755 --- a/composer.json +++ b/composer.json @@ -32,8 +32,8 @@ } }, "require": { - "slim/slim": "^3.10", - "respect/validation": "^1.1", + "slim/slim": "^3.11", + "respect/validation": "^1.1.28", "php-http/curl-client": "^1.7", "m4tthumphrey/php-gitlab-api": "8", "jumbojett/openid-connect-php": "^0.3.0", diff --git a/vendor/kriswallsmith/buzz/.gitattributes b/vendor/kriswallsmith/buzz/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..e993ce46dfaf6ec5ee5a34ec55a9b7fb54daed20 --- /dev/null +++ b/vendor/kriswallsmith/buzz/.gitattributes @@ -0,0 +1,9 @@ +* text=auto + +/examples export-ignore +/tests export-ignore +/.gitignore export-ignore +/.travis.yml export-ignore +/CHANGELOG.md export-ignore +/README.md export-ignore +/phpunit.xml.dist export-ignore diff --git a/vendor/kriswallsmith/buzz/.php_cs b/vendor/kriswallsmith/buzz/.php_cs new file mode 100644 index 0000000000000000000000000000000000000000..82fcf5ae936f4bc4108d52befeceb0a400a7f6d5 --- /dev/null +++ b/vendor/kriswallsmith/buzz/.php_cs @@ -0,0 +1,20 @@ +<?php + +return PhpCsFixer\Config::create() + ->setRules(array( + '@Symfony' => true, + '@Symfony:risky' => true, + 'array_syntax' => array('syntax' => 'short'), + 'protected_to_private' => false, + 'declare_strict_types' => true, + )) + ->setRiskyAllowed(true) + ->setCacheFile((getenv('TRAVIS') ? getenv('HOME') . '/.php-cs-fixer' : __DIR__).'/.php_cs.cache') + ->setUsingCache(true) + ->setFinder( + PhpCsFixer\Finder::create() + ->in(__DIR__) + ->exclude('vendor') + ->name('*.php') + ) +; \ No newline at end of file diff --git a/vendor/kriswallsmith/buzz/.scrutinizer.yml b/vendor/kriswallsmith/buzz/.scrutinizer.yml new file mode 100644 index 0000000000000000000000000000000000000000..d92b5c69b960e5d552ba626768b2aebce3ce71d8 --- /dev/null +++ b/vendor/kriswallsmith/buzz/.scrutinizer.yml @@ -0,0 +1,9 @@ +filter: + excluded_paths: [vendor/*, tests/*, lib/Middleware/DigestAuthMiddleware.php] + +checks: + php: + code_rating: true + duplication: true +tools: + external_code_coverage: true diff --git a/vendor/kriswallsmith/buzz/.styleci.yml b/vendor/kriswallsmith/buzz/.styleci.yml new file mode 100644 index 0000000000000000000000000000000000000000..f97f9b983d4c9dbbba4650c863f8a904e7819578 --- /dev/null +++ b/vendor/kriswallsmith/buzz/.styleci.yml @@ -0,0 +1,11 @@ +preset: symfony + +finder: + exclude: + - "vendor" + +enabled: + - short_array_syntax + +disabled: + - phpdoc_annotation_without_dot # This is still buggy: https://github.com/symfony/symfony/pull/19198 \ No newline at end of file diff --git a/vendor/kriswallsmith/buzz/LICENSE b/vendor/kriswallsmith/buzz/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..e234f8007a80c63ecd95faf6b52fedab2091a7e6 --- /dev/null +++ b/vendor/kriswallsmith/buzz/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010-2011 Kris Wallsmith + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/kriswallsmith/buzz/composer.json b/vendor/kriswallsmith/buzz/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..f4b31232b2ed91d7040eeb7579a9a5313f6e8e37 --- /dev/null +++ b/vendor/kriswallsmith/buzz/composer.json @@ -0,0 +1,59 @@ +{ + "name": "kriswallsmith/buzz", + "description": "Lightweight HTTP client", + "keywords": ["http client", "curl"], + "homepage": "https://github.com/kriswallsmith/Buzz", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Kris Wallsmith", + "email": "kris.wallsmith@gmail.com", + "homepage": "http://kriswallsmith.net/" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "http://tnyholm.se/" + } + ], + "require": { + "php": "^7.1", + "psr/http-message": "^1.0", + "psr/http-client": "^0.1", + "php-http/httplug": "^1.1", + "nyholm/psr7": "^1.0", + "symfony/options-resolver": "^3.4 || ^4.0", + "psr/http-factory": "^1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.11", + "php-http/client-integration-tests": "^0.6.2", + "phpunit/phpunit": "^6.5.7", + "psr/log": "^1.0", + "symfony/phpunit-bridge": "^4.0" + }, + "conflict": { + "http-interop/http-factory": "<0.4.1" + }, + "provide": { + "php-http/client-implementation": "1.0" + }, + "suggest": { + "ext-curl": "*" + }, + "autoload": { + "psr-4": { + "Buzz\\": "lib" + } + }, + "autoload-dev": { + "psr-4": { + "Buzz\\Test\\": "tests" + } + }, + "scripts": { + "test": "vendor/bin/simple-phpunit", + "test-ci": "vendor/bin/simple-phpunit --coverage-text --coverage-clover=build/coverage.xml" + } +} diff --git a/vendor/kriswallsmith/buzz/doc/client.md b/vendor/kriswallsmith/buzz/doc/client.md new file mode 100644 index 0000000000000000000000000000000000000000..4a03fcdfc1358664b07fcabac9742eece1cd80dc --- /dev/null +++ b/vendor/kriswallsmith/buzz/doc/client.md @@ -0,0 +1,92 @@ +[<-- Index](/doc/index.md) + +# Clients + +Clients are the low-level objects to send HTTP requests. All clients are minimalistic both in +features and flexibility. You may give the client some default configuration and some additional +configuration each time you send a request. + +There are 3 clients: `FileGetContents`, `Curl` and `MultiCurl`. + +```php +$request = new PSR7Request('GET', 'https://example.com'); + +$client = new Buzz\Client\FileGetContents(['allow_redirects' => true], new Psr17ResponseFactory()); +$response = $client->send($request, ['timeout' => 4]); +``` + +## Configuration + +Not all configuration works will all clients. If there is any client specific configuration it +will be noted below. + +#### allow_redirects + +Type: boolean<br> +Default: `false` + +Should the client follow HTTP redirects or not. + +#### callback + +Type: callable<br> +Default: `function() {}`<br> +*Only for MultiCurl* + +A callback function that is called after a request has been sent. + +```php +$callback = function(RequestInterface $request, ResponseInterface $response = null, ClientException $exception = null) { + // Process the response +}; +$request = new PSR7Request('GET', 'https://example.com'); +$client->sendAsyncRequest($request, array('callback' => $callback)); +``` + +#### curl + +Type: array<br> +Default: `[]`<br> +*Only for Curl and MultiCurl* + +An array with Curl options. + +```php +$request = new PSR7Request('GET', 'https://example.com'); +$client->sendAsyncRequest($request, array('curl' => [ + CURLOPT_FAILONERROR => false, +])); +``` + +#### max_redirects + +Type: integer<br> +Default: `5` + +The maximum number of redirects to follow. Note that this will have no effect unless you set +`'allow_redirects' => true`. + +#### proxy + +Type: string<br> +Default: `null` + +A proxy server to use when sending requests. + +#### timeout + +Type: integer<br> +Default: `30` + +The time to wait before interrupt the request. + +#### verify + +Type: boolean<br> +Default: `true` + +If SSL protocols should verified. + +--- + +Continue reading about [Middlewares](/doc/middlewares.md). diff --git a/vendor/kriswallsmith/buzz/doc/index.md b/vendor/kriswallsmith/buzz/doc/index.md new file mode 100644 index 0000000000000000000000000000000000000000..1750747e484d4629e4ac211b1b8e656bbe368826 --- /dev/null +++ b/vendor/kriswallsmith/buzz/doc/index.md @@ -0,0 +1,90 @@ +# Buzz documentation + +Buzz is a simple and lightweight HTTP client which is easy to use. This page is +the index of the documentation. Please use the table of contents below to start +reading. + +* [Browser](#browser) +* [Submit forms](#submit-a-form) +* [Client](/doc/client.md) +* [Middlewares](/doc/middlewares.md) +* [Symfony Bundle](/doc/symfony.md) + + +## Browser + +The Browser is the high-level object to send HTTP requests. Main focus is on simplicity. + +When a `Browser` in constructed you have to select a [Client](/doc/client.md) to use. The +`FileGetContents` client is used by default. See example of how +to use the Bowser: + +```php +$client = new Buzz\Client\FileGetContents([], new Psr17ResponseFactory()); +$browser = new Buzz\Browser($client, new Psr17RequestFactory()); + +$response = $browser->get('https://example.com'); +$response = $browser->get('https://example.com', ['User-Agent'=>'Buzz']); +$response = $browser->post('https://example.com', ['User-Agent'=>'Buzz'], 'http-post-body'); + +$response = $browser->head('https://example.com'); +$response = $browser->patch('https://example.com'); +$response = $browser->put('https://example.com'); +$response = $browser->delete('https://example.com'); + + +$response = $browser->request('GET', 'https://example.com'); +``` + +You do also have a function to send PSR-7 requests. + +```php +$request = new PSR7Request('GET', 'https://google.com/foo'); +$response = $browser->sendRequest($request) +``` + +## Submit a form + +With Buzz you have built in support for posing forms. You could of course create your own PSR-7 request and posting it +as you normally would. But it might be easier to use the `Browser::submit()` function or the `FormRequestBuilder`. + +Below is an example how to use `Browser::submit()` to upload a file. + +```php +$browser->submitForm('http://example.com/foo', [ + 'user' => 'Kris Wallsmith', + 'image' => [ + 'path'=>'/path/to/image.jpg' + ], +]); +``` + +```php +$browser->submitForm('http://example.com/foo', [ + 'user[name]' => 'Kris Wallsmith', + 'user[image]' => [ + 'path'=>'/path/to/image.jpg', + 'filename' => 'my-image.jpg', + 'contentType' => 'image/jpg', + ], +]); +``` + +### Using the FormRequestBuilder + +If you have a large from or you want to build your request in a structured way you may use the `FormRequestBuilder`. + +```php +use Buzz\Message\FormRequestBuilder; + +$builder = new FormRequestBuilder(); +$builder->addField('user[name]', 'Kris Wallsmith'); +$builder->addFile('user[image]', '/path/to/image.jpg', 'image/jpg', 'my-image.jpg'); +$builder->addFile('cover-image', '/path/to/cover.jpg'); + +$browser->submitForm('http://example.com/foo', $builder->build()); +``` + +--- + +Continue reading about [Clients](/doc/client.md). diff --git a/vendor/kriswallsmith/buzz/doc/middlewares.md b/vendor/kriswallsmith/buzz/doc/middlewares.md new file mode 100644 index 0000000000000000000000000000000000000000..1b75ea3fd27fc2c350695fea2583b51b0a8bcef5 --- /dev/null +++ b/vendor/kriswallsmith/buzz/doc/middlewares.md @@ -0,0 +1,92 @@ +[<-- Index](/doc/index.md) + +# Buzz middlewares + +If you want to modify the request or response somehow, a middleware is the way to +go. Every time you send a request with the `Browser` it will run through all the +middlewares. The order of the middlewares is important. The first middleware added +to the `Browser` will be the first one that is executed when handling the request and +the last one to be executed when handling the response. + +``` +Request ---> Middleware1 ---> Middleware2 ---> HttpClient ---- + | (processing call) +Response <--- Middleware1 <--- Middleware2 <--- HttpClient <--- +``` +## Creating a middleware + +You are free to create any custom middleware you want. It is super simple to do so. +Let's look at the example when we create a middleware for adding the User-Agent +request header. + +First we need to create a class that implements `Buzz\Middleware\MiddlewareInterface` + +```php +<?php + +use Buzz\Middleware\MiddlewareInterface; + +class UserAgentMiddleware implements MiddlewareInterface +{ + // ... +``` + +The interface has two functions; `handleRequest` and `handleResponse`. The last +parameter to these functions is a `callable`. That callable is actually the next +middleware in the chain. It is **very important** that you end your function by +returning the the result when calling that callable. If you forget about that, +then no request will be sent. + +Let's look at an example implementation of `handleRequest`: + +```php +public function handleRequest(RequestInterface $request, callable $next) +{ + $request = $request->withAddedHeader('User-Agent', 'Buzz'); + + return $next($request); +} +``` + +Note that PSR-7 requests and responses are immutable. That is why we do +`$request = $request->with...`. + +Sine this middleware does not need to modify the response we just let the +`handleResponse` function to be empty like: + + ```php + public function handleResponse(RequestInterface $request, ResponseInterface $response, callable $next) + { + return $next($request, $response); + } + ``` + +### The full example + +```php +<?php + +use Buzz\Middleware\MiddlewareInterface; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +class UserAgentMiddleware implements MiddlewareInterface +{ + public function handleRequest(RequestInterface $request, callable $next) + { + $request = $request->withAddedHeader('User-Agent', 'Buzz'); + + return $next($request); + } + + public function handleResponse(RequestInterface $request, ResponseInterface $response, callable $next) + { + return $next($request, $response); + } +} +``` + + +--- + +Continue reading about [Symfony integration](/doc/symfony.md). \ No newline at end of file diff --git a/vendor/kriswallsmith/buzz/doc/symfony.md b/vendor/kriswallsmith/buzz/doc/symfony.md new file mode 100644 index 0000000000000000000000000000000000000000..5e8988406fc832a540045778fd47cc4ecb9b8529 --- /dev/null +++ b/vendor/kriswallsmith/buzz/doc/symfony.md @@ -0,0 +1,48 @@ +[<-- Index](/doc/index.md) + +# Symfony integration + +Symfony is a great PHP framework and of course should we have some nice integration +with it. We have provided a flex recipe in the [contrib repository](https://github.com/symfony/recipes-contrib) +which will register the `Browser` and clients as services. But of course, you want +more! You want a proper bundle. + +Buzz is compatible with HTTPlug which means that we can use all the greatness from +the [HTTPlugBundle](https://github.com/php-http/httplugbundle). + +## Install + +``` +composer require php-http/httplug-bundle +``` + +## Configure + +``` +# config/services.yaml +# This is done by the flex recipe +services: + Buzz\Browser: + calls: + - ['addMiddleware', ['@buzz.middleware.content_length']] + + buzz.middleware.content_length: + class: Buzz\Middleware\ContentLengthMiddleware +``` + +``` +# config/httplug.yaml +httplug: + clients: + my_buzz: + service: 'Buzz\Browser' +``` + +You will now have a service named `httplug.client.my_buzz`. You can of course add +plugins method clients and whatever you want according to the +[HTTPlug documentation](http://docs.php-http.org/en/latest/integrations/symfony-bundle.html). + + +--- + +Go back to [index](/doc/index.md). \ No newline at end of file diff --git a/vendor/kriswallsmith/buzz/lib/Browser.php b/vendor/kriswallsmith/buzz/lib/Browser.php new file mode 100644 index 0000000000000000000000000000000000000000..73a18c858981f1f0d9686fefd4af8b161e47fd2b --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Browser.php @@ -0,0 +1,278 @@ +<?php + +declare(strict_types=1); + +namespace Buzz; + +use Buzz\Client\BuzzClientInterface; +use Buzz\Client\FileGetContents; +use Buzz\Exception\ClientException; +use Buzz\Exception\InvalidArgumentException; +use Buzz\Exception\LogicException; +use Buzz\Middleware\MiddlewareInterface; +use Http\Message\RequestFactory; +use Nyholm\Psr7\Factory\Psr17Factory; +use Psr\Http\Message\RequestFactoryInterface; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +class Browser implements BuzzClientInterface +{ + /** @var BuzzClientInterface */ + private $client; + + /** @var RequestFactoryInterface|RequestFactory */ + private $requestFactory; + + /** + * @var MiddlewareInterface[] + */ + private $middlewares = []; + + /** @var RequestInterface */ + private $lastRequest; + + /** @var ResponseInterface */ + private $lastResponse; + + /** + * @param BuzzClientInterface|null $client + * @param RequestFactoryInterface|RequestFactory|null $requestFactory + */ + public function __construct(BuzzClientInterface $client = null, $requestFactory = null) + { + if (null === $client) { + @trigger_error('Not passing a BuzzClientInterface to Browser constructor is deprecated.', E_USER_DEPRECATED); + $client = new FileGetContents(); + } + + if (null === $requestFactory) { + @trigger_error('Not passing a RequestFactory to Browser constructor is deprecated.', E_USER_DEPRECATED); + $requestFactory = new Psr17Factory(); + } elseif (!$requestFactory instanceof RequestFactoryInterface && !$requestFactory instanceof RequestFactory) { + throw new InvalidArgumentException('$requestFactory not a valid RequestFactory'); + } + + $this->client = $client; + $this->requestFactory = $requestFactory; + } + + public function get(string $url, array $headers = []): ResponseInterface + { + return $this->request('GET', $url, $headers); + } + + public function post(string $url, array $headers = [], string $body = ''): ResponseInterface + { + return $this->request('POST', $url, $headers, $body); + } + + public function head(string $url, array $headers = []): ResponseInterface + { + return $this->request('HEAD', $url, $headers); + } + + public function patch(string $url, array $headers = [], string $body = ''): ResponseInterface + { + return $this->request('PATCH', $url, $headers, $body); + } + + public function put(string $url, array $headers = [], string $body = ''): ResponseInterface + { + return $this->request('PUT', $url, $headers, $body); + } + + public function delete(string $url, array $headers = [], string $body = ''): ResponseInterface + { + return $this->request('DELETE', $url, $headers, $body); + } + + /** + * Sends a request. + * + * @param string $method The request method to use + * @param string $url The URL to call + * @param array $headers An array of request headers + * @param string $body The request content + * + * @return ResponseInterface The response object + */ + public function request(string $method, string $url, array $headers = [], string $body = ''): ResponseInterface + { + $request = $this->createRequest($method, $url, $headers, $body); + + return $this->sendRequest($request); + } + + /** + * Submit a form. + * + * @throws ClientException + * @throws LogicException + * @throws InvalidArgumentException + */ + public function submitForm(string $url, array $fields, string $method = 'POST', array $headers = []): ResponseInterface + { + $body = []; + $files = ''; + $boundary = uniqid('', true); + foreach ($fields as $name => $field) { + if (!isset($field['path'])) { + $body[$name] = $field; + } else { + // This is a file + $fileContent = file_get_contents($field['path']); + $files .= $this->prepareMultipart($name, $fileContent, $boundary, $field); + } + } + + if (empty($files)) { + $headers['Content-Type'] = 'application/x-www-form-urlencoded'; + $body = http_build_query($body); + } else { + $headers['Content-Type'] = 'multipart/form-data; boundary="'.$boundary.'"'; + + foreach ($body as $name => $value) { + $files .= $this->prepareMultipart($name, $value, $boundary); + } + $body = "$files--{$boundary}--\r\n"; + } + + $request = $this->createRequest($method, $url, $headers, $body); + + return $this->sendRequest($request); + } + + /** + * Send a PSR7 request. + * + * @throws ClientException + * @throws LogicException + * @throws InvalidArgumentException + */ + public function sendRequest(RequestInterface $request, array $options = []): ResponseInterface + { + $chain = $this->createMiddlewareChain($this->middlewares, function (RequestInterface $request, callable $responseChain) use ($options) { + $response = $this->client->sendRequest($request, $options); + $responseChain($request, $response); + }, function (RequestInterface $request, ResponseInterface $response) { + $this->lastRequest = $request; + $this->lastResponse = $response; + }); + + // Call the chain + $chain($request); + + return $this->lastResponse; + } + + /** + * @param MiddlewareInterface[] $middlewares + * @param callable $requestChainLast + * @param callable $responseChainLast + * + * @return callable + */ + private function createMiddlewareChain(array $middlewares, callable $requestChainLast, callable $responseChainLast): callable + { + $responseChainNext = $responseChainLast; + + // Build response chain + /** @var MiddlewareInterface $middleware */ + foreach ($middlewares as $middleware) { + $lastCallable = function (RequestInterface $request, ResponseInterface $response) use ($middleware, $responseChainNext) { + return $middleware->handleResponse($request, $response, $responseChainNext); + }; + + $responseChainNext = $lastCallable; + } + + $requestChainLast = function (RequestInterface $request) use ($requestChainLast, $responseChainNext) { + // Send the actual request and get the response + $requestChainLast($request, $responseChainNext); + }; + + $middlewares = array_reverse($middlewares); + + // Build request chain + $requestChainNext = $requestChainLast; + /** @var MiddlewareInterface $middleware */ + foreach ($middlewares as $middleware) { + $lastCallable = function (RequestInterface $request) use ($middleware, $requestChainNext) { + return $middleware->handleRequest($request, $requestChainNext); + }; + + $requestChainNext = $lastCallable; + } + + return $requestChainNext; + } + + public function getLastRequest(): ?RequestInterface + { + return $this->lastRequest; + } + + public function getLastResponse(): ?ResponseInterface + { + return $this->lastResponse; + } + + public function getClient(): BuzzClientInterface + { + return $this->client; + } + + /** + * Add a new middleware to the stack. + * + * @param MiddlewareInterface $middleware + */ + public function addMiddleware(MiddlewareInterface $middleware): void + { + $this->middlewares[] = $middleware; + } + + private function prepareMultipart(string $name, string $content, string $boundary, array $data = []): string + { + $output = ''; + $fileHeaders = []; + + // Set a default content-disposition header + $fileHeaders['Content-Disposition'] = sprintf('form-data; name="%s"', $name); + if (isset($data['filename'])) { + $fileHeaders['Content-Disposition'] .= sprintf('; filename="%s"', $data['filename']); + } + + // Set a default content-length header + if ($length = \strlen($content)) { + $fileHeaders['Content-Length'] = (string) $length; + } + + if (isset($data['contentType'])) { + $fileHeaders['Content-Type'] = $data['contentType']; + } + + // Add start + $output .= "--$boundary\r\n"; + foreach ($fileHeaders as $key => $value) { + $output .= sprintf("%s: %s\r\n", $key, $value); + } + $output .= "\r\n"; + $output .= $content; + $output .= "\r\n"; + + return $output; + } + + protected function createRequest(string $method, string $url, array $headers, $body): RequestInterface + { + $request = $this->requestFactory->createRequest($method, $url); + $request->getBody()->write($body); + foreach ($headers as $name => $value) { + $request = $request->withAddedHeader($name, $value); + } + + return $request; + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Client/AbstractClient.php b/vendor/kriswallsmith/buzz/lib/Client/AbstractClient.php new file mode 100644 index 0000000000000000000000000000000000000000..ae789f341fe3c91034c93e01bd61ee2cc96c93eb --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Client/AbstractClient.php @@ -0,0 +1,101 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Client; + +use Buzz\Configuration\ParameterBag; +use Buzz\Exception\InvalidArgumentException; +use Http\Message\ResponseFactory; +use Nyholm\Psr7\Factory\Psr17Factory; +use Psr\Http\Message\ResponseFactoryInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; + +abstract class AbstractClient +{ + /** + * @var OptionsResolver + */ + private $optionsResolver; + + /** + * @var ParameterBag + */ + private $options; + + /** + * @var ResponseFactoryInterface|ResponseFactory + */ + protected $responseFactory; + + public function __construct(array $options = [], $responseFactory = null) + { + $this->options = new ParameterBag(); + $this->options = $this->doValidateOptions($options); + if (null === $responseFactory) { + @trigger_error('Not passing a ResponseFactory to Buzz client constructor is deprecated.', E_USER_DEPRECATED); + $responseFactory = new Psr17Factory(); + } elseif (!$responseFactory instanceof ResponseFactoryInterface && !$responseFactory instanceof ResponseFactory) { + throw new InvalidArgumentException('$responseFactory not a valid ResponseFactory'); + } + $this->responseFactory = $responseFactory; + } + + protected function getOptionsResolver(): OptionsResolver + { + if (null !== $this->optionsResolver) { + return $this->optionsResolver; + } + + $this->optionsResolver = new OptionsResolver(); + $this->configureOptions($this->optionsResolver); + + return $this->optionsResolver; + } + + /** + * Validate a set of options and return a new and shiny ParameterBag. + */ + protected function validateOptions(array $options = []): ParameterBag + { + if (empty($options)) { + return $this->options; + } + + return $this->doValidateOptions($options); + } + + /** + * Validate a set of options and return a new and shiny ParameterBag. + */ + private function doValidateOptions(array $options = []): ParameterBag + { + $parameterBag = $this->options->add($options); + + try { + $parameters = $this->getOptionsResolver()->resolve($parameterBag->all()); + } catch (\Throwable $e) { + // Wrap any errors. + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + + return new ParameterBag($parameters); + } + + protected function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'allow_redirects' => false, + 'max_redirects' => 5, + 'timeout' => 30, + 'verify' => true, + 'proxy' => null, + ]); + + $resolver->setAllowedTypes('allow_redirects', 'boolean'); + $resolver->setAllowedTypes('verify', 'boolean'); + $resolver->setAllowedTypes('max_redirects', 'integer'); + $resolver->setAllowedTypes('timeout', ['integer', 'float']); + $resolver->setAllowedTypes('proxy', ['null', 'string']); + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Client/AbstractCurl.php b/vendor/kriswallsmith/buzz/lib/Client/AbstractCurl.php new file mode 100644 index 0000000000000000000000000000000000000000..596b446ee748e9abcae9c3ca9931a3a743cf8caa --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Client/AbstractCurl.php @@ -0,0 +1,247 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Client; + +use Buzz\Configuration\ParameterBag; +use Buzz\Message\HeaderConverter; +use Buzz\Exception\ClientException; +use Buzz\Exception\NetworkException; +use Buzz\Exception\RequestException; +use Buzz\Message\ResponseBuilder; +use Psr\Http\Message\RequestInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; + +/** + * Base client class with helpers for working with cURL. + */ +abstract class AbstractCurl extends AbstractClient +{ + private $handles = []; + + private $maxHandles = 5; + + protected function configureOptions(OptionsResolver $resolver): void + { + parent::configureOptions($resolver); + + $resolver->setDefault('curl', []); + $resolver->setAllowedTypes('curl', ['array']); + } + + /** + * Creates a new cURL resource. + * + * @return resource A new cURL resource + * + * @throws ClientException If unable to create a cURL resource + */ + protected function createHandle() + { + $curl = $this->handles ? array_pop($this->handles) : curl_init(); + if (false === $curl) { + throw new ClientException('Unable to create a new cURL handle'); + } + + return $curl; + } + + /** + * Release a cUrl resource. This function is from Guzzle. + * + * @param resource $curl + */ + protected function releaseHandle($curl): void + { + if (\count($this->handles) >= $this->maxHandles) { + curl_close($curl); + } else { + // Remove all callback functions as they can hold onto references + // and are not cleaned up by curl_reset. Using curl_setopt_array + // does not work for some reason, so removing each one + // individually. + curl_setopt($curl, CURLOPT_HEADERFUNCTION, null); + curl_setopt($curl, CURLOPT_READFUNCTION, null); + curl_setopt($curl, CURLOPT_WRITEFUNCTION, null); + curl_setopt($curl, CURLOPT_PROGRESSFUNCTION, null); + curl_reset($curl); + $this->handles[] = $curl; + } + } + + /** + * Prepares a cURL resource to send a request. + * + * @param resource $curl + * @param RequestInterface $request + * @param ParameterBag $options + * + * @return ResponseBuilder + */ + protected function prepare($curl, RequestInterface $request, ParameterBag $options): ResponseBuilder + { + if (\defined('CURLOPT_PROTOCOLS')) { + curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + curl_setopt($curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + } + + curl_setopt($curl, CURLOPT_HEADER, false); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, false); + curl_setopt($curl, CURLOPT_FAILONERROR, false); + + $this->setOptionsFromParameterBag($curl, $options); + $this->setOptionsFromRequest($curl, $request); + + $responseBuilder = new ResponseBuilder($this->responseFactory); + curl_setopt($curl, CURLOPT_HEADERFUNCTION, function ($ch, $data) use ($responseBuilder) { + $str = trim($data); + if ('' !== $str) { + if (0 === strpos(strtolower($str), 'http/')) { + $responseBuilder->setStatus($str); + } else { + $responseBuilder->addHeader($str); + } + } + + return \strlen($data); + }); + + curl_setopt($curl, CURLOPT_WRITEFUNCTION, function ($ch, $data) use ($responseBuilder) { + return $responseBuilder->writeBody($data); + }); + + // apply additional options + curl_setopt_array($curl, $options->get('curl')); + + return $responseBuilder; + } + + /** + * Sets options on a cURL resource based on a request. + * + * @param resource $curl A cURL resource + * @param RequestInterface $request A request object + */ + private function setOptionsFromRequest($curl, RequestInterface $request): void + { + $options = [ + CURLOPT_CUSTOMREQUEST => $request->getMethod(), + CURLOPT_URL => $request->getUri()->__toString(), + CURLOPT_HTTPHEADER => HeaderConverter::toBuzzHeaders($request->getHeaders()), + ]; + + if (0 !== $version = $this->getProtocolVersion($request)) { + $options[CURLOPT_HTTP_VERSION] = $version; + } + + if ($request->getUri()->getUserInfo()) { + $options[CURLOPT_USERPWD] = $request->getUri()->getUserInfo(); + } + + switch (strtoupper($request->getMethod())) { + case 'HEAD': + $options[CURLOPT_NOBODY] = true; + + break; + + case 'GET': + $options[CURLOPT_HTTPGET] = true; + + break; + + case 'POST': + case 'PUT': + case 'DELETE': + case 'PATCH': + case 'OPTIONS': + $body = $request->getBody(); + $bodySize = $body->getSize(); + if (0 !== $bodySize) { + if ($body->isSeekable()) { + $body->rewind(); + } + + // Message has non empty body. + if (null === $bodySize || $bodySize > 1024 * 1024) { + // Avoid full loading large or unknown size body into memory + $options[CURLOPT_UPLOAD] = true; + if (null !== $bodySize) { + $options[CURLOPT_INFILESIZE] = $bodySize; + } + $options[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) { + return $body->read($length); + }; + } else { + // Small body can be loaded into memory + $options[CURLOPT_POSTFIELDS] = (string) $body; + } + } + } + + curl_setopt_array($curl, $options); + } + + /** + * @param resource $curl + * @param ParameterBag $options + */ + private function setOptionsFromParameterBag($curl, ParameterBag $options): void + { + $timeout = $options->get('timeout'); + $proxy = $options->get('proxy'); + if ($proxy) { + curl_setopt($curl, CURLOPT_PROXY, $proxy); + } + + $canFollow = !ini_get('safe_mode') && !ini_get('open_basedir') && $options->get('allow_redirects'); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, $canFollow); + curl_setopt($curl, CURLOPT_MAXREDIRS, $canFollow ? $options->get('max_redirects') : 0); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $options->get('verify') ? 1 : 0); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, $options->get('verify') ? 2 : 0); + curl_setopt($curl, CURLOPT_TIMEOUT, $timeout); + } + + /** + * @param RequestInterface $request + * @param int $errno + * @param resource $curl + * + * @throws NetworkException + * @throws RequestException + */ + protected function parseError(RequestInterface $request, int $errno, $curl): void + { + switch ($errno) { + case CURLE_OK: + // All OK, create a response object + break; + case CURLE_COULDNT_RESOLVE_PROXY: + case CURLE_COULDNT_RESOLVE_HOST: + case CURLE_COULDNT_CONNECT: + case CURLE_OPERATION_TIMEOUTED: + case CURLE_SSL_CONNECT_ERROR: + throw new NetworkException($request, curl_error($curl), $errno); + default: + throw new RequestException($request, curl_error($curl), $errno); + } + } + + private function getProtocolVersion(RequestInterface $request): int + { + switch ($request->getProtocolVersion()) { + case '1.0': + return CURL_HTTP_VERSION_1_0; + case '1.1': + return CURL_HTTP_VERSION_1_1; + case '2.0': + if (\defined('CURL_HTTP_VERSION_2_0')) { + return CURL_HTTP_VERSION_2_0; + } + + throw new \UnexpectedValueException('libcurl 7.33 needed for HTTP 2.0 support'); + default: + return 0; + } + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Client/BatchClientInterface.php b/vendor/kriswallsmith/buzz/lib/Client/BatchClientInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..0cb09a36f46e803fd64b6455a6afd16d091ebc19 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Client/BatchClientInterface.php @@ -0,0 +1,36 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Client; + +use Buzz\Exception\ClientException; +use Psr\Http\Message\RequestInterface; + +/** + * A client capable of running batches of requests. + * + * The Countable implementation should return the number of queued requests. + */ +interface BatchClientInterface extends \Countable +{ + /** + * @param RequestInterface $request + * @param array $options + */ + public function sendAsyncRequest(RequestInterface $request, array $options = []): void; + + /** + * Processes all queued requests. + * + * @throws ClientException If something goes wrong + */ + public function flush(): void; + + /** + * Processes zero or more queued requests. + * + * @throws ClientException If something goes wrong + */ + public function proceed(): void; +} diff --git a/vendor/kriswallsmith/buzz/lib/Client/BuzzClientInterface.php b/vendor/kriswallsmith/buzz/lib/Client/BuzzClientInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..21b4a7615a7a1e403e2088be6f23e2593ad9cc08 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Client/BuzzClientInterface.php @@ -0,0 +1,21 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Client; + +use Http\Client\HttpClient; +use Psr\Http\Client\ClientInterface; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +/** + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + */ +interface BuzzClientInterface extends ClientInterface, HttpClient +{ + /** + * {@inheritdoc} + */ + public function sendRequest(RequestInterface $request, array $options = []): ResponseInterface; +} diff --git a/vendor/kriswallsmith/buzz/lib/Client/Curl.php b/vendor/kriswallsmith/buzz/lib/Client/Curl.php new file mode 100644 index 0000000000000000000000000000000000000000..fd246e646f7b6bc9ed9c27cf5a5d5ed3641b0f11 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Client/Curl.php @@ -0,0 +1,30 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Client; + +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +/** + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + */ +class Curl extends AbstractCurl implements BuzzClientInterface +{ + public function sendRequest(RequestInterface $request, array $options = []): ResponseInterface + { + $options = $this->validateOptions($options); + $curl = $this->createHandle(); + $responseBuilder = $this->prepare($curl, $request, $options); + + try { + curl_exec($curl); + $this->parseError($request, curl_errno($curl), $curl); + } finally { + $this->releaseHandle($curl); + } + + return $responseBuilder->getResponse(); + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Client/FileGetContents.php b/vendor/kriswallsmith/buzz/lib/Client/FileGetContents.php new file mode 100644 index 0000000000000000000000000000000000000000..fb16c2611a480e731ca4c114187a303119a6249f --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Client/FileGetContents.php @@ -0,0 +1,90 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Client; + +use Buzz\Configuration\ParameterBag; +use Buzz\Message\HeaderConverter; +use Buzz\Exception\NetworkException; +use Buzz\Message\ResponseBuilder; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +class FileGetContents extends AbstractClient implements BuzzClientInterface +{ + public function sendRequest(RequestInterface $request, array $options = []): ResponseInterface + { + $options = $this->validateOptions($options); + $context = stream_context_create($this->getStreamContextArray($request, $options)); + + $level = error_reporting(0); + $content = file_get_contents($request->getUri()->__toString(), false, $context); + error_reporting($level); + if (false === $content) { + $error = error_get_last(); + + throw new NetworkException($request, $error['message']); + } + + $requestBuilder = new ResponseBuilder($this->responseFactory); + $requestBuilder->parseHttpHeaders($this->filterHeaders((array) $http_response_header)); + $requestBuilder->writeBody($content); + + return $requestBuilder->getResponse(); + } + + /** + * Converts a request into an array for stream_context_create(). + * + * @param RequestInterface $request A request object + * @param ParameterBag $options + * + * @return array An array for stream_context_create() + */ + protected function getStreamContextArray(RequestInterface $request, ParameterBag $options): array + { + $headers = $request->getHeaders(); + unset($headers['Host']); + $context = [ + 'http' => [ + // values from the request + 'method' => $request->getMethod(), + 'header' => implode("\r\n", HeaderConverter::toBuzzHeaders($headers)), + 'content' => $request->getBody()->__toString(), + 'protocol_version' => $request->getProtocolVersion(), + + // values from the current client + 'ignore_errors' => true, + 'follow_location' => $options->get('allow_redirects') && $options->get('max_redirects') > 0, + 'max_redirects' => $options->get('max_redirects') + 1, + 'timeout' => $options->get('timeout'), + ], + 'ssl' => [ + 'verify_peer' => $options->get('verify'), + 'verify_host' => $options->get('verify'), + ], + ]; + + if (null !== $options->get('proxy')) { + $context['http']['proxy'] = $options->get('proxy'); + $context['http']['request_fulluri'] = true; + } + + return $context; + } + + private function filterHeaders(array $headers): array + { + $filtered = []; + foreach ($headers as $header) { + if (0 === stripos($header, 'http/')) { + $filtered = []; + } + + $filtered[] = $header; + } + + return $filtered; + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Client/MultiCurl.php b/vendor/kriswallsmith/buzz/lib/Client/MultiCurl.php new file mode 100644 index 0000000000000000000000000000000000000000..9d3a468a671fdbf100b4fa6c3d49c0dfa5c2b8bf --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Client/MultiCurl.php @@ -0,0 +1,162 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Client; + +use Buzz\Configuration\ParameterBag; +use Buzz\Exception\ExceptionInterface; +use Buzz\Exception\ClientException; +use Buzz\Message\ResponseBuilder; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; + +class MultiCurl extends AbstractCurl implements BatchClientInterface, BuzzClientInterface +{ + private $queue = []; + + private $curlm; + + /** + * Populates the supplied response with the response for the supplied request. + * + * The array of options will be passed to curl_setopt_array(). + * + * If a "callback" option is supplied, its value will be called when the + * request completes. The callable should have the following signature: + * + * $callback = function($request, $response, $exception) { + * if (!$exception) { + * // success + * } else { + * // error ($error is one of the CURLE_* constants) + * } + * }; + */ + public function sendAsyncRequest(RequestInterface $request, array $options = []): void + { + $options = $this->validateOptions($options); + + $this->queue[] = [$request, $options]; + } + + public function sendRequest(RequestInterface $request, array $options = []): ResponseInterface + { + $options = $this->validateOptions($options); + $originalCallback = $options->get('callback'); + $responseToReturn = null; + $options = $options->add(['callback' => function (RequestInterface $request, ResponseInterface $response = null, ClientException $e = null) use (&$responseToReturn, $originalCallback) { + $responseToReturn = $response; + $originalCallback($request, $response, $e); + }]); + + $this->queue[] = [$request, $options]; + $this->flush(); + + return $responseToReturn; + } + + protected function configureOptions(OptionsResolver $resolver): void + { + parent::configureOptions($resolver); + + $resolver->setDefault('callback', function (RequestInterface $request, ResponseInterface $response = null, ClientException $e = null) { + }); + $resolver->setAllowedTypes('callback', 'callable'); + } + + public function count(): int + { + return \count($this->queue); + } + + /** + * @throws ClientException + */ + public function flush(): void + { + while (!empty($this->queue)) { + $this->proceed(); + } + } + + /** + * @throws ClientException + */ + public function proceed(): void + { + if (empty($this->queue)) { + return; + } + + if (!$this->curlm && false === $this->curlm = curl_multi_init()) { + throw new ClientException('Unable to create a new cURL multi handle'); + } + + foreach ($this->queue as $i => $queueItem) { + if (2 !== \count($queueItem)) { + // We have already prepared this curl + continue; + } + // prepare curl handle + /** @var $request RequestInterface */ + /** @var $options ParameterBag */ + list($request, $options) = $queueItem; + $curl = $this->createHandle(); + $responseBuilder = $this->prepare($curl, $request, $options); + $this->queue[$i][] = $curl; + $this->queue[$i][] = $responseBuilder; + curl_multi_add_handle($this->curlm, $curl); + } + + // process outstanding perform + $active = null; + do { + $mrc = curl_multi_exec($this->curlm, $active); + } while ($active && CURLM_CALL_MULTI_PERFORM == $mrc); + + $exception = null; + // handle any completed requests + while ($done = curl_multi_info_read($this->curlm)) { + foreach (array_keys($this->queue) as $i) { + /** @var $request RequestInterface */ + /** @var $options ParameterBag */ + /** @var $responseBuilder ResponseBuilder */ + list($request, $options, $curl, $responseBuilder) = $this->queue[$i]; + + if ($curl !== $done['handle']) { + continue; + } + + try { + $response = null; + $this->parseError($request, $done['result'], $curl); + $response = $responseBuilder->getResponse(); + } catch (ExceptionInterface $e) { + if (null === $exception) { + $exception = $e; + } + } + + // remove from queue + curl_multi_remove_handle($this->curlm, $curl); + $this->releaseHandle($curl); + unset($this->queue[$i]); + + // callback + \call_user_func($options->get('callback'), $request, $response, $exception); + } + } + + // cleanup + if (empty($this->queue)) { + curl_multi_close($this->curlm); + $this->curlm = null; + + if (null !== $exception) { + throw $exception; + } + } + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Configuration/ParameterBag.php b/vendor/kriswallsmith/buzz/lib/Configuration/ParameterBag.php new file mode 100644 index 0000000000000000000000000000000000000000..90ea31cc0822be1cafd91c001b9e0c4278aea4b1 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Configuration/ParameterBag.php @@ -0,0 +1,112 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Configuration; + +/** + * A ParameterBag is a container for key/value pairs. This implementation is immutable. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + */ +final class ParameterBag implements \IteratorAggregate, \Countable +{ + /** + * Parameter storage. + */ + private $parameters; + + /** + * @param array $parameters An array of parameters + */ + public function __construct(array $parameters = []) + { + $this->parameters = $parameters; + } + + /** + * Returns the parameters. + * + * @return array An array of parameters + */ + public function all(): array + { + return $this->parameters; + } + + /** + * Returns the parameter keys. + * + * @return array An array of parameter keys + */ + public function keys(): array + { + return array_keys($this->parameters); + } + + /** + * Adds parameters to the existing ones. + * + * @param array $parameters An array of parameters + */ + public function add(array $parameters = []): self + { + // Make sure to merge Curl parameters + if (isset($this->parameters['curl']) + && isset($parameters['curl']) + && \is_array($this->parameters['curl']) + && \is_array($parameters['curl'])) { + $parameters['curl'] = array_replace($this->parameters['curl'], $parameters['curl']); + } + + $newParameters = array_replace($this->parameters, $parameters); + + return new self($newParameters); + } + + /** + * Returns a parameter by name. + * + * @param string|int $key The key + * @param mixed $default The default value if the parameter key does not exist + * + * @return mixed + */ + public function get($key, $default = null) + { + return array_key_exists($key, $this->parameters) ? $this->parameters[$key] : $default; + } + + /** + * Returns true if the parameter is defined. + * + * @param string|int $key The key + * + * @return bool true if the parameter exists, false otherwise + */ + public function has($key): bool + { + return array_key_exists($key, $this->parameters); + } + + /** + * Returns an iterator for parameters. + * + * @return \ArrayIterator An \ArrayIterator instance + */ + public function getIterator(): \ArrayIterator + { + return new \ArrayIterator($this->parameters); + } + + /** + * Returns the number of parameters. + * + * @return int The number of parameters + */ + public function count(): int + { + return \count($this->parameters); + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Exception/ClientException.php b/vendor/kriswallsmith/buzz/lib/Exception/ClientException.php new file mode 100644 index 0000000000000000000000000000000000000000..917488173cb7e80c9e65e779875843d5833ad25f --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Exception/ClientException.php @@ -0,0 +1,14 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Exception; + +use Http\Client\Exception as HTTPlugException; + +/** + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + */ +class ClientException extends \RuntimeException implements ExceptionInterface, HTTPlugException +{ +} diff --git a/vendor/kriswallsmith/buzz/lib/Exception/ExceptionInterface.php b/vendor/kriswallsmith/buzz/lib/Exception/ExceptionInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..c097bbdc1185b4c83441177b29da34ef7db9dc2f --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Exception/ExceptionInterface.php @@ -0,0 +1,12 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Exception; + +/** + * Marker interface to denote exceptions thrown from the Buzz context. + */ +interface ExceptionInterface +{ +} diff --git a/vendor/kriswallsmith/buzz/lib/Exception/InvalidArgumentException.php b/vendor/kriswallsmith/buzz/lib/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000000000000000000000000000000..712cc8b08d208e00834d422ce1c11c734d84dd29 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Exception/InvalidArgumentException.php @@ -0,0 +1,12 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Exception; + +/** + * Thrown when an invalid argument is provided. + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/kriswallsmith/buzz/lib/Exception/LogicException.php b/vendor/kriswallsmith/buzz/lib/Exception/LogicException.php new file mode 100644 index 0000000000000000000000000000000000000000..64c84fac2ac2b69b03461953fb4eb442e5b89a85 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Exception/LogicException.php @@ -0,0 +1,12 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Exception; + +/** + * Thrown whenever a required call-flow is not respected. + */ +class LogicException extends \LogicException implements ExceptionInterface +{ +} diff --git a/vendor/kriswallsmith/buzz/lib/Exception/NetworkException.php b/vendor/kriswallsmith/buzz/lib/Exception/NetworkException.php new file mode 100644 index 0000000000000000000000000000000000000000..1b461d03efd014660ef2f6415e53c47651a73fa4 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Exception/NetworkException.php @@ -0,0 +1,30 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Exception; + +use Psr\Http\Client\Exception\NetworkException as PsrNetworkException; +use Psr\Http\Message\RequestInterface; + +/** + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + */ +class NetworkException extends ClientException implements PsrNetworkException +{ + /** + * @var RequestInterface + */ + private $request; + + public function __construct(RequestInterface $request, string $message = '', int $code = 0, \Throwable $previous = null) + { + $this->request = $request; + parent::__construct($message, $code, $previous); + } + + public function getRequest(): RequestInterface + { + return $this->request; + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Exception/RequestException.php b/vendor/kriswallsmith/buzz/lib/Exception/RequestException.php new file mode 100644 index 0000000000000000000000000000000000000000..d15cff5ca806a27454784be713c85bb9a80c7158 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Exception/RequestException.php @@ -0,0 +1,30 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Exception; + +use Psr\Http\Client\Exception\RequestException as PsrRequestException; +use Psr\Http\Message\RequestInterface; + +/** + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + */ +class RequestException extends ClientException implements PsrRequestException +{ + /** + * @var RequestInterface + */ + private $request; + + public function __construct(RequestInterface $request, string $message = '', int $code = 0, \Throwable $previous = null) + { + $this->request = $request; + parent::__construct($message, $code, $previous); + } + + public function getRequest(): RequestInterface + { + return $this->request; + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Message/FormRequestBuilder.php b/vendor/kriswallsmith/buzz/lib/Message/FormRequestBuilder.php new file mode 100644 index 0000000000000000000000000000000000000000..a9d2d5ed809dbc7851bb6e8b4abec7aa7d745e94 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Message/FormRequestBuilder.php @@ -0,0 +1,75 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Message; + +class FormRequestBuilder +{ + /** + * @var array + */ + private $data; + + /** + * @var array + */ + private $files; + + /** + * @param array $data + * @param array $files + */ + public function __construct(array $data = [], array $files = []) + { + $this->data = $data; + $this->files = $files; + } + + /** + * @param string $name + * @param string $value + */ + public function addField(string $name, string $value): void + { + $this->data[$name] = $value; + } + + /** + * @param string $name + * @param string $path + * @param string|null $contentType + * @param string|null $filename + */ + public function addFile(string $name, string $path, string $contentType = null, string $filename = null): void + { + $this->files[$name] = [ + 'path' => $path, + 'contentType' => $contentType, + 'filename' => $filename, + ]; + } + + /** + * @return array + */ + public function build(): array + { + $data = $this->data; + + foreach ($this->files as $name => $file) { + $data[$name] = $file; + } + + return $data; + } + + /** + * Reset the builder. + */ + public function reset(): void + { + $this->data = []; + $this->files = []; + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Message/HeaderConverter.php b/vendor/kriswallsmith/buzz/lib/Message/HeaderConverter.php new file mode 100644 index 0000000000000000000000000000000000000000..9ce2b65853aeafa0c98acd49926428ff2c53eab6 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Message/HeaderConverter.php @@ -0,0 +1,65 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Message; + +/** + * Convert between Buzz style: + * array( + * 'foo: bar', + * 'baz: biz', + * ). + * + * and PSR style: + * array( + * 'foo' => 'bar' + * 'baz' => ['biz', 'buz'], + * ) + * + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + */ +class HeaderConverter +{ + /** + * Convert from Buzz style headers to PSR style. + * + * @param array $headers + * + * @return array + */ + public static function toBuzzHeaders(array $headers): array + { + $buzz = []; + + foreach ($headers as $key => $values) { + if (!\is_array($values)) { + $buzz[] = sprintf('%s: %s', $key, $values); + } else { + foreach ($values as $value) { + $buzz[] = sprintf('%s: %s', $key, $value); + } + } + } + + return $buzz; + } + + /** + * Convert from PSR style headers to Buzz style. + * + * @param array $headers + * + * @return array + */ + public static function toPsrHeaders(array $headers): array + { + $psr = []; + foreach ($headers as $header) { + list($key, $value) = explode(':', $header, 2); + $psr[trim($key)][] = trim($value); + } + + return $psr; + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Message/ResponseBuilder.php b/vendor/kriswallsmith/buzz/lib/Message/ResponseBuilder.php new file mode 100644 index 0000000000000000000000000000000000000000..cbd65e1bef27c362f6b015d690d2ade15f6f94db --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Message/ResponseBuilder.php @@ -0,0 +1,95 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Message; + +use Buzz\Exception\InvalidArgumentException; +use Http\Message\ResponseFactory as HTTPlugResponseFactory; +use Psr\Http\Message\ResponseFactoryInterface as PsrResponseFactory; +use Psr\Http\Message\ResponseInterface; + +/** + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + */ +class ResponseBuilder +{ + /** + * @var ResponseInterface + */ + private $response; + + /** + * @param HTTPlugResponseFactory|PsrResponseFactory $responseFactory + */ + public function __construct($responseFactory) + { + if (!$responseFactory instanceof HTTPlugResponseFactory && !$responseFactory instanceof PsrResponseFactory) { + throw new InvalidArgumentException('First parameter to ResponseBuilder must be a response factory'); + } + + $this->response = $responseFactory->createResponse(); + } + + public function setStatus(string $input): void + { + $parts = explode(' ', $input, 3); + if (\count($parts) < 2 || 0 !== strpos(strtolower($parts[0]), 'http/')) { + throw new InvalidArgumentException(sprintf('"%s" is not a valid HTTP status line', $input)); + } + + $this->response = $this->response->withStatus((int) $parts[1], isset($parts[2]) ? $parts[2] : ''); + $this->response = $this->response->withProtocolVersion((string) substr($parts[0], 5)); + } + + /** + * Add a single HTTP header line. + * + * @param string $input + */ + public function addHeader(string $input): void + { + list($key, $value) = explode(':', $input, 2); + $this->response = $this->response->withAddedHeader(trim($key), trim($value)); + } + + /** + * Add HTTP headers. The input array is all the header lines from the HTTP message. Optionally including the + * status line. + * + * @param array $headers + */ + public function parseHttpHeaders(array $headers): void + { + $statusLine = array_shift($headers); + + try { + $this->setStatus($statusLine); + } catch (InvalidArgumentException $e) { + array_unshift($headers, $statusLine); + } + + foreach ($headers as $header) { + $this->addHeader($header); + } + } + + /** + * Add some content to the body. This function writes the $input to a stream. + * + * @param string $input + * + * @return int returns the number of bytes written + */ + public function writeBody(string $input): int + { + return $this->response->getBody()->write($input); + } + + public function getResponse(): ResponseInterface + { + $this->response->getBody()->rewind(); + + return $this->response; + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Middleware/BasicAuthMiddleware.php b/vendor/kriswallsmith/buzz/lib/Middleware/BasicAuthMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..cf7db608fba1f1b5b87823f8cd2befa87d664e47 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Middleware/BasicAuthMiddleware.php @@ -0,0 +1,33 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Middleware; + +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +class BasicAuthMiddleware implements MiddlewareInterface +{ + private $username; + + private $password; + + public function __construct($username, $password) + { + $this->username = $username; + $this->password = $password; + } + + public function handleRequest(RequestInterface $request, callable $next) + { + $request = $request->withAddedHeader('Authorization', sprintf('Basic %s', base64_encode($this->username.':'.$this->password))); + + return $next($request); + } + + public function handleResponse(RequestInterface $request, ResponseInterface $response, callable $next) + { + return $next($request, $response); + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Middleware/BearerAuthMiddleware.php b/vendor/kriswallsmith/buzz/lib/Middleware/BearerAuthMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..8dd983da419db00d549ec1daa5c51edc7dda92a6 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Middleware/BearerAuthMiddleware.php @@ -0,0 +1,35 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Middleware; + +use Buzz\Exception\InvalidArgumentException; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +class BearerAuthMiddleware implements MiddlewareInterface +{ + private $accessToken; + + public function __construct($accessToken) + { + if (empty($accessToken)) { + throw new InvalidArgumentException('You must supply a non empty accessToken'); + } + + $this->accessToken = $accessToken; + } + + public function handleRequest(RequestInterface $request, callable $next) + { + $request = $request->withAddedHeader('Authorization', sprintf('Bearer %s', $this->accessToken)); + + return $next($request); + } + + public function handleResponse(RequestInterface $request, ResponseInterface $response, callable $next) + { + return $next($request, $response); + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Middleware/CallbackMiddleware.php b/vendor/kriswallsmith/buzz/lib/Middleware/CallbackMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..f56e02153947060d8a548122701bac1be0485d63 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Middleware/CallbackMiddleware.php @@ -0,0 +1,56 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Middleware; + +use Buzz\Exception\InvalidArgumentException; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +/** + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + */ +class CallbackMiddleware implements MiddlewareInterface +{ + private $callable; + + /** + * The callback should expect either one or two arguments, depending on + * whether it is receiving a pre or post send notification. + * + * $middleware = new CallbackMiddleware(function($request, $response = null) { + * if ($response) { + * // postSend + * } else { + * // preSend + * } + * }); + * + * @param mixed $callable A PHP callable + * + * @throws InvalidArgumentException If the argument is not callable + */ + public function __construct($callable) + { + if (!\is_callable($callable)) { + throw new InvalidArgumentException('The argument is not callable.'); + } + + $this->callable = $callable; + } + + public function handleRequest(RequestInterface $request, callable $next) + { + $request = \call_user_func($this->callable, $request); + + return $next($request); + } + + public function handleResponse(RequestInterface $request, ResponseInterface $response, callable $next) + { + $response = \call_user_func($this->callable, $request, $response); + + return $next($request, $response); + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Middleware/ContentLengthMiddleware.php b/vendor/kriswallsmith/buzz/lib/Middleware/ContentLengthMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..74177033acc4486608feabb12fc875261dae9a98 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Middleware/ContentLengthMiddleware.php @@ -0,0 +1,27 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Middleware; + +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +class ContentLengthMiddleware implements MiddlewareInterface +{ + public function handleRequest(RequestInterface $request, callable $next) + { + $body = $request->getBody(); + + if (!$request->hasHeader('Content-Length')) { + $request = $request->withAddedHeader('Content-Length', (string) $body->getSize()); + } + + return $next($request); + } + + public function handleResponse(RequestInterface $request, ResponseInterface $response, callable $next) + { + return $next($request, $response); + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Middleware/CookieMiddleware.php b/vendor/kriswallsmith/buzz/lib/Middleware/CookieMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..059c6742323079fe3e20231bd7cf20d6ab4a4a84 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Middleware/CookieMiddleware.php @@ -0,0 +1,58 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Middleware; + +use Buzz\Util\Cookie; +use Buzz\Util\CookieJar; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +class CookieMiddleware implements MiddlewareInterface +{ + private $cookieJar; + + public function __construct() + { + $this->cookieJar = new CookieJar(); + } + + public function setCookies(array $cookies): void + { + $this->cookieJar->setCookies($cookies); + } + + /** + * @return Cookie[] + */ + public function getCookies(): array + { + return $this->cookieJar->getCookies(); + } + + /** + * Adds a cookie to the current cookie jar. + * + * @param Cookie $cookie A cookie object + */ + public function addCookie(Cookie $cookie): void + { + $this->cookieJar->addCookie($cookie); + } + + public function handleRequest(RequestInterface $request, callable $next) + { + $this->cookieJar->clearExpiredCookies(); + $request = $this->cookieJar->addCookieHeaders($request); + + return $next($request); + } + + public function handleResponse(RequestInterface $request, ResponseInterface $response, callable $next) + { + $this->cookieJar->processSetCookieHeaders($request, $response); + + return $next($request, $response); + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Middleware/DigestAuthMiddleware.php b/vendor/kriswallsmith/buzz/lib/Middleware/DigestAuthMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..dcc0a839f8d0668d3fa47416a0b623efb883de3f --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Middleware/DigestAuthMiddleware.php @@ -0,0 +1,833 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Middleware; + +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +class DigestAuthMiddleware implements MiddlewareInterface +{ + private $username; + + private $password; + + private $realm; + + private $algorithm; + + private $authenticationMethod; + + private $clientNonce; + + private $domain; + + private $entityBody; + + private $method; + + private $nonce; + + private $nonceCount; + + private $opaque; + + private $uri; + + /** @var string[] Quality of Protection */ + private $qop = []; + + /** + * QOP options: Only one of the following can be set at any time. setOptions will throw an exception otherwise. + * OPTION_QOP_AUTH_INT - Always use auth-int (if available) + * OPTION_QOP_AUTH - Always use auth (even if auth-int available). + */ + const OPTION_QOP_AUTH_INT = 1; + + const OPTION_QOP_AUTH = 2; + + /** + * Ignore server request to downgrade authentication from Digest to Basic. + * Breaks RFC compatibility, but ensures passwords are never sent using base64 which is trivial for an attacker to decode. + */ + const OPTION_IGNORE_DOWNGRADE_REQUEST = 4; + + /** + * Discard Client Nonce on each request. + */ + const OPTION_DISCARD_CLIENT_NONCE = 8; + + private $options; + + /** + * Set OPTION_QOP_BEST_AVAILABLE and OPTION_DISCARD_CLIENT_NONCE by default. + */ + public function __construct(string $username = null, string $password = null, string $realm = null) + { + $this->setUsername($username); + $this->setPassword($password); + $this->setRealm($realm); + $this->setOptions(self::OPTION_QOP_AUTH_INT & self::OPTION_DISCARD_CLIENT_NONCE); + } + + /** + * Populates uri, method and entityBody used to generate the Authentication header using the specified request object. + * Appends the Authentication header if it is present and has been able to be calculated. + */ + public function handleRequest(RequestInterface $request, callable $next) + { + $this->setUri($request->getUri()->getPath()); + $this->setMethod(strtoupper($request->getMethod())); + $this->setEntityBody($request->getBody()->__toString()); + + if (null !== $header = $this->getHeader()) { + $request = $request->withHeader('Authorization', $header); + } + + return $next($request); + } + + /** + * Passes the returned server headers to parseServerHeaders() to check if any authentication variables need to be set. + * Inteprets the returned status code and attempts authentication if status is 401 (Authentication Required) by resending + * the last request with an Authentication header. + */ + public function handleResponse(RequestInterface $request, ResponseInterface $response, callable $next) + { + $this->parseServerHeaders($response); + + return $next($request, $response); + } + + /** + * Sets the password to be used to authenticate the client. + * + * @param string $password The password + */ + public function setPassword(?string $password): void + { + $this->password = $password; + } + + /** + * Sets the realm to be used to authenticate the client. + * + * @param string $realm The realm + */ + public function setRealm(?string $realm): void + { + $this->realm = $realm; + } + + /** + * Sets the username to be used to authenticate the client. + * + * @param string $username The username + */ + public function setUsername(?string $username): void + { + $this->username = $username; + } + + /** + * Sets the options to be used by this class. + * + * @param mixed $options a bitmask of the constants defined in this class + */ + public function setOptions($options): void + { + if ($options & self::OPTION_QOP_AUTH_INT) { + if ($options & self::OPTION_QOP_AUTH) { + throw new \InvalidArgumentException('DigestAuthMiddleware: Only one value of OPTION_QOP_AUTH_INT or OPTION_QOP_AUTH may be set.'); + } + $this->options = $this->options | self::OPTION_QOP_AUTH_INT; + } elseif ($options & self::OPTION_QOP_AUTH) { + $this->options = $this->options | self::OPTION_QOP_AUTH; + } + + if ($options & self::OPTION_IGNORE_DOWNGRADE_REQUEST) { + $this->options = $this->options | self::OPTION_IGNORE_DOWNGRADE_REQUEST; + } + + if ($options & self::OPTION_DISCARD_CLIENT_NONCE) { + $this->options = $this->options | self::OPTION_DISCARD_CLIENT_NONCE; + } + } + + /** + * Discards the Client Nonce forcing the generation of a new Client Nonce on the next request. + */ + private function discardClientNonce(): void + { + $this->clientNonce = null; + } + + /** + * Returns the hashing algorithm to be used to generate the digest value. Currently only returns MD5. + * + * @return string the hashing algorithm to be used + */ + private function getAlgorithm(): ?string + { + if (null == $this->algorithm) { + $this->algorithm = 'MD5'; + } + + return $this->algorithm; + } + + /** + * Returns the authentication method requested by the server. + * If OPTION_IGNORE_DOWNGRADE_REQUEST is set this will always return "Digest". + * + * @return string returns either "Digest" or "Basic" + */ + private function getAuthenticationMethod(): ?string + { + if ($this->options & self::OPTION_IGNORE_DOWNGRADE_REQUEST) { + return 'Digest'; + } + + return $this->authenticationMethod; + } + + /** + * Returns either the current value of clientNonce or generates a new value if clientNonce is null. + * Also increments nonceCount. + * + * @return string Returns either the current value of clientNonce the newly generated clientNonce; + */ + private function getClientNonce(): ?string + { + if (null == $this->clientNonce) { + $this->clientNonce = uniqid(); + + if (null == $this->nonceCount) { + // If nonceCount is not set then set it to 00000001. + $this->nonceCount = '00000001'; + } else { + // If it is set then increment it. + ++$this->nonceCount; + // Ensure nonceCount is zero-padded at the start of the string to a length of 8 + while (\strlen($this->nonceCount) < 8) { + $this->nonceCount = '0'.$this->nonceCount; + } + } + } + + return $this->clientNonce; + } + + /** + * Returns a space separated list of uris that the server nonce can be used to generate an authentication response against. + * + * @return string space separated list of uris + */ + private function getDomain(): ?string + { + return $this->domain; + } + + /** + * Returns the entity body of the current request. + * The entity body is the request before it has been encoded with the content-encoding and minus the request headers. + * + * @return string the full entity-body + */ + private function getEntityBody(): ?string + { + return (string) $this->entityBody; + } + + /** + * Calculates the value of HA1 according to RFC 2617 and RFC 2069. + * + * @return string|null The value of HA1 + */ + private function getHA1(): ?string + { + $username = $this->getUsername(); + $password = $this->getPassword(); + $realm = $this->getRealm(); + + if (($username) && ($password) && ($realm)) { + $algorithm = $this->getAlgorithm(); + + if ('MD5' === $algorithm) { + $A1 = "{$username}:{$realm}:{$password}"; + + return $this->hash($A1); + } elseif ('MD5-sess' === $algorithm) { + $nonce = $this->getNonce(); + $cnonce = $this->getClientNonce(); + if (($nonce) && ($cnonce)) { + $A1 = $this->hash("{$username}:{$realm}:{$password}").":{$nonce}:{$cnonce}"; + + return $this->hash($A1); + } + } + } + + return null; + } + + /** + * Calculates the value of HA2 according to RFC 2617 and RFC 2069. + * + * @return string The value of HA2 + */ + private function getHA2(): ?string + { + $method = $this->getMethod(); + $uri = $this->getUri(); + + if (($method) && ($uri)) { + $qop = $this->getQOP(); + + if (null === $qop || 'auth' === $qop) { + $A2 = "{$method}:{$uri}"; + } elseif ('auth-int' === $qop) { + $entityBody = (string) $this->getEntityBody(); + $A2 = "{$method}:{$uri}:".(string) $this->hash($entityBody); + } else { + return null; + } + + $HA2 = $this->hash($A2); + + return $HA2; + } + + return null; + } + + /** + * Returns the full Authentication header for use in authenticating the client with either Digest or Basic authentication. + * + * @return string the Authentication header to be sent to the server + */ + private function getHeader(): ?string + { + if ('Digest' == $this->getAuthenticationMethod()) { + $username = $this->getUsername(); + $realm = $this->getRealm(); + $nonce = $this->getNonce(); + $response = $this->getResponse(); + if (($username) && ($realm) && ($nonce) && ($response)) { + $uri = $this->getUri(); + $opaque = $this->getOpaque(); + $qop = $this->getQOP(); + + $header = 'Digest'; + $header .= ' username="'.$username.'",'; + $header .= ' realm="'.$realm.'",'; + $header .= ' nonce="'.$nonce.'",'; + $header .= ' response="'.$response.'",'; + + if ($uri) { + $header .= ' uri="'.$uri.'",'; + } + if ($opaque) { + $header .= ' opaque="'.$opaque.'",'; + } + + if ($qop) { + $header .= ' qop='.$qop.','; + + $cnonce = $this->getClientNonce(); + $nc = $this->getNonceCount(); + + if ($cnonce) { + $header .= ' nc='.$nc.','; + } + if ($cnonce) { + $header .= ' cnonce="'.$cnonce.'",'; + } + } + + // Remove the last comma from the header + $header = substr($header, 0, \strlen($header) - 1); + // Discard the Client Nonce if OPTION_DISCARD_CLIENT_NONCE is set. + if ($this->options & self::OPTION_DISCARD_CLIENT_NONCE) { + $this->discardClientNonce(); + } + + return $header; + } + } + if ('Basic' == $this->getAuthenticationMethod()) { + $username = $this->getUsername(); + $password = $this->getPassword(); + if (($username) && ($password)) { + $header = 'Basic '.base64_encode("{$username}:{$password}"); + + return $header; + } + } + + return null; + } + + /** + * Returns the HTTP method used in the current request. + * + * @return string one of GET,POST,PUT,DELETE or HEAD + */ + private function getMethod(): ?string + { + return $this->method; + } + + /** + * Returns the value of nonce we have received in the server headers. + * + * @return string the value of the server nonce + */ + private function getNonce(): ?string + { + return $this->nonce; + } + + /** + * Returns the current nonce counter for the client nonce. + * + * @return string an eight digit zero-padded string which reflects the number of times the clientNonce has been generated + */ + private function getNonceCount(): ?string + { + return $this->nonceCount; + } + + /** + * Returns the opaque value that was sent to us from the server. + * + * @return string the value of opaque + */ + private function getOpaque(): ?string + { + return $this->opaque; + } + + /** + * Returns the plaintext password for the client. + * + * @return string the value of password + */ + private function getPassword(): ?string + { + return $this->password; + } + + /** + * Returns either the realm specified by the client, or the realm specified by the server. + * If the server set the value of realm then anything set by our client is overwritten. + * + * @return string the value of realm + */ + private function getRealm(): ?string + { + return $this->realm; + } + + /** + * Calculates the value of response according to RFC 2617 and RFC 2069. + * + * @return string The value of response + */ + private function getResponse(): ?string + { + $HA1 = $this->getHA1(); + $nonce = $this->getNonce(); + $HA2 = $this->getHA2(); + + if (null !== $HA1 && ($nonce) && null !== $HA2) { + $qop = $this->getQOP(); + + if (empty($qop)) { + $response = $this->hash("{$HA1}:{$nonce}:{$HA2}"); + + return $response; + } + + $cnonce = $this->getClientNonce(); + $nc = $this->getNonceCount(); + if (($cnonce) && ($nc)) { + $response = $this->hash("{$HA1}:{$nonce}:{$nc}:{$cnonce}:{$qop}:{$HA2}"); + + return $response; + } + } + + return null; + } + + /** + * Returns the Quality of Protection to be used when authenticating with the server. + * + * @return string this will either be auth-int or auth + */ + private function getQOP(): ?string + { + // Has the server specified any options for Quality of Protection + if (\count($this->qop) > 0) { + if ($this->options & self::OPTION_QOP_AUTH_INT) { + if (\in_array('auth-int', $this->qop)) { + return 'auth-int'; + } + if (\in_array('auth', $this->qop)) { + return 'auth'; + } + } + if ($this->options & self::OPTION_QOP_AUTH) { + if (\in_array('auth', $this->qop)) { + return 'auth'; + } + if (\in_array('auth-int', $this->qop)) { + return 'auth-int'; + } + } + } + // Server has not specified any value for Quality of Protection so return null + return null; + } + + /** + * Returns the username set by the client to authenticate with the server. + * + * @return string The value of username + */ + private function getUsername(): ?string + { + return $this->username; + } + + /** + * Returns the uri that we are requesting access to. + * + * @return string The value of uri + */ + private function getUri(): ?string + { + return $this->uri; + } + + /** + * Calculates the hash for a given value using the algorithm specified by the server. + * + * @param string $value The value to be hashed + * + * @return string the hashed value + */ + private function hash($value): ?string + { + $algorithm = $this->getAlgorithm(); + if (('MD5' == $algorithm) || ('MD5-sess' == $algorithm)) { + return hash('md5', $value); + } + + return null; + } + + /** + * Parses the Authentication-Info header received from the server and calls the relevant setter method on each variable received. + * + * @param string $authenticationInfo the full Authentication-Info header + */ + private function parseAuthenticationInfoHeader(string $authenticationInfo): void + { + $nameValuePairs = $this->parseNameValuePairs($authenticationInfo); + foreach ($nameValuePairs as $name => $value) { + switch ($name) { + case 'message-qop': + + break; + case 'nextnonce': + // This function needs to only set the Nonce once the rspauth has been verified. + $this->setNonce($value); + + break; + case 'rspauth': + // Check server rspauth value + break; + } + } + } + + /** + * Parses a string of name=value pairs separated by commas and returns and array with the name as the index. + * + * @param string $nameValuePairs the string containing the name=value pairs + * + * @return array an array with the name used as the index and the values stored within + */ + private function parseNameValuePairs(string $nameValuePairs): array + { + $parsedNameValuePairs = []; + $nameValuePairs = explode(',', $nameValuePairs); + foreach ($nameValuePairs as $nameValuePair) { + // Trim the Whitespace from the start and end of the name value pair string + $nameValuePair = trim($nameValuePair); + // Split $nameValuePair (name=value) into $name and $value + list($name, $value) = explode('=', $nameValuePair, 2); + // Remove quotes if the string is quoted + $value = $this->unquoteString($value); + // Add pair to array[name] => value + $parsedNameValuePairs[$name] = $value; + } + + return $parsedNameValuePairs; + } + + /** + * Parses the server headers received and checks for WWW-Authenticate and Authentication-Info headers. + * Calls parseWwwAuthenticateHeader() and parseAuthenticationInfoHeader() respectively if either of these headers are present. + * + * @param ResponseInterface $response + */ + private function parseServerHeaders(ResponseInterface $response): void + { + // Check to see if the WWW-Authenticate header is present and if so set $authHeader + if (!empty($header = $response->getHeaderLine('www-authenticate'))) { + $this->parseWwwAuthenticateHeader($header); + } + + // Check to see if the Authentication-Info header is present and if so set $authInfo + if (!empty($header = $response->getHeaderLine('authentication-info'))) { + $this->parseAuthenticationInfoHeader($header); + } + } + + /** + * Parses the WWW-Authenticate header received from the server and calls the relevant setter method on each variable received. + * + * @param string $wwwAuthenticate the full WWW-Authenticate header + */ + private function parseWwwAuthenticateHeader(string $wwwAuthenticate): void + { + if ('Digest ' == substr($wwwAuthenticate, 0, 7)) { + $this->setAuthenticationMethod('Digest'); + // Remove "Digest " from start of header + $wwwAuthenticate = substr($wwwAuthenticate, 7, \strlen($wwwAuthenticate) - 7); + + $nameValuePairs = $this->parseNameValuePairs($wwwAuthenticate); + + foreach ($nameValuePairs as $name => $value) { + switch ($name) { + case 'algorithm': + $this->setAlgorithm($value); + + break; + case 'domain': + $this->setDomain($value); + + break; + case 'nonce': + $this->setNonce($value); + + break; + case 'realm': + $this->setRealm($value); + + break; + case 'opaque': + $this->setOpaque($value); + + break; + case 'qop': + $this->setQOP(explode(',', $value)); + + break; + } + } + } + if ('Basic ' == substr($wwwAuthenticate, 0, 6)) { + $this->setAuthenticationMethod('Basic'); + // Remove "Basic " from start of header + $wwwAuthenticate = substr($wwwAuthenticate, 6, \strlen($wwwAuthenticate) - 6); + + $nameValuePairs = $this->parseNameValuePairs($wwwAuthenticate); + + foreach ($nameValuePairs as $name => $value) { + switch ($name) { + case 'realm': + $this->setRealm($value); + + break; + } + } + } + } + + /** + * Sets the hashing algorithm to be used. Currently only uses MD5 specified by either MD5 or MD5-sess. + * RFCs are currently in draft stage for the proposal of SHA-256 and SHA-512-256. + * Support will be added once the RFC leaves the draft stage. + * + * @param string $algorithm the algorithm the server has requested to use + * + * @throws \InvalidArgumentException if $algorithm is set to anything other than MD5 or MD5-sess + */ + private function setAlgorithm(string $algorithm): void + { + if (('MD5' == $algorithm) || ('MD5-sess' == $algorithm)) { + $this->algorithm = $algorithm; + } else { + throw new \InvalidArgumentException('DigestAuthMiddleware: Only MD5 and MD5-sess algorithms are currently supported.'); + } + } + + /** + * Sets authentication method to be used. Options are "Digest" and "Basic". + * If the server and the client are unable to authenticate using Digest then the RFCs state that the server should attempt + * to authenticate the client using Basic authentication. This ensures that we adhere to that behaviour. + * This does however create the possibilty of a downgrade attack so it may be an idea to add a way of disabling this functionality + * as Basic authentication is trivial to decrypt and exposes the username/password to a man-in-the-middle attack. + * + * @param string $authenticationMethod the authentication method requested by the server + * + * @throws \InvalidArgumentException If $authenticationMethod is set to anything other than Digest or Basic + */ + private function setAuthenticationMethod(string $authenticationMethod): void + { + if ('Digest' === $authenticationMethod || 'Basic' === $authenticationMethod) { + $this->authenticationMethod = $authenticationMethod; + } else { + throw new \InvalidArgumentException('DigestAuthMiddleware: Only Digest and Basic authentication methods are currently supported.'); + } + } + + /** + * Sets the domain to be authenticated against. THIS IS NOT TO BE CONFUSED WITH THE HOSTNAME/DOMAIN. + * This is specified by the RFC to be a list of uris separated by spaces that the client will be allowed to access. + * An RFC in draft stage is proposing the removal of this functionality, it does not seem to be in widespread use. + * + * @param string $domain the list of uris separated by spaces that the client will be able to access upon successful authentication + */ + private function setDomain(string $domain): void + { + $this->domain = $domain; + } + + /** + * Sets the Entity Body of the Request for use with qop=auth-int. + * + * @param string $entityBody the body of the entity (The unencoded request minus the headers) + */ + private function setEntityBody(string $entityBody = null): void + { + $this->entityBody = $entityBody; + } + + /** + * Sets the HTTP method being used for the request. + * + * @param string $method The HTTP method + * + * @throws \InvalidArgumentException if $method is set to anything other than GET,POST,PUT,DELETE or HEAD + */ + private function setMethod(string $method = null): void + { + if ('GET' == $method) { + $this->method = 'GET'; + + return; + } + if ('POST' == $method) { + $this->method = 'POST'; + + return; + } + if ('PUT' == $method) { + $this->method = 'PUT'; + + return; + } + if ('DELETE' == $method) { + $this->method = 'DELETE'; + + return; + } + if ('HEAD' == $method) { + $this->method = 'HEAD'; + + return; + } + + throw new \InvalidArgumentException('DigestAuthMiddleware: Only GET,POST,PUT,DELETE,HEAD HTTP methods are currently supported.'); + } + + /** + * Sets the value of nonce. + * + * @param string $nonce The server nonce value + */ + private function setNonce(string $nonce = null): void + { + $this->nonce = $nonce; + } + + /** + * Sets the value of opaque. + * + * @param string $opaque The opaque value + */ + private function setOpaque(string $opaque): void + { + $this->opaque = $opaque; + } + + /** + * Sets the acceptable value(s) for the quality of protection used by the server. Supported values are auth and auth-int. + * TODO: This method should give precedence to using qop=auth-int first as this offers integrity protection. + * + * @param array $qop an array with the values of qop that the server has specified it will accept + * + * @throws \InvalidArgumentException if $qop contains any values other than auth-int or auth + */ + private function setQOP(array $qop = []): void + { + $this->qop = []; + foreach ($qop as $protection) { + $protection = trim($protection); + if ('auth-int' == $protection) { + $this->qop[] = 'auth-int'; + } elseif ('auth' == $protection) { + $this->qop[] = 'auth'; + } else { + throw new \InvalidArgumentException('DigestAuthMiddleware: Only auth-int and auth are supported Quality of Protection mechanisms.'); + } + } + } + + /** + * Sets the value of uri. + * + * @param string $uri The uri + */ + private function setUri(string $uri = null): void + { + $this->uri = $uri; + } + + /** + * If a string contains quotation marks at either end this function will strip them. Otherwise it will remain unchanged. + * + * @param string $str the string to be stripped of quotation marks + * + * @return string returns the original string without the quotation marks at either end + */ + private function unquoteString(string $str = null): ?string + { + if ($str) { + if ('"' == substr($str, 0, 1)) { + $str = substr($str, 1, \strlen($str) - 1); + } + if ('"' == substr($str, \strlen($str) - 1, 1)) { + $str = substr($str, 0, \strlen($str) - 1); + } + } + + return $str; + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Middleware/History/Entry.php b/vendor/kriswallsmith/buzz/lib/Middleware/History/Entry.php new file mode 100644 index 0000000000000000000000000000000000000000..36a0a5d7c3352824cb19de3639963109c62bfe0b --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Middleware/History/Entry.php @@ -0,0 +1,44 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Middleware\History; + +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +class Entry +{ + private $request; + + private $response; + + private $duration; + + /** + * @param RequestInterface $request The request + * @param ResponseInterface $response The response + * @param null|float $duration The duration in seconds + */ + public function __construct(RequestInterface $request, ResponseInterface $response, float $duration = null) + { + $this->request = $request; + $this->response = $response; + $this->duration = $duration; + } + + public function getRequest(): RequestInterface + { + return $this->request; + } + + public function getResponse(): ResponseInterface + { + return $this->response; + } + + public function getDuration(): ?float + { + return $this->duration; + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Middleware/History/Journal.php b/vendor/kriswallsmith/buzz/lib/Middleware/History/Journal.php new file mode 100644 index 0000000000000000000000000000000000000000..77f0933ea977c0568a6aa74beddeefa43385a262 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Middleware/History/Journal.php @@ -0,0 +1,97 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Middleware\History; + +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +class Journal implements \Countable, \IteratorAggregate +{ + private $entries = []; + + private $limit = 10; + + public function __construct(int $limit = 10) + { + $this->limit = $limit; + } + + /** + * Records an entry in the journal. + * + * @param RequestInterface $request The request + * @param ResponseInterface $response The response + * @param null|float $duration The duration in seconds + */ + public function record(RequestInterface $request, ResponseInterface $response, float $duration = null): void + { + $this->addEntry(new Entry($request, $response, $duration)); + } + + public function addEntry(Entry $entry): void + { + array_push($this->entries, $entry); + $this->entries = \array_slice($this->entries, $this->getLimit() * -1); + end($this->entries); + } + + /** + * @return Entry[] + */ + public function getEntries(): array + { + return $this->entries; + } + + public function getLast(): ?Entry + { + $entry = end($this->entries); + + return false === $entry ? null : $entry; + } + + public function getLastRequest(): ?RequestInterface + { + if (null === $entry = $this->getLast()) { + return null; + } + + return $entry->getRequest(); + } + + public function getLastResponse(): ?ResponseInterface + { + if (null === $entry = $this->getLast()) { + return null; + } + + return $entry->getResponse(); + } + + public function clear(): void + { + $this->entries = []; + } + + public function count(): int + { + return \count($this->entries); + } + + public function setLimit(int $limit): void + { + $this->limit = $limit; + } + + public function getLimit(): int + { + return $this->limit; + } + + public function getIterator(): \ArrayIterator + { + return new \ArrayIterator(array_reverse($this->entries)); + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Middleware/HistoryMiddleware.php b/vendor/kriswallsmith/buzz/lib/Middleware/HistoryMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..e6c1eafa7f30be0353bf8d214086fc0dae450ba0 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Middleware/HistoryMiddleware.php @@ -0,0 +1,40 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Middleware; + +use Buzz\Middleware\History\Journal; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +class HistoryMiddleware implements MiddlewareInterface +{ + private $journal; + + private $startTime; + + public function __construct(Journal $journal) + { + $this->journal = $journal; + } + + public function getJournal(): Journal + { + return $this->journal; + } + + public function handleRequest(RequestInterface $request, callable $next) + { + $this->startTime = microtime(true); + + return $next($request); + } + + public function handleResponse(RequestInterface $request, ResponseInterface $response, callable $next) + { + $this->journal->record($request, $response, microtime(true) - $this->startTime); + + return $next($request, $response); + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Middleware/LoggerMiddleware.php b/vendor/kriswallsmith/buzz/lib/Middleware/LoggerMiddleware.php new file mode 100644 index 0000000000000000000000000000000000000000..79f0ea9b3edc20bae165d0a3b49e858dfae0d124 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Middleware/LoggerMiddleware.php @@ -0,0 +1,47 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Middleware; + +use Psr\Http\Message\ResponseInterface; +use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; + +class LoggerMiddleware implements MiddlewareInterface +{ + private $logger; + + private $level; + + private $prefix; + + private $startTime; + + /** + * @param LoggerInterface $logger + * @param string $level + * @param string|null $prefix + */ + public function __construct(LoggerInterface $logger = null, $level = 'info', $prefix = null) + { + $this->logger = $logger ?: new NullLogger(); + $this->level = $level; + $this->prefix = $prefix; + } + + public function handleRequest(\Psr\Http\Message\RequestInterface $request, callable $next) + { + $this->startTime = microtime(true); + + return $next($request); + } + + public function handleResponse(\Psr\Http\Message\RequestInterface $request, ResponseInterface $response, callable $next) + { + $seconds = microtime(true) - $this->startTime; + $this->logger->log($this->level, sprintf('%sSent "%s %s" in %dms', $this->prefix, $request->getMethod(), $request->getUri(), round($seconds * 1000))); + + return $next($request, $response); + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Middleware/MiddlewareInterface.php b/vendor/kriswallsmith/buzz/lib/Middleware/MiddlewareInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..d24a2fffebdcdeb3b0e31230284e442e37bca444 --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Middleware/MiddlewareInterface.php @@ -0,0 +1,44 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Middleware; + +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +/** + * A middleware gets called twice per request. One time before we send the request + * and once after the response is received. A middleware may modify/change the + * request and the response. Just be aware that they are immutable. + * + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + */ +interface MiddlewareInterface +{ + /** + * Handle a request. + * + * End this function by calling: + * <code> + * return $next($request); + * </code + * + * @param RequestInterface $request + * @param callable $next next middleware + */ + public function handleRequest(RequestInterface $request, callable $next); + + /** + * Handle a response. + * + * End this function by calling: + * <code> + * return $next($request, $response); + * </code + * + * @param RequestInterface $request + * @param callable $next next middleware + */ + public function handleResponse(RequestInterface $request, ResponseInterface $response, callable $next); +} diff --git a/vendor/kriswallsmith/buzz/lib/Util/Cookie.php b/vendor/kriswallsmith/buzz/lib/Util/Cookie.php new file mode 100644 index 0000000000000000000000000000000000000000..a8f286705245814d907b2a5cc9e27daae852e07e --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Util/Cookie.php @@ -0,0 +1,232 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Util; + +use Psr\Http\Message\RequestInterface; + +class Cookie +{ + const ATTR_DOMAIN = 'domain'; + + const ATTR_PATH = 'path'; + + const ATTR_SECURE = 'secure'; + + const ATTR_MAX_AGE = 'max-age'; + + const ATTR_EXPIRES = 'expires'; + + protected $name; + + protected $value; + + protected $attributes = []; + + protected $createdAt; + + /** + * Constructor. + */ + public function __construct() + { + $this->createdAt = time(); + } + + /** + * Returns true if the current cookie matches the supplied request. + * + * @param RequestInterface $request A request object + * + * @return bool + */ + public function matchesRequest(RequestInterface $request): bool + { + $uri = $request->getUri(); + // domain + if (!$this->matchesDomain($uri->getHost())) { + return false; + } + + // path + if (!$this->matchesPath($uri->getPath())) { + return false; + } + + // secure + if ($this->hasAttribute(static::ATTR_SECURE) && 'https' !== $uri->getScheme()) { + return false; + } + + return true; + } + + /** + * Returns true of the current cookie has expired. + * + * Checks the max-age and expires attributes. + * + * @return bool Whether the current cookie has expired + */ + public function isExpired(): bool + { + $maxAge = $this->getAttribute(static::ATTR_MAX_AGE); + if ($maxAge && time() - $this->getCreatedAt() > $maxAge) { + return true; + } + + $expires = $this->getAttribute(static::ATTR_EXPIRES); + if ($expires && strtotime($expires) < time()) { + return true; + } + + return false; + } + + /** + * Returns true if the current cookie matches the supplied domain. + * + * @param string $domain A domain hostname + * + * @return bool + */ + public function matchesDomain(string $domain): bool + { + $cookieDomain = $this->getAttribute(static::ATTR_DOMAIN); + + if (0 === strpos($cookieDomain, '.')) { + $pattern = '/\b'.preg_quote(substr($cookieDomain, 1), '/').'$/i'; + + return (bool) preg_match($pattern, $domain); + } else { + return 0 == strcasecmp($cookieDomain, $domain); + } + } + + /** + * Returns true if the current cookie matches the supplied path. + * + * @param string $path A path + * + * @return bool + */ + public function matchesPath(string $path): bool + { + $needle = $this->getAttribute(static::ATTR_PATH); + + return null === $needle || 0 === strpos($path, $needle); + } + + /** + * Populates the current cookie with data from the supplied Set-Cookie header. + * + * @param string $header A Set-Cookie header + * @param string $issuingDomain The domain that issued the header + */ + public function fromSetCookieHeader(string $header, string $issuingDomain): void + { + list($this->name, $header) = explode('=', $header, 2); + if (false === strpos($header, ';')) { + $this->value = $header; + $header = null; + } else { + list($this->value, $header) = explode(';', $header, 2); + } + + $this->clearAttributes(); + if (null !== $header) { + foreach (array_map('trim', explode(';', trim($header))) as $pair) { + if (false === strpos($pair, '=')) { + $name = $pair; + $value = null; + } else { + list($name, $value) = explode('=', $pair); + } + + $this->setAttribute($name, $value); + } + } + + if (!$this->getAttribute(static::ATTR_DOMAIN)) { + $this->setAttribute(static::ATTR_DOMAIN, $issuingDomain); + } + } + + /** + * Formats a Cookie header for the current cookie. + * + * @return string An HTTP request Cookie header + */ + public function toCookieHeader(): string + { + return $this->getName().'='.$this->getValue(); + } + + public function setName(string $name): void + { + $this->name = $name; + } + + public function getName(): string + { + return $this->name; + } + + public function setValue(string $value): void + { + $this->value = $value; + } + + public function getValue(): string + { + return $this->value; + } + + public function setAttributes(array $attributes) + { + // attributes are case insensitive + $this->attributes = array_change_key_case($attributes); + } + + public function setAttribute(string $name, ?string $value): void + { + $this->attributes[strtolower($name)] = $value; + } + + public function getAttributes(): array + { + return $this->attributes; + } + + public function getAttribute(string $name): ?string + { + $name = strtolower($name); + + if (isset($this->attributes[$name])) { + return $this->attributes[$name]; + } + + return null; + } + + public function hasAttribute(string $name): bool + { + return array_key_exists($name, $this->attributes); + } + + public function clearAttributes(): void + { + $this->setAttributes([]); + } + + public function setCreatedAt(int $createdAt): void + { + $this->createdAt = $createdAt; + } + + public function getCreatedAt(): int + { + return $this->createdAt; + } +} diff --git a/vendor/kriswallsmith/buzz/lib/Util/CookieJar.php b/vendor/kriswallsmith/buzz/lib/Util/CookieJar.php new file mode 100644 index 0000000000000000000000000000000000000000..6732e9019ec84aeb08bedc4fb01523abd6afcb4d --- /dev/null +++ b/vendor/kriswallsmith/buzz/lib/Util/CookieJar.php @@ -0,0 +1,94 @@ +<?php + +declare(strict_types=1); + +namespace Buzz\Util; + +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +class CookieJar +{ + /** @var Cookie[] */ + private $cookies = []; + + public function clear(): void + { + $this->cookies = []; + } + + public function setCookies(array $cookies): void + { + $this->cookies = []; + foreach ($cookies as $cookie) { + $this->addCookie($cookie); + } + } + + /** + * @return Cookie[] + */ + public function getCookies(): array + { + return $this->cookies; + } + + /** + * Adds a cookie to the current cookie jar. + * + * @param Cookie $cookie A cookie object + */ + public function addCookie(Cookie $cookie): void + { + $this->cookies[] = $cookie; + } + + /** + * Adds Cookie headers to the supplied request. + * + * @param RequestInterface $request A request object + */ + public function addCookieHeaders(RequestInterface $request): RequestInterface + { + foreach ($this->getCookies() as $cookie) { + if ($cookie->matchesRequest($request)) { + $request = $request->withHeader('Cookie', $cookie->toCookieHeader()); + } + } + + return $request; + } + + /** + * Processes Set-Cookie headers from a request/response pair. + * + * @param RequestInterface $request A request object + * @param ResponseInterface $response A response object + */ + public function processSetCookieHeaders(RequestInterface $request, ResponseInterface $response): void + { + $host = $request->getUri()->getHost(); + foreach ($response->getHeader('Set-Cookie') as $header) { + $cookie = new Cookie(); + $cookie->fromSetCookieHeader($header, $host); + + $this->addCookie($cookie); + } + } + + /** + * Removes expired cookies. + */ + public function clearExpiredCookies(): void + { + $cookies = $this->getCookies(); + foreach ($cookies as $i => $cookie) { + if ($cookie->isExpired()) { + unset($cookies[$i]); + } + } + + $this->clear(); + $this->setCookies(array_values($cookies)); + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/.gitignore b/vendor/m4tthumphrey/php-gitlab-api/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d1502b087b4d4ede40ddbbf64a8b87a6348b17d8 --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/.gitignore @@ -0,0 +1,2 @@ +vendor/ +composer.lock diff --git a/vendor/m4tthumphrey/php-gitlab-api/.travis.yml b/vendor/m4tthumphrey/php-gitlab-api/.travis.yml new file mode 100644 index 0000000000000000000000000000000000000000..97190200d2640da65bc8b33ecd6a0beff1166e1f --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/.travis.yml @@ -0,0 +1,17 @@ +language: php + +sudo: false + +php: + - 5.3 + - 5.4 + - 5.5 + - 5.6 + - 7.0 + +before_script: + - travis_retry composer self-update + - travis_retry composer install --no-interaction --prefer-source + +script: + - vendor/bin/phpunit --verbose --coverage-text diff --git a/vendor/m4tthumphrey/php-gitlab-api/README.md b/vendor/m4tthumphrey/php-gitlab-api/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b8cbdb352a53aab50dd2c195921cf3f0844a425e --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/README.md @@ -0,0 +1,96 @@ +A PHP wrapper to be used with [Gitlab's API](https://github.com/gitlabhq/gitlabhq/tree/master/doc/api). +============== + +[](https://travis-ci.org/m4tthumphrey/php-gitlab-api) + +Based on [php-github-api](https://github.com/m4tthumphrey/php-github-api) and code from [KnpLabs](https://github.com/KnpLabs/php-github-api). + +Installation +------------ +1. Install Composer + + ```bash + $ curl -sS https://getcomposer.org/installer | php + $ sudo mv composer.phar /usr/local/bin/composer + ``` + +2. Add the following to your require block in composer.json config. + + > Note: be careful when using the `dev-master` tag as this may have unexpected results depending on your version of + Gitlab. See the Versioning section below for more information. + + `php composer.phar require m4tthumphrey/php-gitlab-api:dev-master` + +3. Include Composer's autoloader: + + ```php + require_once dirname(__DIR__).'/vendor/autoload.php'; + ``` + +Versioning +---------- + +From the 6.0 stable release of Gitlab, I shall now be matching the client version with the Gitlab version. For example +when Gitlab 6.1 is released I will release version 6.1.0 of the API client. If I need to make future updates to the client +before the next API version is released, I'll simply use a 3rd build version - `6.1.1`, `6.1.2` etc for example. + +It is recommended that you keep your composer file in sync with whatever version of Gitlab you are currently running: +if you are using 6.0, you should require `6.0.*`; 6.1 should be `6.1.*`... + +General API Usage +----------------- + +```php +$client = new \Gitlab\Client('http://git.yourdomain.com/api/v3/'); // change here +$client->authenticate('your_gitlab_token_here', \Gitlab\Client::AUTH_URL_TOKEN); // change here + +$project = $client->api('projects')->create('My Project', array( + 'description' => 'This is a project', + 'issues_enabled' => false +)); + +``` + +Model Usage +----------- + +You can also use the library in an object oriented manner: + +```php +$client = new \Gitlab\Client('http://git.yourdomain.com/api/v3/'); // change here +$client->authenticate('your_gitlab_token_here', \Gitlab\Client::AUTH_URL_TOKEN); // change here + +# Creating a new project +$project = \Gitlab\Model\Project::create($client, 'My Project', array( + 'description' => 'This is my project', + 'issues_enabled' => false +)); + +$project->addHook('http://mydomain.com/hook/push/1'); + +# Creating a new issue +$project = new \Gitlab\Model\Project(1, $client); +$issue = $project->createIssue('This does not work.', array( + 'description' => 'This doesn\'t work properly. Please fix.', + 'assignee_id' => 2 +)); + +# Closing that issue +$issue->close(); +``` + +You get the idea! Take a look around ([API methods](https://github.com/m4tthumphrey/php-gitlab-api/tree/master/lib/Gitlab/Api), +[models](https://github.com/m4tthumphrey/php-gitlab-api/tree/master/lib/Gitlab/Model)) and please feel free to report any bugs. + +Framework Integrations +---------------------- +- **Symfony** - https://github.com/Zeichen32/GitLabApiBundle +- **Laravel** - https://github.com/vinkla/gitlab + +If you have integrated GitLab into a popular PHP framework, let us know! + +Contributing +------------ + +There are many parts of Gitlab that I have not added to this as it was originally created for personal use, hence the +lack of tests. Feel free to fork and add new functionality and tests, I'll gladly accept decent pull requests. diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/HttpClient.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/HttpClient.php new file mode 100644 index 0000000000000000000000000000000000000000..7a84bfb436af3bfad1ff1a6d01f6bcd58ea39644 --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/HttpClient.php @@ -0,0 +1,231 @@ +<?php namespace Gitlab\HttpClient; + +use Buzz\Client\ClientInterface; +use Buzz\Listener\ListenerInterface; +use Buzz\Message\Form\FormUpload; + +use Gitlab\Exception\ErrorException; +use Gitlab\Exception\RuntimeException; +use Gitlab\HttpClient\Listener\ErrorListener; +use Gitlab\HttpClient\Message\Request; +use Gitlab\HttpClient\Message\Response; +use Gitlab\HttpClient\Message\FormRequest; + +/** + * Performs requests on Gitlab API. API documentation should be self-explanatory. + * + * @author Joseph Bielawski <stloyd@gmail.com> + * @author Matt Humphrey <matt@m4tt.co> + */ +class HttpClient implements HttpClientInterface +{ + /** + * @var array + */ + protected $options = array( + 'user_agent' => 'php-gitlab-api (http://github.com/m4tthumphrey/php-gitlab-api)', + 'timeout' => 10, + ); + + /** + * @var string + */ + protected $baseUrl; + + /** + * @var ListenerInterface[] + */ + protected $listeners = array(); + /** + * @var array + */ + protected $headers = array(); + + /** + * @var Response + */ + private $lastResponse; + + /** + * @var Request + */ + private $lastRequest; + + /** + * @param string $baseUrl + * @param array $options + * @param ClientInterface $client + */ + public function __construct($baseUrl, array $options, ClientInterface $client) + { + $this->baseUrl = $baseUrl; + $this->options = array_merge($this->options, $options); + $this->client = $client; + + $this->addListener(new ErrorListener($this->options)); + + $this->clearHeaders(); + } + + /** + * {@inheritDoc} + */ + public function setOption($name, $value) + { + $this->options[$name] = $value; + } + + /** + * {@inheritDoc} + */ + public function setHeaders(array $headers) + { + $this->headers = array_merge($this->headers, $headers); + } + + /** + * Clears used headers + */ + public function clearHeaders() + { + $this->headers = array(); + } + + /** + * @param ListenerInterface $listener + */ + public function addListener(ListenerInterface $listener) + { + $this->listeners[get_class($listener)] = $listener; + } + + /** + * {@inheritDoc} + */ + public function get($path, array $parameters = array(), array $headers = array()) + { + if (0 < count($parameters)) { + $path .= (false === strpos($path, '?') ? '?' : '&').http_build_query($parameters, '', '&'); + } + + return $this->request($path, array(), 'GET', $headers); + } + + /** + * {@inheritDoc} + */ + public function post($path, array $parameters = array(), array $headers = array(), array $files = array()) + { + return $this->request($path, $parameters, 'POST', $headers, $files); + } + + /** + * {@inheritDoc} + */ + public function patch($path, array $parameters = array(), array $headers = array()) + { + return $this->request($path, $parameters, 'PATCH', $headers); + } + + /** + * {@inheritDoc} + */ + public function delete($path, array $parameters = array(), array $headers = array()) + { + return $this->request($path, $parameters, 'DELETE', $headers); + } + + /** + * {@inheritDoc} + */ + public function put($path, array $parameters = array(), array $headers = array()) + { + return $this->request($path, $parameters, 'PUT', $headers); + } + + /** + * {@inheritDoc} + */ + public function request($path, array $parameters = array(), $httpMethod = 'GET', array $headers = array(), array $files = array()) + { + $path = trim($this->baseUrl.$path, '/'); + + $request = $this->createRequest($httpMethod, $path, $parameters, $headers, $files); + + $hasListeners = 0 < count($this->listeners); + if ($hasListeners) { + foreach ($this->listeners as $listener) { + $listener->preSend($request); + } + } + + $response = new Response(); + + try { + $this->client->send($request, $response); + } catch (\LogicException $e) { + throw new ErrorException($e->getMessage()); + } catch (\RuntimeException $e) { + throw new RuntimeException($e->getMessage()); + } + + $this->lastRequest = $request; + $this->lastResponse = $response; + + if ($hasListeners) { + foreach ($this->listeners as $listener) { + $listener->postSend($request, $response); + } + } + + return $response; + } + + /** + * @return Request + */ + public function getLastRequest() + { + return $this->lastRequest; + } + + /** + * @return Response + */ + public function getLastResponse() + { + return $this->lastResponse; + } + + /** + * @param string $httpMethod + * @param string $url + * @param array $parameters + * @param array $headers + * @param array $files + * + * @return FormRequest|Request + */ + private function createRequest($httpMethod, $url, array $parameters, array $headers, array $files) + { + if (empty($files)) { + $request = new Request($httpMethod); + $request->setContent(http_build_query($parameters)); + } else { + $request = new FormRequest($httpMethod); + foreach ($parameters as $name => $value) { + $request->setField($name, $value); + } + + foreach ($files as $name => $file) { + $upload = new FormUpload($file); + $request->setField($name, $upload); + } + } + $request->setHeaders($this->headers); + $request->fromUrl($url); + $request->addHeaders($headers); + + return $request; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/HttpClientInterface.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/HttpClientInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..674987becc99373bf338170cb5727f010323b59d --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/HttpClientInterface.php @@ -0,0 +1,98 @@ +<?php namespace Gitlab\HttpClient; + +use Gitlab\Exception\InvalidArgumentException; + +/** + * Performs requests on Gitlab API. API documentation should be self-explanatory. + * + * @author Joseph Bielawski <stloyd@gmail.com> + * @author Matt Humphrey <matt@m4tt.co> + */ +interface HttpClientInterface +{ + /** + * Send a GET request + * + * @param string $path Request path + * @param array $parameters GET Parameters + * @param array $headers Reconfigure the request headers for this call only + * + * @return array Data + */ + public function get($path, array $parameters = array(), array $headers = array()); + + /** + * Send a POST request + * + * @param string $path Request path + * @param array $parameters POST Parameters + * @param array $headers Reconfigure the request headers for this call only + * @param array $files Files paths of files to upload + * + * @return array Data + */ + public function post($path, array $parameters = array(), array $headers = array(), array $files = array()); + + /** + * Send a PATCH request + * + * @param string $path Request path + * @param array $parameters PATCH Parameters + * @param array $headers Reconfigure the request headers for this call only + * + * @return array Data + */ + public function patch($path, array $parameters = array(), array $headers = array()); + + /** + * Send a PUT request + * + * @param string $path Request path + * @param array $parameters PUT Parameters + * @param array $headers Reconfigure the request headers for this call only + * + * @return array Data + */ + public function put($path, array $parameters = array(), array $headers = array()); + + /** + * Send a DELETE request + * + * @param string $path Request path + * @param array $parameters DELETE Parameters + * @param array $headers Reconfigure the request headers for this call only + * + * @return array Data + */ + public function delete($path, array $parameters = array(), array $headers = array()); + + /** + * Send a request to the server, receive a response, + * decode the response and returns an associative array + * + * @param string $path Request API path + * @param array $parameters Parameters + * @param string $httpMethod HTTP method to use + * @param array $headers Request headers + * + * @return array Data + */ + public function request($path, array $parameters = array(), $httpMethod = 'GET', array $headers = array()); + + /** + * Change an option value. + * + * @param string $name The option name + * @param mixed $value The value + * + * @throws InvalidArgumentException + */ + public function setOption($name, $value); + + /** + * Set HTTP headers + * + * @param array $headers + */ + public function setHeaders(array $headers); +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/AuthListener.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/AuthListener.php new file mode 100644 index 0000000000000000000000000000000000000000..27164112280cd918457cbaa4af00b0fc4afc453c --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/AuthListener.php @@ -0,0 +1,95 @@ +<?php namespace Gitlab\HttpClient\Listener; + +use Gitlab\Client; +use Gitlab\Exception\InvalidArgumentException; + +use Buzz\Listener\ListenerInterface; +use Buzz\Message\MessageInterface; +use Buzz\Message\RequestInterface; +use Buzz\Util\Url; + +/** + * @author Joseph Bielawski <stloyd@gmail.com> + * @author Matt Humphrey <matt@m4tt.co> + */ +class AuthListener implements ListenerInterface +{ + /** + * @var string + */ + private $method; + + /** + * @var string + */ + private $token; + + /** + * @var string|null + */ + private $sudo; + + /** + * @param string $method + * @param string $token + * @param string|null $sudo + */ + public function __construct($method, $token, $sudo = null) + { + $this->method = $method; + $this->token = $token; + $this->sudo = $sudo; + } + + /** + * {@inheritDoc} + * + * @throws InvalidArgumentException + */ + public function preSend(RequestInterface $request) + { + // Skip by default + if (null === $this->method) { + return; + } + + switch ($this->method) { + case Client::AUTH_HTTP_TOKEN: + $request->addHeader('PRIVATE-TOKEN: '.$this->token); + if (!is_null($this->sudo)) { + $request->addHeader('SUDO: '.$this->sudo); + } + break; + + case Client::AUTH_URL_TOKEN: + $url = $request->getUrl(); + + $query = array( + 'private_token' => $this->token + ); + + if (!is_null($this->sudo)) { + $query['sudo'] = $this->sudo; + } + + $url .= (false === strpos($url, '?') ? '?' : '&').utf8_encode(http_build_query($query, '', '&')); + + $request->fromUrl(new Url($url)); + break; + + case Client::AUTH_OAUTH_TOKEN: + $request->addHeader('Authorization: Bearer '.$this->token); + if (!is_null($this->sudo)) { + $request->addHeader('SUDO: '.$this->sudo); + } + break; + } + } + + /** + * {@inheritDoc} + */ + public function postSend(RequestInterface $request, MessageInterface $response) + { + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/ErrorListener.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/ErrorListener.php new file mode 100644 index 0000000000000000000000000000000000000000..cb2acc68b21af5b17ef4b4b822333c4f7da757fd --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/ErrorListener.php @@ -0,0 +1,97 @@ +<?php namespace Gitlab\HttpClient\Listener; + +use Buzz\Listener\ListenerInterface; +use Buzz\Message\MessageInterface; +use Buzz\Message\RequestInterface; +use Gitlab\Exception\ErrorException; +use Gitlab\Exception\RuntimeException; + +/** + * @author Joseph Bielawski <stloyd@gmail.com> + * @author Matt Humphrey <git@m4tt.co> + */ +class ErrorListener implements ListenerInterface +{ + /** + * @var array + */ + private $options; + + /** + * @param array $options + */ + public function __construct(array $options) + { + $this->options = $options; + } + + /** + * {@inheritDoc} + */ + public function preSend(RequestInterface $request) + { + } + + /** + * {@inheritDoc} + */ + public function postSend(RequestInterface $request, MessageInterface $response) + { + /** @var $response \Gitlab\HttpClient\Message\Response */ + if ($response->isClientError() || $response->isServerError()) { + $content = $response->getContent(); + if (is_array($content) && isset($content['message'])) { + if (400 == $response->getStatusCode()) { + $message = $this->parseMessage($content['message']); + + throw new ErrorException($message, 400); + } + } + + $errorMessage = null; + if (isset($content['error'])) { + $errorMessage = $content['error']; + if (is_array($content['error'])) { + $errorMessage = implode("\n", $content['error']); + } + } elseif (isset($content['message'])) { + $errorMessage = $this->parseMessage($content['message']); + } else { + $errorMessage = $content; + } + + throw new RuntimeException($errorMessage, $response->getStatusCode()); + } + } + + /** + * @param mixed $message + * @return string + */ + protected function parseMessage($message) + { + $string = $message; + + if (is_array($message)) { + $format = '"%s" %s'; + $errors = array(); + + foreach ($message as $field => $messages) { + if (is_array($messages)) { + $messages = array_unique($messages); + foreach ($messages as $error) { + $errors[] = sprintf($format, $field, $error); + } + } elseif (is_integer($field)) { + $errors[] = $messages; + } else { + $errors[] = sprintf($format, $field, $messages); + } + } + + $string = implode(', ', $errors); + } + + return $string; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/PaginationListener.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/PaginationListener.php new file mode 100644 index 0000000000000000000000000000000000000000..80ba39ea96586fc667251b33f7824cb3b3dd4f3d --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Listener/PaginationListener.php @@ -0,0 +1,38 @@ +<?php namespace Gitlab\HttpClient\Listener; + +use Buzz\Listener\ListenerInterface; +use Buzz\Message\MessageInterface; +use Buzz\Message\RequestInterface; + +class PaginationListener implements ListenerInterface +{ + /** + * {@inheritDoc} + */ + public function preSend(RequestInterface $request) + { + } + + /** + * {@inheritDoc} + */ + public function postSend(RequestInterface $request, MessageInterface $response) + { + $header = $response->getHeader('Link'); + + if (empty($header)) { + return null; + } + + $pagination = array(); + foreach (explode(',', $header) as $link) { + preg_match('/<(.*)>; rel="(.*)"/i', trim($link, ','), $match); + + if (3 === count($match)) { + $pagination[$match[2]] = $match[1]; + } + } + + $response->setPagination($pagination); + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/FormRequest.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/FormRequest.php new file mode 100644 index 0000000000000000000000000000000000000000..ecd05e17d8edbb957f530b78e12c66bd4c42a935 --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/FormRequest.php @@ -0,0 +1,8 @@ +<?php namespace Gitlab\HttpClient\Message; + +use Buzz\Message\Form\FormRequest as BaseFormRequest; + +class FormRequest extends BaseFormRequest +{ + +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/Request.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/Request.php new file mode 100644 index 0000000000000000000000000000000000000000..41a950f35f3292a50ec7a06a4d4440ce3a20eadc --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/Request.php @@ -0,0 +1,8 @@ +<?php namespace Gitlab\HttpClient\Message; + +use Buzz\Message\Request as BaseRequest; + +class Request extends BaseRequest +{ + +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/Response.php b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/Response.php new file mode 100644 index 0000000000000000000000000000000000000000..e5746e0b8c26ff6aa5517c9fd2363a7b02c717a6 --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/lib/Gitlab/HttpClient/Message/Response.php @@ -0,0 +1,48 @@ +<?php namespace Gitlab\HttpClient\Message; + +use Buzz\Message\Response as BaseResponse; + +class Response extends BaseResponse +{ + /** + * @var array pagination + * See PaginationListener + */ + protected $pagination = array(); + + /** + * @return mixed + */ + public function getPagination() + { + return $this->pagination; + } + + /** + * @param array $pagination + */ + public function setPagination(array $pagination) + { + $this->pagination = $pagination; + } + + /** + * {@inheritDoc} + */ + public function getContent() + { + $response = parent::getContent(); + + if ($this->getHeader('Content-Type') === 'application/json') { + $content = json_decode($response, true); + + if (JSON_ERROR_NONE !== json_last_error()) { + return $response; + } + + return $content; + } + + return $response; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/phpunit.xml.dist b/vendor/m4tthumphrey/php-gitlab-api/phpunit.xml.dist new file mode 100644 index 0000000000000000000000000000000000000000..e01386f15e1d1938f4f166c60ffdb9a2d34f418c --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/phpunit.xml.dist @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<phpunit backupGlobals="false" + backupStaticAttributes="false" + colors="true" + convertErrorsToExceptions="true" + convertNoticesToExceptions="true" + convertWarningsToExceptions="true" + processIsolation="false" + stopOnFailure="false" + syntaxCheck="false" + bootstrap="test/bootstrap.php" + > + <testsuites> + <testsuite name="php-gitlab-api Test Suite"> + <directory>./test/Gitlab/</directory> + </testsuite> + </testsuites> + + <filter> + <whitelist> + <directory suffix=".php">./lib/Gitlab/</directory> + </whitelist> + </filter> +</phpunit> \ No newline at end of file diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/AbstractApiTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/AbstractApiTest.php new file mode 100644 index 0000000000000000000000000000000000000000..aa1eeaea2885e0a0e712c67c1f53414bfb52493b --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/AbstractApiTest.php @@ -0,0 +1,177 @@ +<?php namespace Gitlab\Tests\Api; + +use Gitlab\Api\AbstractApi; +use Gitlab\Client; +use Gitlab\HttpClient\Message\Response; + +class AbstractApiTest extends TestCase +{ + /** + * @test + */ + public function shouldPassGETRequestToClient() + { + $response = $this->getResponse('value'); + + $httpClient = $this->getHttpMock(); + $httpClient + ->expects($this->any()) + ->method('get') + ->with('/path', array('param1' => 'param1value'), array('header1' => 'header1value')) + ->will($this->returnValue($response)); + + $client = $this->getClientMock(); + $client->setHttpClient($httpClient); + + $api = $this->getAbstractApiObject($client); + $this->assertEquals('value', $api->get('/path', array('param1' => 'param1value'), array('header1' => 'header1value'))); + } + + /** + * @test + */ + public function shouldPassPOSTRequestToClient() + { + $response = $this->getResponse('value'); + + $httpClient = $this->getHttpMock(); + $httpClient + ->expects($this->any()) + ->method('post') + ->with('/path', array('param1' => 'param1value'), array('header1' => 'header1value')) + ->will($this->returnValue($response)); + + $client = $this->getClientMock(); + $client->setHttpClient($httpClient); + + $api = $this->getAbstractApiObject($client); + $this->assertEquals('value', $api->post('/path', array('param1' => 'param1value'), array('header1' => 'header1value'))); + } + + /** + * @test + */ + public function shouldPassPUTRequestToClient() + { + $response = $this->getResponse('value'); + + $httpClient = $this->getHttpMock(); + $httpClient + ->expects($this->any()) + ->method('put') + ->with('/path', array('param1' => 'param1value'), array('header1' => 'header1value')) + ->will($this->returnValue($response)); + + $client = $this->getClientMock(); + $client->setHttpClient($httpClient); + + $api = $this->getAbstractApiObject($client); + $this->assertEquals('value', $api->put('/path', array('param1' => 'param1value'), array('header1' => 'header1value'))); + } + + /** + * @test + */ + public function shouldPassDELETERequestToClient() + { + $response = $this->getResponse('value'); + + $httpClient = $this->getHttpMock(); + $httpClient + ->expects($this->any()) + ->method('delete') + ->with('/path', array('param1' => 'param1value'), array('header1' => 'header1value')) + ->will($this->returnValue($response)); + + $client = $this->getClientMock(); + $client->setHttpClient($httpClient); + + $api = $this->getAbstractApiObject($client); + $this->assertEquals('value', $api->delete('/path', array('param1' => 'param1value'), array('header1' => 'header1value'))); + } + + /** + * @test + */ + public function shouldPassPATCHRequestToClient() + { + $response = $this->getResponse('value'); + + $httpClient = $this->getHttpMock(); + $httpClient + ->expects($this->any()) + ->method('patch') + ->with('/path', array('param1' => 'param1value'), array('header1' => 'header1value')) + ->will($this->returnValue($response)); + + $client = $this->getClientMock(); + $client->setHttpClient($httpClient); + + $api = $this->getAbstractApiObject($client); + $this->assertEquals('value', $api->patch('/path', array('param1' => 'param1value'), array('header1' => 'header1value'))); + } + + /** + * @param mixed $value + * @return Response + */ + protected function getResponse($value) + { + $response = new Response(); + $response->setContent($value); + + return $response; + } + + /** + * @param Client $client + * @return AbstractApiTestInstance + */ + protected function getAbstractApiObject(Client $client) + { + return new AbstractApiTestInstance($client); + } +} + +class AbstractApiTestInstance extends AbstractApi +{ + /** + * {@inheritDoc} + */ + public function get($path, array $parameters = array(), $requestHeaders = array()) + { + return parent::get($path, $parameters, $requestHeaders); + } + + /** + * {@inheritDoc} + */ + public function post($path, array $parameters = array(), $requestHeaders = array(), array $files = array()) + { + return parent::post($path, $parameters, $requestHeaders, $files); + } + + /** + * {@inheritDoc} + */ + public function patch($path, array $parameters = array(), $requestHeaders = array()) + { + return parent::patch($path, $parameters, $requestHeaders); + } + + /** + * {@inheritDoc} + */ + public function put($path, array $parameters = array(), $requestHeaders = array()) + { + return parent::put($path, $parameters, $requestHeaders); + } + + /** + * {@inheritDoc} + */ + public function delete($path, array $parameters = array(), $requestHeaders = array()) + { + return parent::delete($path, $parameters, $requestHeaders); + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ApiTestCase.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ApiTestCase.php new file mode 100644 index 0000000000000000000000000000000000000000..a695d97cb8007b5ef05014099192368a099403bc --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ApiTestCase.php @@ -0,0 +1,23 @@ +<?php namespace Gitlab\Tests\Api; + +abstract class ApiTestCase extends TestCase +{ + abstract protected function getApiClass(); + + /** + * @param array $methods + * @return \PHPUnit_Framework_MockObject_MockObject|mixed + */ + protected function getApiMock($methods = array()) + { + $client = $this->getClientMock(); + + $methods = array_merge(array('get', 'post', 'postRaw', 'patch', 'delete', 'put', 'head'), $methods); + + return $this->getMockBuilder($this->getApiClass()) + ->setMethods($methods) + ->setConstructorArgs(array($client)) + ->getMock() + ; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/DeployKeysTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/DeployKeysTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a17dd312c3d16fa85fc8f5f4d3e24ef3e4755c06 --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/DeployKeysTest.php @@ -0,0 +1,51 @@ +<?php namespace Gitlab\Tests\Api; + +class DeployKeysTest extends ApiTestCase +{ + /** + * @test + */ + public function shouldGetAllDeployKeys() + { + $expectedArray = $this->getMultipleDeployKeysData(); + + $api = $this->getMultipleDeployKeysRequestMock('deploy_keys', $expectedArray); + + $this->assertEquals($expectedArray, $api->all()); + } + + protected function getMultipleDeployKeysRequestMock($path, $expectedArray = array(), $page = 1, $per_page = 20, $order_by = 'id', $sort = 'asc') + { + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with($path, array('page' => $page, 'per_page' => $per_page, 'order_by' => $order_by, 'sort' => $sort)) + ->will($this->returnValue($expectedArray)) + ; + + return $api; + } + + protected function getMultipleDeployKeysData() + { + return array( + array( + 'id' => 1, + 'title' => 'Public key', + 'key' => 'ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=', + 'created_at' => '2013-10-02T10:12:29Z' + ), + array( + 'id' => 3, + 'title' => 'Another Public key', + 'key' => 'ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=', + 'created_at' => '2013-10-02T11:12:29Z' + ) + ); + } + + protected function getApiClass() + { + return 'Gitlab\Api\DeployKeys'; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/GroupsTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/GroupsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..20fd1fd58f3590d329e2fcae590ae36829e9628d --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/GroupsTest.php @@ -0,0 +1,264 @@ +<?php namespace Gitlab\Tests\Api; + +use Gitlab\Api\AbstractApi; + +class GroupsTest extends ApiTestCase +{ + /** + * @test + */ + public function shouldGetAllGroups() + { + $expectedArray = array( + array('id' => 1, 'name' => 'A group'), + array('id' => 2, 'name' => 'Another group'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('groups', array('page' => 1, 'per_page' => 10)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->all(1, 10)); + } + + /** + * @test + */ + public function shouldNotNeedPaginationWhenGettingGroups() + { + $expectedArray = array( + array('id' => 1, 'name' => 'A group'), + array('id' => 2, 'name' => 'Another group'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('groups', array('page' => 1, 'per_page' => AbstractApi::PER_PAGE)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->all()); + } + + /** + * @test + */ + public function shouldSearchGroups() + { + $expectedArray = array( + array('id' => 1, 'name' => 'A group'), + array('id' => 2, 'name' => 'Another group'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('groups?search=some%20group', array('page' => 1, 'per_page' => AbstractApi::PER_PAGE)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->search('some group')); + } + + /** + * @test + */ + public function shouldSearchGroupsWithPagination() + { + $expectedArray = array( + array('id' => 1, 'name' => 'A group'), + array('id' => 2, 'name' => 'Another group'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('groups?search=group', array('page' => 2, 'per_page' => 5)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->search('group', 2, 5)); + } + + /** + * @test + */ + public function shouldShowGroup() + { + $expectedArray = array('id' => 1, 'name' => 'A group'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('groups/1') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->show(1)); + } + + /** + * @test + */ + public function shouldCreateGroup() + { + $expectedArray = array('id' => 1, 'name' => 'A new group'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('groups', array('name' => 'A new group', 'path' => 'a-new-group', 'description' => null, 'visibility_level' => 0)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->create('A new group', 'a-new-group')); + } + + /** + * @test + */ + public function shouldCreateGroupWithDescriptionAndVisLevel() + { + $expectedArray = array('id' => 1, 'name' => 'A new group', 'visibility_level' => 2); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('groups', array('name' => 'A new group', 'path' => 'a-new-group', 'description' => 'Description', 'visibility_level' => 2)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->create('A new group', 'a-new-group', 'Description', 2)); + } + + /** + * @test + */ + public function shouldUpdateGroup() + { + $expectedArray = array('id' => 3, 'name' => 'Group name', 'path' => 'group-path'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('groups/3', array('name' => 'Group name', 'path' => 'group-path')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->update(3, array('name' => 'Group name', 'path' => 'group-path'))); + } + + /** + * @test + */ + public function shouldTransferProjectToGroup() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('groups/1/projects/2') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->transfer(1, 2)); + } + + /** + * @test + */ + public function shouldGetMembers() + { + $expectedArray = array( + array('id' => 1, 'name' => 'Matt'), + array('id' => 2, 'name' => 'Bob') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('groups/1/members') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->members(1)); + } + + /** + * @test + */ + public function shouldAddMember() + { + $expectedArray = array('id' => 1, 'name' => 'Matt'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('groups/1/members', array('user_id' => 2, 'access_level' => 3)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->addMember(1, 2, 3)); + } + + /** + * @test + */ + public function shouldSaveMember() + { + $expectedArray = array('id' => 1, 'name' => 'Matt'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('groups/1/members/2', array('access_level' => 4)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->saveMember(1, 2, 4)); + } + + /** + * @test + */ + public function shouldRemoveMember() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('groups/1/members/2') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->removeMember(1, 2)); + } + + /** + * @test + */ + public function shouldRemoveGroup() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('groups/1') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->remove(1)); + } + + protected function getApiClass() + { + return 'Gitlab\Api\Groups'; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/IssuesTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/IssuesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8c656f003a2878d7a11d25e0098cdd181499cea2 --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/IssuesTest.php @@ -0,0 +1,279 @@ +<?php namespace Gitlab\Tests\Api; + +use Gitlab\Api\AbstractApi; + +class IssuesTest extends ApiTestCase +{ + /** + * @test + */ + public function shouldGetAllIssues() + { + $expectedArray = array( + array('id' => 1, 'title' => 'An issue'), + array('id' => 2, 'title' => 'Another issue'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('issues', array('page' => 1, 'per_page' => AbstractApi::PER_PAGE)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->all()); + } + + /** + * @test + */ + public function shouldGetProjectIssuesWithPagination() + { + $expectedArray = array( + array('id' => 1, 'title' => 'An issue'), + array('id' => 2, 'title' => 'Another issue'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/issues', array('page' => 2, 'per_page' => 5)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->all(1, 2, 5)); + } + + /** + * @test + */ + public function shouldGetProjectIssuesWithParams() + { + $expectedArray = array( + array('id' => 1, 'title' => 'An issue'), + array('id' => 2, 'title' => 'Another issue'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/issues', array('page' => 2, 'per_page' => 5, 'order_by' => 'created_at', 'sort' => 'desc', 'labels' => 'foo,bar', 'state' => 'open')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->all(1, 2, 5, array('order_by' => 'created_at', 'sort' => 'desc', 'labels' => 'foo,bar', 'state' => 'open'))); + } + + /** + * @test + */ + public function shouldShowIssue() + { + $expectedArray = array('id' => 2, 'title' => 'Another issue'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/issues?iid=2') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->show(1, 2)); + } + + /** + * @test + */ + public function shouldCreateIssue() + { + $expectedArray = array('id' => 3, 'title' => 'A new issue'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/issues', array('title' => 'A new issue', 'labels' => 'foo,bar')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->create(1, array('title' => 'A new issue', 'labels' => 'foo,bar'))); + } + + /** + * @test + */ + public function shouldUpdateIssue() + { + $expectedArray = array('id' => 2, 'title' => 'A renamed issue'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/issues/2', array('title' => 'A renamed issue', 'labels' => 'foo')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->update(1, 2, array('title' => 'A renamed issue', 'labels' => 'foo'))); + } + + /** + * @test + */ + public function shouldGetIssueComments() + { + $expectedArray = array( + array('id' => 1, 'body' => 'A comment'), + array('id' => 2, 'body' => 'Another comment') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/issues/2/notes') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->showComments(1, 2)); + } + + /** + * @test + */ + public function shouldGetIssueComment() + { + $expectedArray = array('id' => 3, 'body' => 'A new comment'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/issues/2/notes/3') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->showComment(1, 2, 3)); + } + + /** + * @test + */ + public function shouldCreateComment() + { + $expectedArray = array('id' => 3, 'body' => 'A new comment'); + + $api = $this->getApiMock(); + $api->expects($this->exactly(2)) + ->method('post') + ->with('projects/1/issues/2/notes', array('body' => 'A new comment')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->addComment(1, 2, array('body' => 'A new comment'))); + $this->assertEquals($expectedArray, $api->addComment(1, 2, 'A new comment')); + } + + /** + * @test + */ + public function shouldUpdateComment() + { + $expectedArray = array('id' => 3, 'body' => 'An edited comment'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/issues/2/notes/3', array('body' => 'An edited comment')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->updateComment(1, 2, 3, 'An edited comment')); + } + + /** + * @test + */ + public function shouldSetTimeEstimate() + { + $expectedArray = array('time_estimate' => 14400, 'total_time_spent' => 0, 'human_time_estimate' => '4h', 'human_total_time_spent' => null); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/issues/2/time_estimate', array('duration' => '4h')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->setTimeEstimate(1, 2, '4h')); + } + + /** + * @test + */ + public function shouldResetTimeEstimate() + { + $expectedArray = array('time_estimate' => 0, 'total_time_spent' => 0, 'human_time_estimate' => null, 'human_total_time_spent' => null); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/issues/2/reset_time_estimate') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->resetTimeEstimate(1, 2)); + } + + /** + * @test + */ + public function shouldAddSpentTime() + { + $expectedArray = array('time_estimate' => 0, 'total_time_spent' => 14400, 'human_time_estimate' => null, 'human_total_time_spent' => '4h'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/issues/2/add_spent_time', array('duration' => '4h')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->addSpentTime(1, 2, '4h')); + } + + /** + * @test + */ + public function shouldResetSpentTime() + { + $expectedArray = array('time_estimate' => 0, 'total_time_spent' => 0, 'human_time_estimate' => null, 'human_total_time_spent' => null); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/issues/2/reset_spent_time') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->resetSpentTime(1, 2)); + } + + /** + * @test + */ + public function shouldGetIssueTimeStats() + { + $expectedArray = array('time_estimate' => 14400, 'total_time_spent' => 5400, 'human_time_estimate' => '4h', 'human_total_time_spent' => '1h 30m'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/issues/2/time_stats') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->getTimeStats(1, 2)); + } + + protected function getApiClass() + { + return 'Gitlab\Api\Issues'; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/KeysTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/KeysTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2f9e94b7a58b5c4c4d55e8068eb29f2049c258df --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/KeysTest.php @@ -0,0 +1,26 @@ +<?php namespace Gitlab\Tests\Api; + +use Gitlab\Api\AbstractApi; + +class KeysTest extends ApiTestCase +{ + /** + * @test + */ + public function shouldShowKey() + { + $expectedArray = array('id' => 1, 'title' => 'A key', 'key' => 'ssh-rsa key', 'created_at' => '2016-01-01T01:00:00.000Z'); + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('keys/1') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->show(1)); + } + + protected function getApiClass() + { + return 'Gitlab\Api\Keys'; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/MergeRequestsTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/MergeRequestsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..bd6e6eb2b70523e3ea2b0ad365c2312e34b19daf --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/MergeRequestsTest.php @@ -0,0 +1,368 @@ +<?php namespace Gitlab\Tests\Api; + +use Gitlab\Api\AbstractApi; +use Gitlab\Api\MergeRequests; + +class MergeRequestsTest extends ApiTestCase +{ + /** + * @test + */ + public function shouldGetMergeRequestListWithDefaultParams() + { + $expectedArray = $this->getMultipleMergeRequestsData(); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/merge_requests', array('page' => 1, 'per_page' => AbstractApi::PER_PAGE, 'state' => MergeRequests::STATE_ALL, 'order_by' => MergeRequests::ORDER_BY, 'sort' => MergeRequests::SORT)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->getList(1)); + } + + /** + * @test + */ + public function shouldGetAll() + { + $expectedArray = $this->getMultipleMergeRequestsData(); + + $api = $this->getApiMock(array('getList')); + $api->expects($this->once()) + ->method('getList') + ->with(1, MergeRequests::STATE_ALL, 1, AbstractApi::PER_PAGE, MergeRequests::ORDER_BY, MergeRequests::SORT) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->all(1)); + } + + /** + * @test + */ + public function shouldGetAllWithParams() + { + $expectedArray = $this->getMultipleMergeRequestsData(); + + $api = $this->getApiMock(array('getList')); + $api->expects($this->once()) + ->method('getList') + ->with(1, MergeRequests::STATE_ALL, 2, 5, 'title', 'desc') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->all(1, 2, 5, 'title', 'desc')); + } + + /** + * @test + */ + public function shouldGetMerged() + { + $expectedArray = $this->getMultipleMergeRequestsData(); + + $api = $this->getApiMock(array('getList')); + $api->expects($this->once()) + ->method('getList') + ->with(1, MergeRequests::STATE_MERGED, 1, AbstractApi::PER_PAGE, MergeRequests::ORDER_BY, MergeRequests::SORT) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->merged(1)); + } + + /** + * @test + */ + public function shouldGetMergedWithParams() + { + $expectedArray = $this->getMultipleMergeRequestsData(); + + $api = $this->getApiMock(array('getList')); + $api->expects($this->once()) + ->method('getList') + ->with(1, MergeRequests::STATE_MERGED, 3, 15, 'updated_at', 'asc') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->merged(1, 3, 15, 'updated_at', 'asc')); + } + + /** + * @test + */ + public function shouldGetOpened() + { + $expectedArray = $this->getMultipleMergeRequestsData(); + + $api = $this->getApiMock(array('getList')); + $api->expects($this->once()) + ->method('getList') + ->with(1, MergeRequests::STATE_OPENED, 1, AbstractApi::PER_PAGE, MergeRequests::ORDER_BY, MergeRequests::SORT) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->opened(1)); + } + + /** + * @test + */ + public function shouldGetOpenedWithParams() + { + $expectedArray = $this->getMultipleMergeRequestsData(); + + $api = $this->getApiMock(array('getList')); + $api->expects($this->once()) + ->method('getList') + ->with(1, MergeRequests::STATE_OPENED, 2, 4, 'title', 'desc') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->opened(1, 2, 4, 'title', 'desc')); + } + + /** + * @test + */ + public function shouldGetClosed() + { + $expectedArray = $this->getMultipleMergeRequestsData(); + + $api = $this->getApiMock(array('getList')); + $api->expects($this->once()) + ->method('getList') + ->with(1, MergeRequests::STATE_CLOSED, 1, AbstractApi::PER_PAGE, MergeRequests::ORDER_BY, MergeRequests::SORT) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->closed(1)); + } + + /** + * @test + */ + public function shouldGetClosedWithParams() + { + $expectedArray = $this->getMultipleMergeRequestsData(); + + $api = $this->getApiMock(array('getList')); + $api->expects($this->once()) + ->method('getList') + ->with(1, MergeRequests::STATE_CLOSED, 2, 4, 'title', 'desc') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->closed(1, 2, 4, 'title', 'desc')); + } + + /** + * @test + */ + public function shouldShowMergeRequest() + { + $expectedArray = array('id' => 2, 'name' => 'A merge request'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/merge_request/2') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->show(1, 2)); + } + + /** + * @test + */ + public function shouldCreateMergeRequestWithoutOptionalParams() + { + $expectedArray = array('id' => 3, 'title' => 'Merge Request'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/merge_requests', array( + 'title' => 'Merge Request', + 'target_branch' => 'master', + 'source_branch' => 'develop', + 'description' => null, + 'assignee_id' => null, + 'target_project_id' => null + )) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->create(1, 'develop', 'master', 'Merge Request')); + } + + /** + * @test + */ + public function shouldCreateMergeRequestWithOptionalParams() + { + $expectedArray = array('id' => 3, 'title' => 'Merge Request'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/merge_requests', array( + 'title' => 'Merge Request', + 'target_branch' => 'master', + 'source_branch' => 'develop', + 'description' => 'Some changes', + 'assignee_id' => 6, + 'target_project_id' => 20 + )) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->create(1, 'develop', 'master', 'Merge Request', 6, 20, 'Some changes')); + } + + /** + * @test + */ + public function shouldUpdateMergeRequest() + { + $expectedArray = array('id' => 2, 'title' => 'Updated title'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/merge_request/2', array('title' => 'Updated title', 'description' => 'No so many changes now', 'state_event' => 'close')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->update(1, 2, array( + 'title' => 'Updated title', + 'description' => 'No so many changes now', + 'state_event' => 'close' + ))); + } + + /** + * @test + */ + public function shouldMergeMergeRequest() + { + $expectedArray = array('id' => 2, 'title' => 'Updated title'); + + $api = $this->getApiMock(); + $api->expects($this->exactly(2)) + ->method('put') + ->with('projects/1/merge_request/2/merge', array('merge_commit_message' => 'Accepted')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->merge(1, 2, 'Accepted')); + $this->assertEquals($expectedArray, $api->merge(1, 2, array('merge_commit_message' => 'Accepted'))); + } + + /** + * @test + */ + public function shouldGetMergeRequestNotes() + { + $expectedArray = array( + array('id' => 1, 'body' => 'A comment'), + array('id' => 2, 'body' => 'Another comment') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/merge_requests/2/notes') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->showNotes(1, 2)); + } + + /** + * @test + */ + public function shouldGetMergeRequestComments() + { + $expectedArray = array( + array('id' => 1, 'note' => 'A comment'), + array('id' => 2, 'note' => 'Another comment') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/merge_request/2/comments') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->showComments(1, 2)); + } + + /** + * @test + */ + public function shouldAddMergeRequestComment() + { + $expectedArray = array('id' => 2, 'title' => 'A comment'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/merge_request/2/comments', array('note' => 'A comment')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->addComment(1, 2, 'A comment')); + } + + /** + * @test + */ + public function shouldGetMergeRequestChanges() + { + $expectedArray = array('id' => 1, 'title' => 'A merge request'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/merge_request/2/changes') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->changes(1, 2)); + } + + /** + * @test + */ + public function shouldGetMergeRequestByIid() + { + $expectedArray = array('id' => 1, 'title' => 'A merge request'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/merge_requests', array('iid' => 2)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->getByIid(1, 2)); + } + + protected function getMultipleMergeRequestsData() + { + return array( + array('id' => 1, 'title' => 'A merge request'), + array('id' => 2, 'title' => 'Another merge request') + ); + } + + protected function getApiClass() + { + return 'Gitlab\Api\MergeRequests'; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/MilestonesTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/MilestonesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e22c2370ff9dfbc49db5087284329da980253438 --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/MilestonesTest.php @@ -0,0 +1,100 @@ +<?php namespace Gitlab\Tests\Api; + +class MilestonesTest extends ApiTestCase +{ + /** + * @test + */ + public function shouldGetAllMilestones() + { + $expectedArray = array( + array('id' => 1, 'title' => 'A milestone'), + array('id' => 2, 'title' => 'Another milestone'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/milestones') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->all(1)); + } + + /** + * @test + */ + public function shouldShowMilestone() + { + $expectedArray = array('id' => 1, 'name' => 'A milestone'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/milestones/2') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->show(1, 2)); + } + + /** + * @test + */ + public function shouldCreateMilestone() + { + $expectedArray = array('id' => 3, 'title' => 'A new milestone'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/milestones', array('description' => 'Some text', 'title' => 'A new milestone')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->create(1, array('description' => 'Some text', 'title' => 'A new milestone'))); + } + + /** + * @test + */ + public function shouldUpdateMilestone() + { + $expectedArray = array('id' => 3, 'title' => 'Updated milestone'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/milestones/3', array('title' => 'Updated milestone', 'due_date' => '2015-04-01', 'state_event' => 'close')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->update(1, 3, array('title' => 'Updated milestone', 'due_date' => '2015-04-01', 'state_event' => 'close'))); + } + + /** + * @test + */ + public function shouldGetMilestonesIssues() + { + $expectedArray = array( + array('id' => 1, 'title' => 'An issue'), + array('id' => 2, 'title' => 'Another issue'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/milestones/3/issues') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->issues(1, 3)); + } + + protected function getApiClass() + { + return 'Gitlab\Api\Milestones'; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ProjectNamespacesTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ProjectNamespacesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1feb5ff1f4146d0b9e020a2ec4f601364aebf5ce --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ProjectNamespacesTest.php @@ -0,0 +1,70 @@ +<?php namespace Gitlab\Tests\Api; + +use Gitlab\Api\AbstractApi; + +class ProjectNamespacesTest extends ApiTestCase +{ + /** + * @test + */ + public function shouldGetAllNamespaces() + { + $expectedArray = array( + array('id' => 1, 'name' => 'bespokes'), + array('id' => 2, 'name' => 'internal') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('namespaces', array('page' => 1, 'per_page' => 10)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->all(1, 10)); + } + + /** + * @test + */ + public function shouldNotNeedPaginationWhenGettingNamespaces() + { + $expectedArray = array( + array('id' => 1, 'name' => 'bespokes'), + array('id' => 2, 'name' => 'internal') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('namespaces', array('page' => 1, 'per_page' => AbstractApi::PER_PAGE)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->all()); + } + /** + * @test + */ + public function shouldSearchNamespaces() + { + $expectedArray = array( + array('id' => 1, 'name' => 'bespokes'), + array('id' => 2, 'name' => 'internal') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('namespaces', array('search' => 'term', 'page' => 1, 'per_page' => 10)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->search('term', 1, 10)); + } + + protected function getApiClass() + { + return 'Gitlab\Api\ProjectNamespaces'; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ProjectsTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ProjectsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..47bb26432f1ddc721cf609e2b524ffcd2a31c65c --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/ProjectsTest.php @@ -0,0 +1,1098 @@ +<?php namespace Gitlab\Tests\Api; + +use Gitlab\Api\AbstractApi; +use Gitlab\Api\Projects; + +class ProjectsTest extends ApiTestCase +{ + /** + * @test + */ + public function shouldGetAllProjects() + { + $expectedArray = $this->getMultipleProjectsData(); + + $api = $this->getMultipleProjectsRequestMock('projects/all', $expectedArray); + + $this->assertEquals($expectedArray, $api->all()); + } + + /** + * @test + */ + public function shouldGetAllProjectsSortedByName() + { + $expectedArray = $this->getMultipleProjectsData(); + + $api = $this->getMultipleProjectsRequestMock('projects/all', $expectedArray, 1, 5, 'name', 'asc'); + + $this->assertEquals($expectedArray, $api->all(1, 5, 'name')); + } + + /** + * @test + */ + public function shouldNotNeedPaginationWhenGettingProjects() + { + $expectedArray = $this->getMultipleProjectsData(); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/all', array('page' => 1, 'per_page' => AbstractApi::PER_PAGE, 'order_by' => Projects::ORDER_BY, 'sort' => Projects::SORT)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->all()); + } + + /** + * @test + */ + public function shouldGetAccessibleProjects() + { + $expectedArray = $this->getMultipleProjectsData(); + + $api = $this->getMultipleProjectsRequestMock('projects', $expectedArray, 2, 7); + + $this->assertEquals($expectedArray, $api->accessible(2, 7)); + } + + /** + * @test + */ + public function shouldGetOwnedProjects() + { + $expectedArray = $this->getMultipleProjectsData(); + + $api = $this->getMultipleProjectsRequestMock('projects?owned=1', $expectedArray, 3, 50); + + $this->assertEquals($expectedArray, $api->owned(3, 50)); + } + + + /** + * @test + */ + public function shouldSearchProjects() + { + $expectedArray = $this->getMultipleProjectsData(); + + $api = $this->getMultipleProjectsRequestMock('projects/search/a%20project', $expectedArray); + $this->assertEquals($expectedArray, $api->search('a project')); + + $api = $this->getMultipleProjectsRequestMock('projects/search/a%2Eproject', $expectedArray); + $this->assertEquals($expectedArray, $api->search('a.project')); + + $api = $this->getMultipleProjectsRequestMock('projects/search/a%2Fproject', $expectedArray); + $this->assertEquals($expectedArray, $api->search('a/project')); + } + + /** + * @test + */ + public function shouldShowProject() + { + $expectedArray = array('id' => 1, 'name' => 'Project Name'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->show(1)); + } + + /** + * @test + */ + public function shouldCreateProject() + { + $expectedArray = array('id' => 1, 'name' => 'Project Name'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects', array('name' => 'Project Name', 'issues_enabled' => true)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->create('Project Name', array( + 'issues_enabled' => true + ))); + } + + /** + * @test + */ + public function shouldUpdateProject() + { + $expectedArray = array('id' => 1, 'name' => 'Updated Name'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1', array('name' => 'Updated Name', 'issues_enabled' => true)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->update(1, array( + 'name' => 'Updated Name', + 'issues_enabled' => true + ))); + } + + /** + * @test + */ + public function shouldArchiveProject() + { + $expectedArray = array('id' => 1, 'archived' => true); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/archive') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->archive(1)); + } + + /** + * @test + */ + public function shouldUnarchiveProject() + { + $expectedArray = array('id' => 1, 'archived' => false); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/unarchive') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->unarchive(1)); + } + + /** + * @test + */ + public function shouldCreateProjectForUser() + { + $expectedArray = array('id' => 1, 'name' => 'Project Name'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/user/1', array('name' => 'Project Name', 'issues_enabled' => true)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->createForUser(1, 'Project Name', array( + 'issues_enabled' => true + ))); + } + + /** + * @test + */ + public function shouldRemoveProject() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->remove(1)); + } + + /** + * @test + */ + public function shouldGetBuilds() + { + $expectedArray = array( + array('id' => 1, 'status' => 'success'), + array('id' => 2, 'status' => 'failed') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/builds') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->builds(1)); + } + + /** + * @test + */ + public function shouldGetBuildsWithScope() + { + $expectedArray = array( + array('id' => 1, 'status' => 'success'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/builds', array('scope' => 'success')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->builds(1, 'success')); + } + + /** + * @test + */ + public function shouldGetBuildsWithMultipleScopes() + { + $expectedArray = array( + array('id' => 1, 'status' => 'success'), + array('id' => 1, 'status' => 'failed'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/builds', array('scope' => array('success', 'failed'))) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->builds(1, array('success', 'failed'))); + } + + /** + * @test + */ + public function shouldGetBuild() + { + $expectedArray = array('id' => 2); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/builds/2') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->build(1, 2)); + } + + /** + * @test + */ + public function shouldGetTrace() + { + $expectedString = 'runner trace of a specific build'; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/builds/2/trace') + ->will($this->returnValue($expectedString)) + ; + + $this->assertEquals($expectedString, $api->trace(1, 2)); + } + + /** + * @test + */ + public function shouldGetPipelines() + { + $expectedArray = array( + array('id' => 1, 'status' => 'success','ref' => 'new-pipeline'), + array('id' => 2, 'status' => 'failed', 'ref' => 'new-pipeline'), + array('id' => 3, 'status' => 'pending', 'ref'=> 'test-pipeline') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/pipelines') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->pipelines(1)); + } + + /** + * @test + */ + public function shouldGetPipeline() + { + $expectedArray = array( + array('id' => 1, 'status' => 'success','ref' => 'new-pipeline'), + array('id' => 2, 'status' => 'failed', 'ref' => 'new-pipeline'), + array('id' => 3, 'status' => 'pending', 'ref'=> 'test-pipeline') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/pipelines/3') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->pipeline(1, 3)); + } + + /** + * @test + */ + public function shouldCreatePipeline() + { + $expectedArray = array( + array('id' => 4, 'status' => 'created', 'ref'=> 'test-pipeline') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/pipelines', array('ref' => 'test-pipeline')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->createPipeline(1, 'test-pipeline')); + } + + /** + * @test + */ + public function shouldRetryPipeline() + { + $expectedArray = array( + array('id' => 5, 'status' => 'pending', 'ref'=> 'test-pipeline') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/pipelines/4/retry') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->retryPipeline(1, 4)); + } + + /** + * @test + */ + public function shouldCancelPipeline() + { + $expectedArray = array( + array('id' => 6, 'status' => 'cancelled', 'ref'=> 'test-pipeline') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/pipelines/6/cancel') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->cancelPipeline(1, 6)); + } + + /** + * @test + */ + public function shouldGetMembers() + { + $expectedArray = array( + array('id' => 1, 'name' => 'Matt'), + array('id' => 2, 'name' => 'Bob') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/members') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->members(1)); + } + + /** + * @test + */ + public function shouldGetMembersWithQuery() + { + $expectedArray = array( + array('id' => 1, 'name' => 'Matt') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/members', array('query' => 'at')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->members(1, 'at')); + } + + /** + * @test + */ + public function shouldGetMember() + { + $expectedArray = array('id' => 2, 'name' => 'Matt'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/members/2') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->member(1, 2)); + } + + /** + * @test + */ + public function shouldAddMember() + { + $expectedArray = array('id' => 1, 'name' => 'Matt'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/members', array('user_id' => 2, 'access_level' => 3)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->addMember(1, 2, 3)); + } + + /** + * @test + */ + public function shouldSaveMember() + { + $expectedArray = array('id' => 1, 'name' => 'Matt'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/members/2', array('access_level' => 4)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->saveMember(1, 2, 4)); + } + + /** + * @test + */ + public function shouldRemoveMember() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/members/2') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->removeMember(1, 2)); + } + + /** + * @test + */ + public function shouldGetHooks() + { + $expectedArray = array( + array('id' => 1, 'name' => 'Test hook'), + array('id' => 2, 'name' => 'Another hook'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/hooks') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->hooks(1)); + } + + /** + * @test + */ + public function shouldGetHook() + { + $expectedArray = array('id' => 2, 'name' => 'Another hook'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/hooks/2') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->hook(1, 2)); + } + + /** + * @test + */ + public function shouldAddHook() + { + $expectedArray = array('id' => 3, 'name' => 'A new hook', 'url' => 'http://www.example.com'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/hooks', array('url' => 'http://www.example.com', 'push_events' => true, 'issues_events' => true, 'merge_requests_events' => true)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->addHook(1, 'http://www.example.com', array('push_events' => true, 'issues_events' => true, 'merge_requests_events' => true))); + } + + /** + * @test + */ + public function shouldAddHookWithOnlyUrl() + { + $expectedArray = array('id' => 3, 'name' => 'A new hook', 'url' => 'http://www.example.com'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/hooks', array('url' => 'http://www.example.com', 'push_events' => true)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->addHook(1, 'http://www.example.com')); + } + + /** + * @test + */ + public function shouldAddHookWithoutPushEvents() + { + $expectedArray = array('id' => 3, 'name' => 'A new hook', 'url' => 'http://www.example.com'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/hooks', array('url' => 'http://www.example.com', 'push_events' => false)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->addHook(1, 'http://www.example.com', array('push_events' => false))); + } + + /** + * @test + */ + public function shouldUpdateHook() + { + $expectedArray = array('id' => 3, 'name' => 'A new hook', 'url' => 'http://www.example.com'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/hooks/3', array('url' => 'http://www.example-test.com', 'push_events' => false)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->updateHook(1, 3, array('url' => 'http://www.example-test.com', 'push_events' => false))); + } + + /** + * @test + */ + public function shouldRemoveHook() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/hooks/2') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->removeHook(1, 2)); + } + + /** + * @test + */ + public function shouldGetKeys() + { + $expectedArray = array( + array('id' => 1, 'title' => 'test-key'), + array('id' => 2, 'title' => 'another-key') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/keys') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->keys(1)); + } + + /** + * @test + */ + public function shouldGetKey() + { + $expectedArray = array('id' => 2, 'title' => 'another-key'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/keys/2') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->key(1, 2)); + } + + /** + * @test + */ + public function shouldAddKey() + { + $expectedArray = array('id' => 3, 'title' => 'new-key'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/keys', array('title' => 'new-key', 'key' => '...')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->addKey(1, 'new-key', '...')); + } + + /** + * @test + */ + public function shouldRemoveKey() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/keys/3') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->removeKey(1, 3)); + } + + /** + * @test + */ + public function shoudEnableKey() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/keys/3/enable') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->enableKey(1, 3)); + } + + /** + * @test + */ + public function shoudDisableKey() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/keys/3/disable') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->disableKey(1, 3)); + } + + /** + * @test + */ + public function shouldGetEvents() + { + $expectedArray = array( + array('id' => 1, 'title' => 'An event'), + array('id' => 2, 'title' => 'Another event') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/events', array( + 'page' => 1, + 'per_page' => AbstractApi::PER_PAGE + )) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->events(1)); + } + + /** + * @test + */ + public function shouldGetEventsWithPagination() + { + $expectedArray = array( + array('id' => 1, 'title' => 'An event'), + array('id' => 2, 'title' => 'Another event') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/events', array( + 'page' => 2, + 'per_page' => 15 + )) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->events(1, 2, 15)); + } + + /** + * @test + */ + public function shouldGetLabels() + { + $expectedArray = array( + array('name' => 'bug', 'color' => '#000000'), + array('name' => 'feature', 'color' => '#ff0000') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/labels') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->labels(1)); + } + + /** + * @test + */ + public function shouldAddLabel() + { + $expectedArray = array('name' => 'bug', 'color' => '#000000'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/labels', array('name' => 'wont-fix', 'color' => '#ffffff')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->addLabel(1, array('name' => 'wont-fix', 'color' => '#ffffff'))); + } + + /** + * @test + */ + public function shouldUpdateLabel() + { + $expectedArray = array('name' => 'bug', 'color' => '#00ffff'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/labels', array('name' => 'bug', 'new_name' => 'big-bug', 'color' => '#00ffff')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->updateLabel(1, array('name' => 'bug', 'new_name' => 'big-bug', 'color' => '#00ffff'))); + } + + /** + * @test + */ + public function shouldRemoveLabel() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/labels', array('name' => 'bug')) + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->removeLabel(1, 'bug')); + } + + /** + * @test + */ + public function shouldCreateForkRelation() + { + $expectedArray = array('project_id' => 1, 'forked_id' => 2); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/fork/2') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->createForkRelation(1, 2)); + } + + /** + * @test + */ + public function shouldRemoveForkRelation() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/2/fork') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->removeForkRelation(2)); + } + + /** + * @test + */ + public function shouldSetService() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/services/hipchat', array('param' => 'value')) + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->setService(1, 'hipchat', array('param' => 'value'))); + } + + /** + * @test + */ + public function shouldRemoveService() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/services/hipchat') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->removeService(1, 'hipchat')); + } + + /** + * @test + */ + public function shouldGetVariables() + { + $expectedArray = array( + array('key' => 'ftp_username', 'value' => 'ftp'), + array('key' => 'ftp_password', 'value' => 'somepassword') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/variables') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->variables(1)); + } + + /** + * @test + */ + public function shouldGetVariable() + { + $expectedArray = array('key' => 'ftp_username', 'value' => 'ftp'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/variables/ftp_username') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->variable(1, 'ftp_username')); + } + + /** + * @test + */ + public function shouldAddVariable() + { + $expectedKey = 'ftp_port'; + $expectedValue = '21'; + + $expectedArray = array( + 'key' => $expectedKey, + 'value' => $expectedValue, + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/variables', $expectedArray) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->addVariable(1, $expectedKey, $expectedValue)); + } + + /** + * @test + */ + public function shouldUpdateVariable() + { + $expectedKey = 'ftp_port'; + $expectedValue = '22'; + + $expectedArray = array( + 'key' => 'ftp_port', + 'value' => '22', + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/variables/'.$expectedKey, array('value' => $expectedValue)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->updateVariable(1, $expectedKey, $expectedValue)); + } + + /** + * @test + */ + public function shouldRemoveVariable() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/variables/ftp_password') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->removeVariable(1, 'ftp_password')); + } + + protected function getMultipleProjectsRequestMock($path, $expectedArray = array(), $page = 1, $per_page = 20, $order_by = 'created_at', $sort = 'asc') + { + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with($path, array('page' => $page, 'per_page' => $per_page, 'order_by' => $order_by, 'sort' => $sort)) + ->will($this->returnValue($expectedArray)) + ; + + return $api; + } + + /** + * @test + */ + public function shouldGetDeployments() + { + $expectedArray = array( + array('id' => 1, 'sha' => '0000001'), + array('id' => 2, 'sha' => '0000002'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/deployments', array( + 'page' => 1, + 'per_page' => AbstractApi::PER_PAGE + )) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->deployments(1)); + } + + /** + * @test + */ + public function shouldGetDeploymentsWithPagination() + { + $expectedArray = array( + array('id' => 1, 'sha' => '0000001'), + array('id' => 2, 'sha' => '0000002'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/deployments', array( + 'page' => 2, + 'per_page' => 15 + )) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->deployments(1, 2, 15)); + } + + protected function getMultipleProjectsData() + { + return array( + array('id' => 1, 'name' => 'A project'), + array('id' => 2, 'name' => 'Another project') + ); + } + + protected function getApiClass() + { + return 'Gitlab\Api\Projects'; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/RepositoriesTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/RepositoriesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a6bffd100c20268850d754ec4226c5aeaeafd027 --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/RepositoriesTest.php @@ -0,0 +1,708 @@ +<?php namespace Gitlab\Tests\Api; + +use Gitlab\Api\AbstractApi; + +class RepositoriesTest extends ApiTestCase +{ + /** + * @test + */ + public function shouldGetBranches() + { + $expectedArray = array( + array('name' => 'master'), + array('name' => 'develop') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/branches') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->branches(1)); + } + + /** + * @test + */ + public function shouldGetBranch() + { + $expectedArray = array('name' => 'master'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/branches/master') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->branch(1, 'master')); + } + + /** + * @test + */ + public function shouldCreateBranch() + { + $expectedArray = array('name' => 'feature'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/repository/branches', array('branch_name' => 'feature', 'ref' => 'master')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->createBranch(1, 'feature', 'master')); + } + + /** + * @test + */ + public function shouldDeleteBranch() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/repository/branches/master') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->deleteBranch(1, 'master')); + } + + /** + * @test + */ + public function shouldProtectBranch() + { + $expectedArray = array('name' => 'master'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/repository/branches/master/protect', array('developers_can_push' => false, 'developers_can_merge' => false)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->protectBranch(1, 'master')); + } + + /** + * @test + */ + public function shouldProtectBranchWithPermissions() + { + $expectedArray = array('name' => 'master'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/repository/branches/master/protect', array('developers_can_push' => true, 'developers_can_merge' => true)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->protectBranch(1, 'master', true, true)); + } + + /** + * @test + */ + public function shouldUnprotectBranch() + { + $expectedArray = array('name' => 'master'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/repository/branches/master/unprotect') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->unprotectBranch(1, 'master')); + } + + /** + * @test + */ + public function shouldGetTags() + { + $expectedArray = array( + array('name' => '1.0'), + array('name' => '1.1') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/tags') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->tags(1)); + } + + /** + * @test + */ + public function shouldCreateTag() + { + $expectedArray = array('name' => '1.0'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/repository/tags', array( + 'tag_name' => '1.0', + 'ref' => 'abcd1234', + 'message' => '1.0 release' + )) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->createTag(1, '1.0', 'abcd1234', '1.0 release')); + } + + /** + * @test + */ + public function shouldCreateRelease() { + $project_id = 1; + $tagName = 'sometag'; + $description = '1.0 release'; + + $expectedArray = array( 'name' => $tagName ); + + $api = $this->getApiMock(); + $api->expects( $this->once()) + ->method('post') + ->with( 'projects/' . $project_id . '/repository/tags/' . $tagName . '/release', array( + 'id' => $project_id, + 'tag_name' => $tagName, + 'description' => $description + )) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals( $expectedArray, $api->createRelease( $project_id, $tagName, $description ) ); + } + + /** + * @test + */ + public function shouldUpdateRelease() { + $project_id = 1; + $tagName = 'sometag'; + $description = '1.0 release'; + + $expectedArray = array( 'description' => $tagName ); + + $api = $this->getApiMock(); + $api->expects( $this->once()) + ->method('put') + ->with( 'projects/' . $project_id . '/repository/tags/' . $tagName . '/release', array( + 'id' => $project_id, + 'tag_name' => $tagName, + 'description' => $description + )) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals( $expectedArray, $api->updateRelease( $project_id, $tagName, $description ) ); + } + + /** + * @test + */ + public function shouldGetCommits() + { + $expectedArray = array( + array('id' => 'abcd1234', 'title' => 'A commit'), + array('id' => 'efgh5678', 'title' => 'Another commit') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/commits', array('page' => 0, 'per_page' => AbstractApi::PER_PAGE, 'ref_name' => null)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->commits(1)); + } + + /** + * @test + */ + public function shouldGetCommitBuilds() + { + $expectedArray = array( + array('id' => 'abcd1234', 'status' => 'failed'), + array('id' => 'efgh5678', 'status' => 'success') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/commits/abcd12345/builds', array('page' => 0, 'per_page' => AbstractApi::PER_PAGE, 'scope' => null)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->commitBuilds(1, 'abcd12345')); + } + + /** + * @test + */ + public function shouldGetCommitBuildsWithScope() + { + $expectedArray = array( + array('id' => 'abcd1234', 'status' => 'success'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/commits/abcd12345/builds', array('page' => 0, 'per_page' => AbstractApi::PER_PAGE, 'scope' => 'success')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->commitBuilds(1, 'abcd12345', 'success')); + } + + + /** + * @test + */ + public function shouldGetCommitsWithParams() + { + $expectedArray = array( + array('id' => 'abcd1234', 'title' => 'A commit'), + array('id' => 'efgh5678', 'title' => 'Another commit') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/commits', array('page' => 2, 'per_page' => 25, 'ref_name' => 'master')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->commits(1, 2, 25, 'master')); + } + + /** + * @test + */ + public function shouldGetCommit() + { + $expectedArray = array('id' => 'abcd1234', 'title' => 'A commit'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/commits/abcd1234') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->commit(1, 'abcd1234')); + } + + /** + * @test + */ + public function shouldGetCommitComments() + { + $expectedArray = array( + array('note' => 'A commit message'), + array('note' => 'Another commit message') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/commits/abcd1234/comments') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->commitComments(1, 'abcd1234')); + } + + /** + * @test + */ + public function shouldCreateCommitComment() + { + $expectedArray = array('id' => 2, 'title' => 'A new comment'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/repository/commits/abcd1234/comments', array('note' => 'A new comment')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->createCommitComment(1, 'abcd1234', 'A new comment')); + } + + /** + * @test + */ + public function shouldCreateCommitCommentWithParams() + { + $expectedArray = array('id' => 2, 'title' => 'A new comment'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/repository/commits/abcd1234/comments', array( + 'note' => 'A new comment', + 'path' => '/some/file.txt', + 'line' => 123, 'line_type' => 'old' + )) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->createCommitComment(1, 'abcd1234', 'A new comment', array( + 'path' => '/some/file.txt', + 'line' => 123, + 'line_type' => 'old' + ))); + } + + /** + * @test + */ + public function shouldCompare() + { + $expectedArray = array('commit' => 'object'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/compare?from=master&to=feature') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->compare(1, 'master', 'feature')); + } + + /** + * @test + */ + public function shouldGetDiff() + { + $expectedArray = array( + array('diff' => '--- ...'), + array('diff' => '+++ ...') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/commits/abcd1234/diff') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->diff(1, 'abcd1234')); + } + + /** + * @test + */ + public function shouldGetTree() + { + $expectedArray = array( + array('name' => 'file1.txt'), + array('name' => 'file2.csv') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/tree') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->tree(1)); + } + + /** + * @test + */ + public function shouldGetTreeWithParams() + { + $expectedArray = array( + array('name' => 'dir/file1.txt'), + array('name' => 'dir/file2.csv') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/tree', array('path' => 'dir/', 'ref_name' => 'master')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->tree(1, array('path' => 'dir/', 'ref_name' => 'master'))); + } + + /** + * @test + */ + public function shouldGetBlob() + { + $expectedString = 'something in a file'; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/commits/abcd1234/blob', array('filepath' => 'dir/file1.txt')) + ->will($this->returnValue($expectedString)) + ; + + $this->assertEquals($expectedString, $api->blob(1, 'abcd1234', 'dir/file1.txt')); + } + + /** + * @test + */ + public function shouldGetFile() + { + $expectedArray = array('file_name' => 'file1.txt', 'file_path' => 'dir/file1.txt'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/files', array('file_path' => 'dir/file1.txt', 'ref' => 'abcd1234')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->getFile(1, 'dir/file1.txt', 'abcd1234')); + } + + /** + * @test + */ + public function shouldCreateFile() + { + $expectedArray = array('file_name' => 'file1.txt', 'file_path' => 'dir/file1.txt'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/repository/files', array( + 'file_path' => 'dir/file1.txt', + 'branch_name' => 'master', + 'encoding' => null, + 'content' => 'some contents', + 'commit_message' => 'Added new file', + 'author_email' => null, + 'author_name' => null, + )) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->createFile(1, 'dir/file1.txt', 'some contents', 'master', 'Added new file')); + } + + /** + * @test + */ + public function shouldCreateFileWithEncoding() + { + $expectedArray = array('file_name' => 'file1.txt', 'file_path' => 'dir/file1.txt'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/repository/files', array( + 'file_path' => 'dir/file1.txt', + 'branch_name' => 'master', + 'encoding' => 'text', + 'content' => 'some contents', + 'commit_message' => 'Added new file', + 'author_email' => null, + 'author_name' => null, + )) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->createFile(1, 'dir/file1.txt', 'some contents', 'master', 'Added new file', 'text')); + } + + /** + * @test + */ + public function shouldCreateFileWithAuthor() + { + $expectedArray = array('file_name' => 'file1.txt', 'file_path' => 'dir/file1.txt'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/repository/files', array( + 'file_path' => 'dir/file1.txt', + 'branch_name' => 'master', + 'encoding' => null, + 'content' => 'some contents', + 'commit_message' => 'Added new file', + 'author_email' => 'gitlab@example.com', + 'author_name' => 'GitLab User', + )) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->createFile(1, 'dir/file1.txt', 'some contents', 'master', 'Added new file', null, 'gitlab@example.com', 'GitLab User')); + } + + /** + * @test + */ + public function shouldUpdateFile() + { + $expectedArray = array('file_name' => 'file1.txt', 'file_path' => 'dir/file1.txt'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/repository/files', array( + 'file_path' => 'dir/file1.txt', + 'branch_name' => 'master', + 'encoding' => null, + 'content' => 'some new contents', + 'commit_message' => 'Updated new file', + 'author_email' => null, + 'author_name' => null, + )) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->updateFile(1, 'dir/file1.txt', 'some new contents', 'master', 'Updated new file')); + } + + /** + * @test + */ + public function shouldUpdateFileWithEncoding() + { + $expectedArray = array('file_name' => 'file1.txt', 'file_path' => 'dir/file1.txt'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/repository/files', array( + 'file_path' => 'dir/file1.txt', + 'branch_name' => 'master', + 'encoding' => 'base64', + 'content' => 'some new contents', + 'commit_message' => 'Updated file', + 'author_email' => null, + 'author_name' => null, + )) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->updateFile(1, 'dir/file1.txt', 'some new contents', 'master', 'Updated file', 'base64')); + } + + /** + * @test + */ + public function shouldUpdateFileWithAuthor() + { + $expectedArray = array('file_name' => 'file1.txt', 'file_path' => 'dir/file1.txt'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/repository/files', array( + 'file_path' => 'dir/file1.txt', + 'branch_name' => 'master', + 'encoding' => null, + 'content' => 'some new contents', + 'commit_message' => 'Updated file', + 'author_email' => 'gitlab@example.com', + 'author_name' => 'GitLab User', + )) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->updateFile(1, 'dir/file1.txt', 'some new contents', 'master', 'Updated file', null, 'gitlab@example.com', 'GitLab User')); + } + + /** + * @test + */ + public function shouldDeleteFile() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/repository/files', array( + 'file_path' => 'dir/file1.txt', + 'branch_name' => 'master', + 'commit_message' => 'Deleted file', + 'author_email' => null, + 'author_name' => null, + )) + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->deleteFile(1, 'dir/file1.txt', 'master', 'Deleted file')); + } + + /** + * @test + */ + public function shouldDeleteFileWithAuthor() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/repository/files', array( + 'file_path' => 'dir/file1.txt', + 'branch_name' => 'master', + 'commit_message' => 'Deleted file', + 'author_email' => 'gitlab@example.com', + 'author_name' => 'GitLab User', + )) + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->deleteFile(1, 'dir/file1.txt', 'master', 'Deleted file', 'gitlab@example.com', 'GitLab User')); + } + + /** + * @test + */ + public function shouldGetContributors() + { + $expectedArray = array( + array('name' => 'Matt'), + array('name' => 'Bob') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/contributors') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->contributors(1)); + } + + protected function getApiClass() + { + return 'Gitlab\Api\Repositories'; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/SnippetsTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/SnippetsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..694aac5959ddecfade4f6b1bedf6d32580003517 --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/SnippetsTest.php @@ -0,0 +1,114 @@ +<?php namespace Gitlab\Tests\Api; + +class SnippetsTest extends ApiTestCase +{ + /** + * @test + */ + public function shouldGetAllSnippets() + { + $expectedArray = array( + array('id' => 1, 'title' => 'A snippet'), + array('id' => 2, 'title' => 'Another snippet'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/snippets') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->all(1)); + } + + /** + * @test + */ + public function shouldShowSnippet() + { + $expectedArray = array('id' => 2, 'title' => 'Another snippet'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/snippets/2') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->show(1, 2)); + } + + /** + * @test + */ + public function shouldCreateSnippet() + { + $expectedArray = array('id' => 3, 'title' => 'A new snippet'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/snippets', array('title' => 'A new snippet', 'code' => 'A file', 'file_name' => 'file.txt')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->create(1, 'A new snippet', 'file.txt', 'A file')); + } + + /** + * @test + */ + public function shouldUpdateSnippet() + { + $expectedArray = array('id' => 3, 'title' => 'Updated snippet'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('projects/1/snippets/3', array('title' => 'Updated snippet', 'code' => 'New content', 'file_name' => 'new_file.txt')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->update(1, 3, array('file_name' => 'new_file.txt', 'code' => 'New content', 'title' => 'Updated snippet'))); + } + + /** + * @test + */ + public function shouldShowContent() + { + $expectedString = 'New content'; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/snippets/3/raw') + ->will($this->returnValue($expectedString)) + ; + + $this->assertEquals($expectedString, $api->content(1, 3)); + } + + /** + * @test + */ + public function shouldRemoveSnippet() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/snippets/3') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->remove(1, 3)); + } + + protected function getApiClass() + { + return 'Gitlab\Api\Snippets'; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/SystemHooksTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/SystemHooksTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3bf16bce6bcd948fad1f0d3c280fc4a4a478e7cb --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/SystemHooksTest.php @@ -0,0 +1,80 @@ +<?php namespace Gitlab\Tests\Api; + +class SystemHooksTest extends ApiTestCase +{ + /** + * @test + */ + public function shouldGetAllHooks() + { + $expectedArray = array( + array('id' => 1, 'url' => 'http://www.example.com'), + array('id' => 2, 'url' => 'http://www.example.org'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('hooks') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->all()); + } + + /** + * @test + */ + public function shouldCreateHook() + { + $expectedArray = array('id' => 3, 'url' => 'http://www.example.net'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('hooks', array('url' => 'http://www.example.net')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->create('http://www.example.net')); + } + + /** + * @test + */ + public function shouldTestHook() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('hooks/3') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->test(3)); + } + + /** + * @test + */ + public function shouldRemoveHook() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('hooks/3') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->remove(3)); + } + + protected function getApiClass() + { + return 'Gitlab\Api\SystemHooks'; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/TagsTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/TagsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b6aaafa6fcaef360599d0818b6455275ebe2383b --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/TagsTest.php @@ -0,0 +1,87 @@ +<?php namespace Gitlab\Tests\Api; + +use Gitlab\Api\AbstractApi; + +class TagsTest extends ApiTestCase +{ + /** + * @test + */ + public function shouldGetAllTags() + { + $expectedArray = array( + array('name' => 'v1.0.0'), + array('name' => 'v1.1.0'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/tags') + ->will($this->returnValue($expectedArray)); + $this->assertEquals($expectedArray, $api->all(1)); + } + + /** + * @test + */ + public function shouldShowTag() + { + $expectedArray = array( + array('name' => 'v1.0.0'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('projects/1/repository/tags/v1.0.0') + ->will($this->returnValue($expectedArray)); + $this->assertEquals($expectedArray, $api->show(1, 'v1.0.0')); + } + + /** + * @test + */ + public function shouldCreateTag() + { + $expectedArray = array( + array('name' => 'v1.1.0'), + ); + + $params = array( + 'id' => 1, + 'tag_name' => 'v1.1.0', + 'ref' => 'ref/heads/master' + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/repository/tags', $params) + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->create(1, $params)); + } + + /** + * @test + */ + public function shouldRemoveTag() + { + $expectedArray = array( + array('name' => 'v1.1.0'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1/repository/tags/v1.1.0') + ->will($this->returnValue($expectedArray)); + $this->assertEquals($expectedArray, $api->remove(1, 'v1.1.0')); + } + + protected function getApiClass() + { + return 'Gitlab\Api\Tags'; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/TestCase.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/TestCase.php new file mode 100644 index 0000000000000000000000000000000000000000..cba51e5e26a9bf8cdc1554ae094450706f3eef9b --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/TestCase.php @@ -0,0 +1,38 @@ +<?php namespace Gitlab\Tests\Api; + +use Buzz\Client\Curl; + +use Gitlab\Client; +use Gitlab\HttpClient\HttpClientInterface; + +abstract class TestCase extends \PHPUnit_Framework_TestCase +{ + /** + * @return Client + */ + protected function getClientMock() + { + return new Client($this->getHttpMock()); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|HttpClientInterface + */ + protected function getHttpMock() + { + return $this->getMock('Gitlab\HttpClient\HttpClient', array(), array(null, array(), $this->getHttpClientMock())); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|Curl + */ + protected function getHttpClientMock() + { + $httpClient = $this->getMock('Buzz\Client\Curl', array('send')); + $httpClient + ->expects($this->any()) + ->method('send'); + + return $httpClient; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/UsersTest.php b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/UsersTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a1441da0089ff4af29ffcfcb2bb3e2943bbde6c5 --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/Gitlab/Tests/Api/UsersTest.php @@ -0,0 +1,459 @@ +<?php namespace Gitlab\Tests\Api; + +use Gitlab\Api\AbstractApi; + +class UsersTest extends ApiTestCase +{ + /** + * @test + */ + public function shouldGetAllUsers() + { + $expectedArray = array( + array('id' => 1, 'name' => 'Matt'), + array('id' => 2, 'name' => 'John'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('users', array('active' => null, 'page' => 1, 'per_page' => 10)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->all(null, 1, 10)); + } + + /** + * @test + */ + public function shouldGetActiveUsers() + { + $expectedArray = array( + array('id' => 1, 'name' => 'Matt'), + array('id' => 2, 'name' => 'John'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('users', array('active' => true, 'page' => 1, 'per_page' => AbstractApi::PER_PAGE)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->all(true)); + } + + /** + * @test + */ + public function shouldNotNeedPaginationWhenGettingUsers() + { + $expectedArray = array( + array('id' => 1, 'name' => 'Matt'), + array('id' => 2, 'name' => 'John'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('users', array('active' => null, 'page' => 1, 'per_page' => AbstractApi::PER_PAGE)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->all()); + } + + /** + * @test + */ + public function shouldSearchUsers() + { + $expectedArray = array( + array('id' => 1, 'name' => 'Matt') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('users', array('search' => 'ma', 'active' => null, 'page' => 1, 'per_page' => AbstractApi::PER_PAGE)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->search('ma')); + } + + /** + * @test + */ + public function shouldSearchActiveUsers() + { + $expectedArray = array( + array('id' => 1, 'name' => 'Matt') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('users', array('search' => 'ma', 'active' => true, 'page' => 1, 'per_page' => AbstractApi::PER_PAGE)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->search('ma', true)); + } + + /** + * @test + */ + public function shouldSearchActiveUsersWithPagination() + { + $expectedArray = array( + array('id' => 1, 'name' => 'Matt') + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('users', array('search' => 'ma', 'active' => true, 'page' => 2, 'per_page' => 5)) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->search('ma', true, 2, 5)); + } + + /** + * @test + */ + public function shouldShowUser() + { + $expectedArray = array('id' => 1, 'name' => 'Matt'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('users/1') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->show(1)); + } + + /** + * @test + */ + public function shouldCreateUser() + { + $expectedArray = array('id' => 3, 'name' => 'Billy'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('users', array('email' => 'billy@example.com', 'password' => 'password')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->create('billy@example.com', 'password')); + } + + /** + * @test + */ + public function shouldCreateUserWithAdditionalInfo() + { + $expectedArray = array('id' => 3, 'name' => 'Billy'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('users', array('email' => 'billy@example.com', 'password' => 'password', 'name' => 'Billy', 'bio' => 'A person')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->create('billy@example.com', 'password', array('name' => 'Billy', 'bio' => 'A person'))); + } + + /** + * @test + */ + public function shouldUpdateUser() + { + $expectedArray = array('id' => 3, 'name' => 'Billy Bob'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('users/3', array('name' => 'Billy Bob')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->update(3, array('name' => 'Billy Bob'))); + } + + /** + * @test + */ + public function shouldRemoveUser() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('users/1') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->remove(1)); + } + + /** + * @test + */ + public function shouldBlockUser() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('users/1/block') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->block(1)); + } + + /** + * @test + */ + public function shouldUnblockUser() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('users/1/unblock') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->unblock(1)); + } + + /** + * @test + */ + public function shouldShowCurrentUser() + { + $expectedArray = array('id' => 1, 'name' => 'Matt'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('user') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->me()); + } + + /** + * @test + */ + public function shouldGetCurrentUserKeys() + { + $expectedArray = array( + array('id' => 1, 'title' => 'A key'), + array('id' => 2, 'name' => 'Another key'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('user/keys') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->keys(1)); + } + + /** + * @test + */ + public function shouldGetCurrentUserKey() + { + $expectedArray = array('id' => 1, 'title' => 'A key'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('user/keys/1') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->key(1)); + } + + /** + * @test + */ + public function shouldCreateKeyForCurrentUser() + { + $expectedArray = array('id' => 3, 'title' => 'A new key'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('user/keys', array('title' => 'A new key', 'key' => '...')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->createKey('A new key', '...')); + } + + /** + * @test + */ + public function shouldDeleteKeyForCurrentUser() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('user/keys/3') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->removeKey(3)); + } + + /** + * @test + */ + public function shouldGetUserKeys() + { + $expectedArray = array( + array('id' => 1, 'title' => 'A key'), + array('id' => 2, 'name' => 'Another key'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('users/1/keys') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->userKeys(1)); + } + + /** + * @test + */ + public function shouldGetUserKey() + { + $expectedArray = array('id' => 2, 'title' => 'Another key'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('users/1/keys/2') + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->userKey(1, 2)); + } + + /** + * @test + */ + public function shouldCreateKeyForUser() + { + $expectedArray = array('id' => 3, 'title' => 'A new key'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('users/1/keys', array('title' => 'A new key', 'key' => '...')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->createKeyForUser(1, 'A new key', '...')); + } + + /** + * @test + */ + public function shouldDeleteKeyForUser() + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('users/1/keys/3') + ->will($this->returnValue($expectedBool)) + ; + + $this->assertEquals($expectedBool, $api->removeUserKey(1, 3)); + } + + /** + * @test + */ + public function shouldAttemptLogin() + { + $expectedArray = array('id' => 1, 'name' => 'Matt'); + + $api = $this->getApiMock(); + $api->expects($this->exactly(2)) + ->method('post') + ->with('session', array('login' => 'matt', 'password' => 'password', 'email' => 'matt')) + ->will($this->returnValue($expectedArray)) + ; + + $this->assertEquals($expectedArray, $api->session('matt', 'password')); + $this->assertEquals($expectedArray, $api->login('matt', 'password')); + } + + /** + * @test + */ + public function shouldGetUserEmails() + { + $expectedArray = array( + array('id' => 1, 'email' => 'foo@bar.baz'), + array('id' => 2, 'email' => 'foo@bar.qux'), + ); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('user/emails') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->emails()); + } + + /** + * @test + */ + public function shouldGetSpecificUserEmail() + { + $expectedArray = array('id' => 1, 'email' => 'foo@bar.baz'); + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('user/emails/1') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->email(1)); + } + + protected function getApiClass() + { + return 'Gitlab\Api\Users'; + } +} diff --git a/vendor/m4tthumphrey/php-gitlab-api/test/bootstrap.php b/vendor/m4tthumphrey/php-gitlab-api/test/bootstrap.php new file mode 100644 index 0000000000000000000000000000000000000000..83bc8b088a4fee7016d39ea78c45258cde578119 --- /dev/null +++ b/vendor/m4tthumphrey/php-gitlab-api/test/bootstrap.php @@ -0,0 +1,18 @@ +<?php + +function includeIfExists($file) +{ + if (file_exists($file)) { + return include $file; + } +} + +if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../.composer/autoload.php'))) { + die('You must set up the project dependencies, run the following commands:'.PHP_EOL. + 'curl -s http://getcomposer.org/installer | php'.PHP_EOL. + 'php composer.phar install'.PHP_EOL); +} + +$loader->add('Gitlab\Tests', __DIR__); + +return $loader; \ No newline at end of file diff --git a/vendor/nyholm/psr7/CHANGELOG.md b/vendor/nyholm/psr7/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..dc4c5134131112d4a65e2de08a951a099cec73f8 --- /dev/null +++ b/vendor/nyholm/psr7/CHANGELOG.md @@ -0,0 +1,54 @@ +# Changelog + +All notable changes to this project will be documented in this file, in reverse chronological order by release. + +## 1.0.1 + +### Fixed + +- Handle `fopen` failing in createStreamFromFile according to PSR-7. +- Reduce execution path to speed up performance. +- Fixed typos. +- Code style. + +## 1.0.0 + +### Added + +- Support for final PSR-17 (HTTP factories). (`Psr17Factory`) +- Support for numeric header values. +- Support for empty header values. +- All classes are final +- `HttplugFactory` that implements factory interfaces from HTTPlug. + +### Changed + +- `ServerRequest` does not extend `Request`. + +### Removed + +- The HTTPlug discovery strategy was removed since it is included in php-http/discovery 1.4. +- `UploadedFileFactory()` was removed in favor for `Psr17Factory`. +- `ServerRequestFactory()` was removed in favor for `Psr17Factory`. +- `StreamFactory`, `UriFactory`, abd `MessageFactory`. Use `HttplugFactory` instead. +- `ServerRequestFactory::createServerRequestFromArray`, `ServerRequestFactory::createServerRequestFromArrays` and + `ServerRequestFactory::createServerRequestFromGlobals`. Please use the new `nyholm/psr7-server` instead. + +## 0.3.0 + +### Added + +- Return types. +- Many `InvalidArgumentException`s are thrown when you use invalid arguments. +- Integration tests for `UploadedFile` and `ServerRequest`. + +### Changed + +- We dropped PHP7.0 support. +- PSR-17 factories have been marked as internal. They do not fall under our BC promise until PSR-17 is accepted. +- `UploadedFileFactory::createUploadedFile` does not accept a string file path. + +## 0.2.3 + +No changelog before this release + diff --git a/vendor/nyholm/psr7/LICENSE b/vendor/nyholm/psr7/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..d6c52312c64110d4bf27b8f2e7add50cb3de5e02 --- /dev/null +++ b/vendor/nyholm/psr7/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Tobias Nyholm + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/nyholm/psr7/README.md b/vendor/nyholm/psr7/README.md new file mode 100644 index 0000000000000000000000000000000000000000..221d3ef2a1f5449845f972dd3ca351e7de775aa8 --- /dev/null +++ b/vendor/nyholm/psr7/README.md @@ -0,0 +1,94 @@ +# PSR-7 implementation + +[](https://github.com/Nyholm/psr7/releases) +[](https://travis-ci.org/Nyholm/psr7) +[](https://scrutinizer-ci.com/g/Nyholm/psr7) +[](https://scrutinizer-ci.com/g/Nyholm/psr7) +[](https://packagist.org/packages/nyholm/psr7) +[](https://packagist.org/packages/nyholm/psr7) +[](LICENSE) + + +A super lightweight PSR-7 implementation. Very strict and very fast. + +| Description | Guzzle | Zend | Slim | Nyholm | +| ---- | ------ | ---- | ---- | ------ | +| Lines of code | 3 000 | 3 000 | 1 700 | 1 100 | +| PHP7 | No | No | No | Yes | +| PSR-7* | 66% | 92% | 75% | 100% | +| PSR-17 | No | No | No | Yes | +| HTTPlug | No | No | No | Yes | +| Performance** | 1.49x | 1x | 1.17x | 1.69x | + +\* Percent of completed tests in https://github.com/php-http/psr7-integration-tests + +\** See benchmark at https://github.com/Nyholm/http-client-benchmark (higher is better) + +## Installation + +```bash +composer require nyholm/psr7 +``` + +If you are using Symfony Flex then you get all message factories registered as services. + +## Usage + +The PSR-7 objects do not contain any other public methods then those defined in +the [PSR-7 specification](https://www.php-fig.org/psr/psr-7/). + +### Create objects + +Use the PSR-17 factory to create requests, streams, URIs etc. + +```php +$factory = new \Nyholm\Psr7\Factory\Psr17Factory(); +$request = $factory->createRequest('GET', 'http://tnyholm.se'); +$stream = $factory->createStream('foobar'); +``` + +### Sending a request + +With [HTTPlug](http://httplug.io/) or any other PSR-18 (HTTP client) you may send requests like: + +```bash +composer require kriswallsmith/buzz +``` + +```php +$psr17Factory = new \Nyholm\Psr7\Factory\Psr17Factory(); +$psr18Client = new Buzz\Client\Curl([], $psr17Factory); + +$request = (new Psr17Factory())->createRequest('GET', 'http://tnyholm.se'); +$response = $psr18Client->sendRequest($request); +``` + +### Create server requests + +```bash +composer require nyholm/psr7-server +``` + +```php +$psr17Factory = new \Nyholm\Psr7\Factory\Psr17Factory(); + +$creator = new ServerRequestCreator( + $psr17Factory, + $psr17Factory, + $psr17Factory, + $psr17Factory +); + +$serverRequest = $creator->fromGlobals(); +``` + +### Emitting a response + +```bash +composer require zendframework/zend-httphandlerrunner +``` + +```php +$response = (new Psr17Factory())->createReponse('200', 'Hello world'); +(new \Zend\HttpHandlerRunner\Emitter\SapiEmitter())->emit($response); +``` diff --git a/vendor/nyholm/psr7/composer.json b/vendor/nyholm/psr7/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..397f38eb357372a660d820270b9e7fd0f49fcfcb --- /dev/null +++ b/vendor/nyholm/psr7/composer.json @@ -0,0 +1,51 @@ +{ + "name": "nyholm/psr7", + "description": "A fast PHP7 implementation of PSR-7", + "license": "MIT", + "keywords": ["psr-7", "psr-17"], + "homepage": "http://tnyholm.se", + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" + } + ], + "require": { + "php": "^7.1", + "psr/http-message": "^1.0", + "php-http/message-factory": "^1.0", + "psr/http-factory": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.0", + "php-http/psr7-integration-tests": "dev-master", + "http-interop/http-factory-tests": "dev-master" + }, + "provide": { + "psr/http-message-implementation": "1.0", + "psr/http-factory-implementation": "1.0" + }, + "autoload": { + "psr-4": { + "Nyholm\\Psr7\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\Nyholm\\Psr7\\": "tests/" + } + }, + "scripts": { + "test": "vendor/bin/phpunit", + "test-ci": "vendor/bin/phpunit --coverage-text --coverage-clover=build/coverage.xml" + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + } +} diff --git a/vendor/nyholm/psr7/src/Factory/HttplugFactory.php b/vendor/nyholm/psr7/src/Factory/HttplugFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..c17878ac39b56d2fd3f771cabf9b2e7914322e54 --- /dev/null +++ b/vendor/nyholm/psr7/src/Factory/HttplugFactory.php @@ -0,0 +1,40 @@ +<?php + +declare(strict_types=1); + +namespace Nyholm\Psr7\Factory; + +use Http\Message\{MessageFactory, StreamFactory, UriFactory}; +use Nyholm\Psr7\{Request, Response, Stream, Uri}; +use Psr\Http\Message\UriInterface; + +/** + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + * @author Martijn van der Ven <martijn@vanderven.se> + */ +final class HttplugFactory implements MessageFactory, StreamFactory, UriFactory +{ + public function createRequest($method, $uri, array $headers = [], $body = null, $protocolVersion = '1.1') + { + return new Request($method, $uri, $headers, $body, $protocolVersion); + } + + public function createResponse($statusCode = 200, $reasonPhrase = null, array $headers = [], $body = null, $version = '1.1') + { + return new Response((int) $statusCode, $headers, $body, $version, $reasonPhrase); + } + + public function createStream($body = null) + { + return Stream::create(null === $body ? '' : $body); + } + + public function createUri($uri = ''): UriInterface + { + if ($uri instanceof UriInterface) { + return $uri; + } + + return new Uri($uri); + } +} diff --git a/vendor/nyholm/psr7/src/Factory/Psr17Factory.php b/vendor/nyholm/psr7/src/Factory/Psr17Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..218122c692f72c9f96da88b251da08600182d668 --- /dev/null +++ b/vendor/nyholm/psr7/src/Factory/Psr17Factory.php @@ -0,0 +1,68 @@ +<?php + +declare(strict_types=1); + +namespace Nyholm\Psr7\Factory; + +use Nyholm\Psr7\{Request, Response, ServerRequest, Stream, UploadedFile, Uri}; +use Psr\Http\Message\{RequestFactoryInterface, RequestInterface, ResponseFactoryInterface, ResponseInterface, ServerRequestFactoryInterface, ServerRequestInterface, StreamFactoryInterface, StreamInterface, UploadedFileFactoryInterface, UploadedFileInterface, UriFactoryInterface, UriInterface}; + +/** + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + * @author Martijn van der Ven <martijn@vanderven.se> + */ +final class Psr17Factory implements RequestFactoryInterface, ResponseFactoryInterface, ServerRequestFactoryInterface, StreamFactoryInterface, UploadedFileFactoryInterface, UriFactoryInterface +{ + public function createRequest(string $method, $uri): RequestInterface + { + return new Request($method, $uri); + } + + public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface + { + return new Response($code, [], null, '1.1', $reasonPhrase); + } + + public function createStream(string $content = ''): StreamInterface + { + return Stream::create($content); + } + + public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface + { + $resource = @\fopen($filename, $mode); + if (false === $resource) { + if (0 === \strlen($mode) || false === \in_array($mode[0], ['r', 'w', 'a', 'x', 'c'])) { + throw new \InvalidArgumentException('The mode '.$mode.' is invalid.'); + } + + throw new \RuntimeException('The file '.$filename.' cannot be opened.'); + } + + return Stream::create($resource); + } + + public function createStreamFromResource($resource): StreamInterface + { + return Stream::create($resource); + } + + public function createUploadedFile(StreamInterface $stream, int $size = null, int $error = \UPLOAD_ERR_OK, string $clientFilename = null, string $clientMediaType = null): UploadedFileInterface + { + if (null === $size) { + $size = $stream->getSize(); + } + + return new UploadedFile($stream, $size, $error, $clientFilename, $clientMediaType); + } + + public function createUri(string $uri = ''): UriInterface + { + return new Uri($uri); + } + + public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface + { + return new ServerRequest($method, $uri, [], null, '1.1', $serverParams); + } +} diff --git a/vendor/nyholm/psr7/src/MessageTrait.php b/vendor/nyholm/psr7/src/MessageTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..1e811741dfe619ea2d02abedbd584ee44a94d71b --- /dev/null +++ b/vendor/nyholm/psr7/src/MessageTrait.php @@ -0,0 +1,202 @@ +<?php + +declare(strict_types=1); + +namespace Nyholm\Psr7; + +use Psr\Http\Message\StreamInterface; + +/** + * Trait implementing functionality common to requests and responses. + * + * @author Michael Dowling and contributors to guzzlehttp/psr7 + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + * @author Martijn van der Ven <martijn@vanderven.se> + * + * @internal should not be used outside of Nyholm/Psr7 as it does not fall under our BC promise + */ +trait MessageTrait +{ + /** @var array Map of all registered headers, as original name => array of values */ + private $headers = []; + + /** @var array Map of lowercase header name => original name at registration */ + private $headerNames = []; + + /** @var string */ + private $protocol = '1.1'; + + /** @var StreamInterface */ + private $stream; + + public function getProtocolVersion(): string + { + return $this->protocol; + } + + public function withProtocolVersion($version): self + { + if ($this->protocol === $version) { + return $this; + } + + $new = clone $this; + $new->protocol = $version; + + return $new; + } + + public function getHeaders(): array + { + return $this->headers; + } + + public function hasHeader($header): bool + { + return isset($this->headerNames[\strtolower($header)]); + } + + public function getHeader($header): array + { + $header = \strtolower($header); + if (!isset($this->headerNames[$header])) { + return []; + } + + $header = $this->headerNames[$header]; + + return $this->headers[$header]; + } + + public function getHeaderLine($header): string + { + return \implode(', ', $this->getHeader($header)); + } + + public function withHeader($header, $value): self + { + $value = $this->validateAndTrimHeader($header, $value); + $normalized = \strtolower($header); + + $new = clone $this; + if (isset($new->headerNames[$normalized])) { + unset($new->headers[$new->headerNames[$normalized]]); + } + $new->headerNames[$normalized] = $header; + $new->headers[$header] = $value; + + return $new; + } + + public function withAddedHeader($header, $value): self + { + if (!\is_string($header) || '' === $header) { + throw new \InvalidArgumentException('Header name must be an RFC 7230 compatible string.'); + } + + $new = clone $this; + $new->setHeaders([$header => $value]); + + return $new; + } + + public function withoutHeader($header): self + { + $normalized = \strtolower($header); + if (!isset($this->headerNames[$normalized])) { + return $this; + } + + $header = $this->headerNames[$normalized]; + $new = clone $this; + unset($new->headers[$header], $new->headerNames[$normalized]); + + return $new; + } + + public function getBody(): StreamInterface + { + if (!$this->stream) { + $this->stream = Stream::create(''); + } + + return $this->stream; + } + + public function withBody(StreamInterface $body): self + { + if ($body === $this->stream) { + return $this; + } + + $new = clone $this; + $new->stream = $body; + + return $new; + } + + private function setHeaders(array $headers): void + { + foreach ($headers as $header => $value) { + $value = $this->validateAndTrimHeader($header, $value); + $normalized = \strtolower($header); + if (isset($this->headerNames[$normalized])) { + $header = $this->headerNames[$normalized]; + $this->headers[$header] = \array_merge($this->headers[$header], $value); + } else { + $this->headerNames[$normalized] = $header; + $this->headers[$header] = $value; + } + } + } + + /** + * Make sure the header complies with RFC 7230. + * + * Header names must be a non-empty string consisting of token characters. + * + * Header values must be strings consisting of visible characters with all optional + * leading and trailing whitespace stripped. This method will always strip such + * optional whitespace. Note that the method does not allow folding whitespace within + * the values as this was deprecated for almost all instances by the RFC. + * + * header-field = field-name ":" OWS field-value OWS + * field-name = 1*( "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / "^" + * / "_" / "`" / "|" / "~" / %x30-39 / ( %x41-5A / %x61-7A ) ) + * OWS = *( SP / HTAB ) + * field-value = *( ( %x21-7E / %x80-FF ) [ 1*( SP / HTAB ) ( %x21-7E / %x80-FF ) ] ) + * + * @see https://tools.ietf.org/html/rfc7230#section-3.2.4 + */ + private function validateAndTrimHeader($header, $values): array + { + if (!\is_string($header) || 1 !== \preg_match("@^[!#$%&'*+.^_`|~0-9A-Za-z-]+$@", $header)) { + throw new \InvalidArgumentException('Header name must be an RFC 7230 compatible string.'); + } + + if (!\is_array($values)) { + // This is simple, just one value. + if ((!\is_numeric($values) && !\is_string($values)) || 1 !== \preg_match("@^[ \t\x21-\x7E\x80-\xFF]*$@", (string) $values)) { + throw new \InvalidArgumentException('Header values must be RFC 7230 compatible strings.'); + } + + return [\trim((string) $values, " \t")]; + } + + if (empty($values)) { + throw new \InvalidArgumentException('Header values must be a string or an array of strings, empty array given.'); + } + + // Assert Non empty array + $returnValues = []; + foreach ($values as $v) { + if ((!\is_numeric($v) && !\is_string($v)) || 1 !== \preg_match("@^[ \t\x21-\x7E\x80-\xFF]*$@", (string) $v)) { + throw new \InvalidArgumentException('Header values must be RFC 7230 compatible strings.'); + } + + $returnValues[] = \trim((string) $v, " \t"); + } + + return $returnValues; + } +} diff --git a/vendor/nyholm/psr7/src/Request.php b/vendor/nyholm/psr7/src/Request.php new file mode 100644 index 0000000000000000000000000000000000000000..5d19086487e00b3671b494116b1d7ba7d10d5f5c --- /dev/null +++ b/vendor/nyholm/psr7/src/Request.php @@ -0,0 +1,44 @@ +<?php + +declare(strict_types=1); + +namespace Nyholm\Psr7; + +use Psr\Http\Message\{RequestInterface, StreamInterface, UriInterface}; + +/** + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + * @author Martijn van der Ven <martijn@vanderven.se> + */ +final class Request implements RequestInterface +{ + use MessageTrait; + use RequestTrait; + + /** + * @param string $method HTTP method + * @param string|UriInterface $uri URI + * @param array $headers Request headers + * @param string|null|resource|StreamInterface $body Request body + * @param string $version Protocol version + */ + public function __construct(string $method, $uri, array $headers = [], $body = null, string $version = '1.1') + { + if (!($uri instanceof UriInterface)) { + $uri = new Uri($uri); + } + + $this->method = $method; + $this->uri = $uri; + $this->setHeaders($headers); + $this->protocol = $version; + + if (!$this->hasHeader('Host')) { + $this->updateHostFromUri(); + } + + if ('' !== $body && null !== $body) { + $this->stream = Stream::create($body); + } + } +} diff --git a/vendor/nyholm/psr7/src/RequestTrait.php b/vendor/nyholm/psr7/src/RequestTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..1ab6215c43ed334f3abf56c684deb0879ad6615a --- /dev/null +++ b/vendor/nyholm/psr7/src/RequestTrait.php @@ -0,0 +1,113 @@ +<?php + +declare(strict_types=1); + +namespace Nyholm\Psr7; + +use Psr\Http\Message\UriInterface; + +/** + * @author Michael Dowling and contributors to guzzlehttp/psr7 + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + * @author Martijn van der Ven <martijn@vanderven.se> + * + * @internal should not be used outside of Nyholm/Psr7 as it does not fall under our BC promise + */ +trait RequestTrait +{ + /** @var string */ + private $method; + + /** @var null|string */ + private $requestTarget; + + /** @var null|UriInterface */ + private $uri; + + public function getRequestTarget(): string + { + if (null !== $this->requestTarget) { + return $this->requestTarget; + } + + if ('' === $target = $this->uri->getPath()) { + $target = '/'; + } + if ('' !== $this->uri->getQuery()) { + $target .= '?'.$this->uri->getQuery(); + } + + return $target; + } + + public function withRequestTarget($requestTarget): self + { + if (\preg_match('#\s#', $requestTarget)) { + throw new \InvalidArgumentException('Invalid request target provided; cannot contain whitespace'); + } + + $new = clone $this; + $new->requestTarget = $requestTarget; + + return $new; + } + + public function getMethod(): string + { + return $this->method; + } + + public function withMethod($method): self + { + if (!\is_string($method)) { + throw new \InvalidArgumentException('Method must be a string'); + } + + $new = clone $this; + $new->method = $method; + + return $new; + } + + public function getUri(): UriInterface + { + return $this->uri; + } + + public function withUri(UriInterface $uri, $preserveHost = false): self + { + if ($uri === $this->uri) { + return $this; + } + + $new = clone $this; + $new->uri = $uri; + + if (!$preserveHost || !$this->hasHeader('Host')) { + $new->updateHostFromUri(); + } + + return $new; + } + + private function updateHostFromUri(): void + { + if ('' === $host = $this->uri->getHost()) { + return; + } + + if (null !== ($port = $this->uri->getPort())) { + $host .= ':'.$port; + } + + if (isset($this->headerNames['host'])) { + $header = $this->headerNames['host']; + } else { + $header = 'Host'; + $this->headerNames['host'] = 'Host'; + } + // Ensure Host is the first header. + // See: http://tools.ietf.org/html/rfc7230#section-5.4 + $this->headers = [$header => [$host]] + $this->headers; + } +} diff --git a/vendor/nyholm/psr7/src/Response.php b/vendor/nyholm/psr7/src/Response.php new file mode 100644 index 0000000000000000000000000000000000000000..c74e697271eb66d5099ceee0b4bc4a26f7d9c4fe --- /dev/null +++ b/vendor/nyholm/psr7/src/Response.php @@ -0,0 +1,87 @@ +<?php + +declare(strict_types=1); + +namespace Nyholm\Psr7; + +use Psr\Http\Message\{ResponseInterface, StreamInterface}; + +/** + * @author Michael Dowling and contributors to guzzlehttp/psr7 + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + * @author Martijn van der Ven <martijn@vanderven.se> + */ +final class Response implements ResponseInterface +{ + use MessageTrait; + + /** @var array Map of standard HTTP status code/reason phrases */ + private static $phrases = [ + 100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', + 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-status', 208 => 'Already Reported', + 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => 'Switch Proxy', 307 => 'Temporary Redirect', + 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m a teapot', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 425 => 'Unordered Collection', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 451 => 'Unavailable For Legal Reasons', + 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 511 => 'Network Authentication Required', + ]; + + /** @var string */ + private $reasonPhrase = ''; + + /** @var int */ + private $statusCode = 200; + + /** + * @param int $status Status code + * @param array $headers Response headers + * @param string|null|resource|StreamInterface $body Response body + * @param string $version Protocol version + * @param string|null $reason Reason phrase (when empty a default will be used based on the status code) + */ + public function __construct(int $status = 200, array $headers = [], $body = null, string $version = '1.1', string $reason = null) + { + $this->statusCode = (int) $status; + if ('' !== $body && null !== $body) { + $this->stream = Stream::create($body); + } + + $this->setHeaders($headers); + if (null === $reason && isset(self::$phrases[$this->statusCode])) { + $this->reasonPhrase = self::$phrases[$status]; + } else { + $this->reasonPhrase = (string) $reason; + } + + $this->protocol = $version; + } + + public function getStatusCode(): int + { + return $this->statusCode; + } + + public function getReasonPhrase(): string + { + return $this->reasonPhrase; + } + + public function withStatus($code, $reasonPhrase = ''): self + { + if (!\is_int($code) && !\is_string($code)) { + throw new \InvalidArgumentException('Status code has to be an integer'); + } + + $code = (int) $code; + if ($code < 100 || $code > 599) { + throw new \InvalidArgumentException('Status code has to be an integer between 100 and 599'); + } + + $new = clone $this; + $new->statusCode = (int) $code; + if ((null === $reasonPhrase || '' === $reasonPhrase) && isset(self::$phrases[$new->statusCode])) { + $reasonPhrase = self::$phrases[$new->statusCode]; + } + $new->reasonPhrase = $reasonPhrase; + + return $new; + } +} diff --git a/vendor/nyholm/psr7/src/ServerRequest.php b/vendor/nyholm/psr7/src/ServerRequest.php new file mode 100644 index 0000000000000000000000000000000000000000..75763f13c59ec953ef6b27bf667e3f10af65eb08 --- /dev/null +++ b/vendor/nyholm/psr7/src/ServerRequest.php @@ -0,0 +1,161 @@ +<?php + +declare(strict_types=1); + +namespace Nyholm\Psr7; + +use Psr\Http\Message\{ServerRequestInterface, StreamInterface, UploadedFileInterface, UriInterface}; + +/** + * @author Michael Dowling and contributors to guzzlehttp/psr7 + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + * @author Martijn van der Ven <martijn@vanderven.se> + */ +final class ServerRequest implements ServerRequestInterface +{ + use MessageTrait; + use RequestTrait; + + /** @var array */ + private $attributes = []; + + /** @var array */ + private $cookieParams = []; + + /** @var null|array|object */ + private $parsedBody; + + /** @var array */ + private $queryParams = []; + + /** @var array */ + private $serverParams; + + /** @var UploadedFileInterface[] */ + private $uploadedFiles = []; + + /** + * @param string $method HTTP method + * @param string|UriInterface $uri URI + * @param array $headers Request headers + * @param string|null|resource|StreamInterface $body Request body + * @param string $version Protocol version + * @param array $serverParams Typically the $_SERVER superglobal + */ + public function __construct(string $method, $uri, array $headers = [], $body = null, string $version = '1.1', array $serverParams = []) + { + $this->serverParams = $serverParams; + + if (!($uri instanceof UriInterface)) { + $uri = new Uri($uri); + } + + $this->method = $method; + $this->uri = $uri; + $this->setHeaders($headers); + $this->protocol = $version; + + if (!$this->hasHeader('Host')) { + $this->updateHostFromUri(); + } + + if ('' !== $body && null !== $body) { + $this->stream = Stream::create($body); + } + } + + public function getServerParams(): array + { + return $this->serverParams; + } + + public function getUploadedFiles(): array + { + return $this->uploadedFiles; + } + + public function withUploadedFiles(array $uploadedFiles) + { + $new = clone $this; + $new->uploadedFiles = $uploadedFiles; + + return $new; + } + + public function getCookieParams(): array + { + return $this->cookieParams; + } + + public function withCookieParams(array $cookies) + { + $new = clone $this; + $new->cookieParams = $cookies; + + return $new; + } + + public function getQueryParams(): array + { + return $this->queryParams; + } + + public function withQueryParams(array $query) + { + $new = clone $this; + $new->queryParams = $query; + + return $new; + } + + public function getParsedBody() + { + return $this->parsedBody; + } + + public function withParsedBody($data) + { + if (!\is_array($data) && !\is_object($data) && null !== $data) { + throw new \InvalidArgumentException('First parameter to withParsedBody MUST be object, array or null'); + } + + $new = clone $this; + $new->parsedBody = $data; + + return $new; + } + + public function getAttributes(): array + { + return $this->attributes; + } + + public function getAttribute($attribute, $default = null) + { + if (false === \array_key_exists($attribute, $this->attributes)) { + return $default; + } + + return $this->attributes[$attribute]; + } + + public function withAttribute($attribute, $value): self + { + $new = clone $this; + $new->attributes[$attribute] = $value; + + return $new; + } + + public function withoutAttribute($attribute): self + { + if (false === \array_key_exists($attribute, $this->attributes)) { + return $this; + } + + $new = clone $this; + unset($new->attributes[$attribute]); + + return $new; + } +} diff --git a/vendor/nyholm/psr7/src/Stream.php b/vendor/nyholm/psr7/src/Stream.php new file mode 100644 index 0000000000000000000000000000000000000000..61b7b54face32648e54c64d72e04ff32c1636b89 --- /dev/null +++ b/vendor/nyholm/psr7/src/Stream.php @@ -0,0 +1,253 @@ +<?php + +declare(strict_types=1); + +namespace Nyholm\Psr7; + +use Psr\Http\Message\StreamInterface; + +/** + * @author Michael Dowling and contributors to guzzlehttp/psr7 + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + * @author Martijn van der Ven <martijn@vanderven.se> + */ +final class Stream implements StreamInterface +{ + /** @var resource A resource reference */ + private $stream; + + /** @var bool */ + private $seekable; + + /** @var bool */ + private $readable; + + /** @var bool */ + private $writable; + + /** @var array|mixed|null|void */ + private $uri; + + /** @var int */ + private $size; + + /** @var array Hash of readable and writable stream types */ + private static $readWriteHash = [ + 'read' => [ + 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true, + 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true, + 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true, + 'x+t' => true, 'c+t' => true, 'a+' => true, + ], + 'write' => [ + 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true, + 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true, + 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true, + 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true, + ], + ]; + + private function __construct() + { + } + + /** + * Creates a new PSR-7 stream. + * + * @param string|resource|StreamInterface $body + * + * @return StreamInterface + * + * @throws \InvalidArgumentException + */ + public static function create($body = ''): StreamInterface + { + if ($body instanceof StreamInterface) { + return $body; + } + + if (\is_string($body)) { + $resource = \fopen('php://temp', 'rw+'); + \fwrite($resource, $body); + $body = $resource; + } + + if ('resource' === \gettype($body)) { + $obj = new self(); + $obj->stream = $body; + $meta = \stream_get_meta_data($obj->stream); + $obj->seekable = $meta['seekable']; + $obj->readable = isset(self::$readWriteHash['read'][$meta['mode']]); + $obj->writable = isset(self::$readWriteHash['write'][$meta['mode']]); + $obj->uri = $obj->getMetadata('uri'); + + return $obj; + } + + throw new \InvalidArgumentException('First argument to Stream::create() must be a string, resource or StreamInterface.'); + } + + /** + * Closes the stream when the destructed. + */ + public function __destruct() + { + $this->close(); + } + + public function __toString(): string + { + try { + if ($this->isSeekable()) { + $this->seek(0); + } + + return $this->getContents(); + } catch (\Exception $e) { + return ''; + } + } + + public function close(): void + { + if (isset($this->stream)) { + if (\is_resource($this->stream)) { + \fclose($this->stream); + } + $this->detach(); + } + } + + public function detach() + { + if (!isset($this->stream)) { + return null; + } + + $result = $this->stream; + unset($this->stream); + $this->size = $this->uri = null; + $this->readable = $this->writable = $this->seekable = false; + + return $result; + } + + public function getSize(): ?int + { + if (null !== $this->size) { + return $this->size; + } + + if (!isset($this->stream)) { + return null; + } + + // Clear the stat cache if the stream has a URI + if ($this->uri) { + \clearstatcache(true, $this->uri); + } + + $stats = \fstat($this->stream); + if (isset($stats['size'])) { + $this->size = $stats['size']; + + return $this->size; + } + + return null; + } + + public function tell(): int + { + if (false === $result = \ftell($this->stream)) { + throw new \RuntimeException('Unable to determine stream position'); + } + + return $result; + } + + public function eof(): bool + { + return !$this->stream || \feof($this->stream); + } + + public function isSeekable(): bool + { + return $this->seekable; + } + + public function seek($offset, $whence = \SEEK_SET): void + { + if (!$this->seekable) { + throw new \RuntimeException('Stream is not seekable'); + } elseif (\fseek($this->stream, $offset, $whence) === -1) { + throw new \RuntimeException('Unable to seek to stream position '.$offset.' with whence '.\var_export($whence, true)); + } + } + + public function rewind(): void + { + $this->seek(0); + } + + public function isWritable(): bool + { + return $this->writable; + } + + public function write($string): int + { + if (!$this->writable) { + throw new \RuntimeException('Cannot write to a non-writable stream'); + } + + // We can't know the size after writing anything + $this->size = null; + + if (false === $result = \fwrite($this->stream, $string)) { + throw new \RuntimeException('Unable to write to stream'); + } + + return $result; + } + + public function isReadable(): bool + { + return $this->readable; + } + + public function read($length): string + { + if (!$this->readable) { + throw new \RuntimeException('Cannot read from non-readable stream'); + } + + return \fread($this->stream, $length); + } + + public function getContents(): string + { + if (!isset($this->stream)) { + throw new \RuntimeException('Unable to read stream contents'); + } + + if (false === $contents = \stream_get_contents($this->stream)) { + throw new \RuntimeException('Unable to read stream contents'); + } + + return $contents; + } + + public function getMetadata($key = null) + { + if (!isset($this->stream)) { + return $key ? null : []; + } elseif (null === $key) { + return \stream_get_meta_data($this->stream); + } + + $meta = \stream_get_meta_data($this->stream); + + return isset($meta[$key]) ? $meta[$key] : null; + } +} diff --git a/vendor/nyholm/psr7/src/UploadedFile.php b/vendor/nyholm/psr7/src/UploadedFile.php new file mode 100644 index 0000000000000000000000000000000000000000..4cf18100eb5bc4407b1091bbec3c84ea4fc8a674 --- /dev/null +++ b/vendor/nyholm/psr7/src/UploadedFile.php @@ -0,0 +1,249 @@ +<?php + +declare(strict_types=1); + +namespace Nyholm\Psr7; + +use Psr\Http\Message\{StreamInterface, UploadedFileInterface}; + +/** + * @author Michael Dowling and contributors to guzzlehttp/psr7 + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + * @author Martijn van der Ven <martijn@vanderven.se> + */ +final class UploadedFile implements UploadedFileInterface +{ + /** @var int[] */ + private static $errors = [ + \UPLOAD_ERR_OK, \UPLOAD_ERR_INI_SIZE, \UPLOAD_ERR_FORM_SIZE, \UPLOAD_ERR_PARTIAL, \UPLOAD_ERR_NO_FILE, + \UPLOAD_ERR_NO_TMP_DIR, \UPLOAD_ERR_CANT_WRITE, \UPLOAD_ERR_EXTENSION, + ]; + + /** @var string */ + private $clientFilename; + + /** @var string */ + private $clientMediaType; + + /** @var int */ + private $error; + + /** @var null|string */ + private $file; + + /** @var bool */ + private $moved = false; + + /** @var null|int */ + private $size; + + /** @var null|StreamInterface */ + private $stream; + + /** + * @param StreamInterface|string|resource $streamOrFile + * @param int $size + * @param int $errorStatus + * @param string|null $clientFilename + * @param string|null $clientMediaType + */ + public function __construct($streamOrFile, $size, $errorStatus, $clientFilename = null, $clientMediaType = null) + { + $this->setError($errorStatus); + $this->setSize($size); + $this->setClientFilename($clientFilename); + $this->setClientMediaType($clientMediaType); + + if ($this->isOk()) { + $this->setStreamOrFile($streamOrFile); + } + } + + /** + * Depending on the value set file or stream variable. + * + * @param string|resource|StreamInterface $streamOrFile + * + * @throws \InvalidArgumentException + */ + private function setStreamOrFile($streamOrFile): void + { + if (\is_string($streamOrFile)) { + $this->file = $streamOrFile; + } elseif (\is_resource($streamOrFile)) { + $this->stream = Stream::create($streamOrFile); + } elseif ($streamOrFile instanceof StreamInterface) { + $this->stream = $streamOrFile; + } else { + throw new \InvalidArgumentException('Invalid stream or file provided for UploadedFile'); + } + } + + private function setError($error): void + { + if (false === \is_int($error)) { + throw new \InvalidArgumentException('Upload file error status must be an integer'); + } + + if (false === \in_array($error, self::$errors)) { + throw new \InvalidArgumentException('Invalid error status for UploadedFile'); + } + + $this->error = $error; + } + + private function setSize($size): void + { + if (false === \is_int($size)) { + throw new \InvalidArgumentException('Upload file size must be an integer'); + } + + $this->size = $size; + } + + private function isStringOrNull($param): bool + { + return \in_array(\gettype($param), ['string', 'NULL']); + } + + private function isStringNotEmpty($param): bool + { + return \is_string($param) && false === empty($param); + } + + private function setClientFilename($clientFilename): void + { + if (false === $this->isStringOrNull($clientFilename)) { + throw new \InvalidArgumentException('Upload file client filename must be a string or null'); + } + + $this->clientFilename = $clientFilename; + } + + private function setClientMediaType($clientMediaType): void + { + if (false === $this->isStringOrNull($clientMediaType)) { + throw new \InvalidArgumentException('Upload file client media type must be a string or null'); + } + + $this->clientMediaType = $clientMediaType; + } + + /** + * @return bool return true if there is no upload error + */ + private function isOk(): bool + { + return \UPLOAD_ERR_OK === $this->error; + } + + /** + * @throws \RuntimeException if is moved or not ok + */ + private function validateActive(): void + { + if (false === $this->isOk()) { + throw new \RuntimeException('Cannot retrieve stream due to upload error'); + } + + if ($this->moved) { + throw new \RuntimeException('Cannot retrieve stream after it has already been moved'); + } + } + + public function getStream(): StreamInterface + { + $this->validateActive(); + + if ($this->stream instanceof StreamInterface) { + return $this->stream; + } + + $resource = \fopen($this->file, 'r'); + + return Stream::create($resource); + } + + public function moveTo($targetPath): void + { + $this->validateActive(); + + if (false === $this->isStringNotEmpty($targetPath)) { + throw new \InvalidArgumentException('Invalid path provided for move operation; must be a non-empty string'); + } + + if (null !== $this->file) { + $this->moved = 'cli' === PHP_SAPI ? \rename($this->file, $targetPath) : \move_uploaded_file($this->file, $targetPath); + } else { + $stream = $this->getStream(); + if ($stream->isSeekable()) { + $stream->rewind(); + } + $this->copyToStream($stream, Stream::create(\fopen($targetPath, 'w'))); + $this->moved = true; + } + + if (false === $this->moved) { + throw new \RuntimeException(\sprintf('Uploaded file could not be moved to %s', $targetPath)); + } + } + + public function getSize(): ?int + { + return $this->size; + } + + public function getError(): int + { + return $this->error; + } + + public function getClientFilename(): ?string + { + return $this->clientFilename; + } + + public function getClientMediaType(): ?string + { + return $this->clientMediaType; + } + + /** + * Copy the contents of a stream into another stream until the given number + * of bytes have been read. + * + * @author Michael Dowling and contributors to guzzlehttp/psr7 + * + * @param StreamInterface $source Stream to read from + * @param StreamInterface $dest Stream to write to + * @param int $maxLen Maximum number of bytes to read. Pass -1 + * to read the entire stream + * + * @throws \RuntimeException on error + */ + private function copyToStream(StreamInterface $source, StreamInterface $dest, $maxLen = -1) + { + if ($maxLen === -1) { + while (!$source->eof()) { + if (!$dest->write($source->read(1048576))) { + break; + } + } + + return; + } + + $bytes = 0; + while (!$source->eof()) { + $buf = $source->read($maxLen - $bytes); + if (!($len = \strlen($buf))) { + break; + } + $bytes += $len; + $dest->write($buf); + if ($bytes === $maxLen) { + break; + } + } + } +} diff --git a/vendor/nyholm/psr7/src/Uri.php b/vendor/nyholm/psr7/src/Uri.php new file mode 100644 index 0000000000000000000000000000000000000000..8376604333052807e15279581b25c7f79ee3b708 --- /dev/null +++ b/vendor/nyholm/psr7/src/Uri.php @@ -0,0 +1,329 @@ +<?php + +declare(strict_types=1); + +namespace Nyholm\Psr7; + +use Psr\Http\Message\UriInterface; + +/** + * PSR-7 URI implementation. + * + * @author Michael Dowling + * @author Tobias Schultze + * @author Matthew Weier O'Phinney + * @author Tobias Nyholm <tobias.nyholm@gmail.com> + * @author Martijn van der Ven <martijn@vanderven.se> + */ +final class Uri implements UriInterface +{ + private static $schemes = ['http' => 80, 'https' => 443]; + + private static $charUnreserved = 'a-zA-Z0-9_\-\.~'; + + private static $charSubDelims = '!\$&\'\(\)\*\+,;='; + + /** @var string Uri scheme. */ + private $scheme = ''; + + /** @var string Uri user info. */ + private $userInfo = ''; + + /** @var string Uri host. */ + private $host = ''; + + /** @var int|null Uri port. */ + private $port; + + /** @var string Uri path. */ + private $path = ''; + + /** @var string Uri query string. */ + private $query = ''; + + /** @var string Uri fragment. */ + private $fragment = ''; + + public function __construct(string $uri = '') + { + if ('' !== $uri) { + if (false === $parts = \parse_url($uri)) { + throw new \InvalidArgumentException("Unable to parse URI: $uri"); + } + + $this->applyParts($parts); + } + } + + public function __toString(): string + { + return self::createUriString($this->scheme, $this->getAuthority(), $this->path, $this->query, $this->fragment); + } + + public function getScheme(): string + { + return $this->scheme; + } + + public function getAuthority(): string + { + if ('' === $this->host) { + return ''; + } + + $authority = $this->host; + if ('' !== $this->userInfo) { + $authority = $this->userInfo.'@'.$authority; + } + + if (null !== $this->port) { + $authority .= ':'.$this->port; + } + + return $authority; + } + + public function getUserInfo(): string + { + return $this->userInfo; + } + + public function getHost(): string + { + return $this->host; + } + + public function getPort(): ?int + { + return $this->port; + } + + public function getPath(): string + { + return $this->path; + } + + public function getQuery(): string + { + return $this->query; + } + + public function getFragment(): string + { + return $this->fragment; + } + + public function withScheme($scheme): self + { + if ($this->scheme === $scheme = $this->filterScheme($scheme)) { + return $this; + } + + $new = clone $this; + $new->scheme = $scheme; + $new->port = $new->filterPort($new->port); + + return $new; + } + + public function withUserInfo($user, $password = null): self + { + $info = $user; + if (null !== $password && '' !== $password) { + $info .= ':'.$password; + } + + if ($this->userInfo === $info) { + return $this; + } + + $new = clone $this; + $new->userInfo = $info; + + return $new; + } + + public function withHost($host): self + { + if ($this->host === $host = $this->filterHost($host)) { + return $this; + } + + $new = clone $this; + $new->host = $host; + + return $new; + } + + public function withPort($port): self + { + if ($this->port === $port = $this->filterPort($port)) { + return $this; + } + + $new = clone $this; + $new->port = $port; + + return $new; + } + + public function withPath($path): self + { + if ($this->path === $path = $this->filterPath($path)) { + return $this; + } + + $new = clone $this; + $new->path = $path; + + return $new; + } + + public function withQuery($query): self + { + if ($this->query === $query = $this->filterQueryAndFragment($query)) { + return $this; + } + + $new = clone $this; + $new->query = $query; + + return $new; + } + + public function withFragment($fragment): self + { + if ($this->fragment === $fragment = $this->filterQueryAndFragment($fragment)) { + return $this; + } + + $new = clone $this; + $new->fragment = $fragment; + + return $new; + } + + /** + * Apply parse_url parts to a URI. + * + * @param array $parts Array of parse_url parts to apply + */ + private function applyParts(array $parts): void + { + $this->scheme = isset($parts['scheme']) ? $this->filterScheme($parts['scheme']) : ''; + $this->userInfo = isset($parts['user']) ? $parts['user'] : ''; + $this->host = isset($parts['host']) ? $this->filterHost($parts['host']) : ''; + $this->port = isset($parts['port']) ? $this->filterPort($parts['port']) : null; + $this->path = isset($parts['path']) ? $this->filterPath($parts['path']) : ''; + $this->query = isset($parts['query']) ? $this->filterQueryAndFragment($parts['query']) : ''; + $this->fragment = isset($parts['fragment']) ? $this->filterQueryAndFragment($parts['fragment']) : ''; + if (isset($parts['pass'])) { + $this->userInfo .= ':'.$parts['pass']; + } + } + + /** + * Create a URI string from its various parts. + */ + private static function createUriString(string $scheme, string $authority, string $path, string $query, string $fragment): string + { + $uri = ''; + if ('' !== $scheme) { + $uri .= $scheme.':'; + } + + if ('' !== $authority) { + $uri .= '//'.$authority; + } + + if ('' !== $path) { + if ('/' !== $path[0]) { + if ('' !== $authority) { + // If the path is rootless and an authority is present, the path MUST be prefixed by "/" + $path = '/'.$path; + } + } elseif (isset($path[1]) && '/' === $path[1]) { + if ('' === $authority) { + // If the path is starting with more than one "/" and no authority is present, the + // starting slashes MUST be reduced to one. + $path = '/'.\ltrim($path, '/'); + } + } + + $uri .= $path; + } + + if ('' !== $query) { + $uri .= '?'.$query; + } + + if ('' !== $fragment) { + $uri .= '#'.$fragment; + } + + return $uri; + } + + /** + * Is a given port non-standard for the current scheme? + */ + private static function isNonStandardPort(string $scheme, int $port): bool + { + return !isset(self::$schemes[$scheme]) || $port !== self::$schemes[$scheme]; + } + + private function filterScheme($scheme): string + { + if (!\is_string($scheme)) { + throw new \InvalidArgumentException('Scheme must be a string'); + } + + return \strtolower($scheme); + } + + private function filterHost($host): string + { + if (!\is_string($host)) { + throw new \InvalidArgumentException('Host must be a string'); + } + + return \strtolower($host); + } + + private function filterPort($port): ?int + { + if (null === $port) { + return null; + } + + $port = (int) $port; + if (1 > $port || 0xffff < $port) { + throw new \InvalidArgumentException(\sprintf('Invalid port: %d. Must be between 1 and 65535', $port)); + } + + return self::isNonStandardPort($this->scheme, $port) ? $port : null; + } + + private function filterPath($path): string + { + if (!\is_string($path)) { + throw new \InvalidArgumentException('Path must be a string'); + } + + return \preg_replace_callback('/(?:[^'.self::$charUnreserved.self::$charSubDelims.'%:@\/]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $path); + } + + private function filterQueryAndFragment($str): string + { + if (!\is_string($str)) { + throw new \InvalidArgumentException('Query and fragment must be a string'); + } + + return \preg_replace_callback('/(?:[^'.self::$charUnreserved.self::$charSubDelims.'%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $str); + } + + private function rawurlencodeMatchZero(array $match): string + { + return \rawurlencode($match[0]); + } +} diff --git a/vendor/psr/http-client/CHANGELOG.md b/vendor/psr/http-client/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..0bd22bb32b520e2acf61d648856f7f45ae163fc2 --- /dev/null +++ b/vendor/psr/http-client/CHANGELOG.md @@ -0,0 +1,4 @@ +# Changelog + +All notable changes to this project will be documented in this file, in reverse chronological order by release. + diff --git a/vendor/psr/http-client/LICENSE b/vendor/psr/http-client/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..cd5e0020afc2f89778937db2a8e3fc31c32b82b6 --- /dev/null +++ b/vendor/psr/http-client/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2017 PHP Framework Interoperability Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/psr/http-client/README.md b/vendor/psr/http-client/README.md new file mode 100644 index 0000000000000000000000000000000000000000..4892c32d88900ea23b9a12cce6e27f4ae098e665 --- /dev/null +++ b/vendor/psr/http-client/README.md @@ -0,0 +1,14 @@ +PSR Http Client +=============== + +This repository holds all interfaces/classes/traits related to +[PSR-18](http://www.php-fig.org/psr/psr-18/). + +Note that this is not an HTTP client implementation of its own. It is merely an +interface that describes an HTTP client. See +[the specification](https://github.com/php-fig/fig-standards/blob/master/proposed/http-client/http-client.md) +for more details. + +You can find implementations of the specification by looking for packages providing +the [psr/http-client-implementation](https://packagist.org/providers/psr/http-client-implementation) +virtual package. diff --git a/vendor/psr/http-client/composer.json b/vendor/psr/http-client/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..78cb39b6d037cd672e089ee236029d29ce659032 --- /dev/null +++ b/vendor/psr/http-client/composer.json @@ -0,0 +1,27 @@ +{ + "name": "psr/http-client", + "description": "Common interface for HTTP clients", + "keywords": ["psr", "psr-18", "http", "http-client"], + "homepage": "https://github.com/php-fig/http-client", + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "require": { + "php": "^7.0", + "psr/http-message": "^1.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/vendor/psr/http-client/src/ClientException.php b/vendor/psr/http-client/src/ClientException.php new file mode 100644 index 0000000000000000000000000000000000000000..6c6be1691178e4bc2e54141d54c329bfa8e3def9 --- /dev/null +++ b/vendor/psr/http-client/src/ClientException.php @@ -0,0 +1,10 @@ +<?php + +namespace Psr\Http\Client; + +/** + * Every HTTP client related Exception MUST implement this interface. + */ +interface ClientException extends \Throwable +{ +} \ No newline at end of file diff --git a/vendor/psr/http-client/src/ClientInterface.php b/vendor/psr/http-client/src/ClientInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..d29ef796f40b1569532018443aed1fcfbf3528fd --- /dev/null +++ b/vendor/psr/http-client/src/ClientInterface.php @@ -0,0 +1,31 @@ +<?php + +namespace Psr\Http\Client; + +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +interface ClientInterface +{ + /** + * Sends a PSR-7 request and returns a PSR-7 response. + * + * Every technically correct HTTP response MUST be returned as is, even if it represents a HTTP + * error response or a redirect instruction. The only special case is 1xx responses, which MUST + * be assembled in the HTTP client. + * + * The client MAY do modifications to the Request before sending it. Because PSR-7 objects are + * immutable, one cannot assume that the object passed to ClientInterface::sendRequest() will be the same + * object that is actually sent. For example the Request object that is returned by an exception MAY + * be a different object than the one passed to sendRequest, so comparison by reference (===) is not possible. + * + * {@link https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message-meta.md#why-value-objects} + * + * @param RequestInterface $request + * + * @return ResponseInterface + * + * @throws \Psr\Http\Client\ClientException If an error happens during processing the request. + */ + public function sendRequest(RequestInterface $request): ResponseInterface; +} diff --git a/vendor/psr/http-client/src/Exception/NetworkException.php b/vendor/psr/http-client/src/Exception/NetworkException.php new file mode 100644 index 0000000000000000000000000000000000000000..3b24090352bae04a637949c10ba6ec16084875c1 --- /dev/null +++ b/vendor/psr/http-client/src/Exception/NetworkException.php @@ -0,0 +1,25 @@ +<?php + +namespace Psr\Http\Client\Exception; + +use Psr\Http\Client\ClientException; +use Psr\Http\Message\RequestInterface; + +/** + * Thrown when the request cannot be completed because of network issues. + * + * There is no response object as this exception is thrown when no response has been received. + * + * Example: the target host name can not be resolved or the connection failed. + */ +interface NetworkException extends ClientException +{ + /** + * Returns the request. + * + * The request object MAY be a different object from the one passed to ClientInterface::sendRequest() + * + * @return RequestInterface + */ + public function getRequest(): RequestInterface; +} \ No newline at end of file diff --git a/vendor/psr/http-client/src/Exception/RequestException.php b/vendor/psr/http-client/src/Exception/RequestException.php new file mode 100644 index 0000000000000000000000000000000000000000..4c392bdc64940baff98f11b6362d16cc10d438e5 --- /dev/null +++ b/vendor/psr/http-client/src/Exception/RequestException.php @@ -0,0 +1,25 @@ +<?php + +namespace Psr\Http\Client\Exception; + +use Psr\Http\Client\ClientException; +use Psr\Http\Message\RequestInterface; + +/** + * Exception for when a request failed. + * + * Examples: + * - Request is invalid (e.g. method is missing) + * - Runtime request errors (e.g. the body stream is not seekable) + */ +interface RequestException extends ClientException +{ + /** + * Returns the request. + * + * The request object MAY be a different object from the one passed to ClientInterface::sendRequest() + * + * @return RequestInterface + */ + public function getRequest(): RequestInterface; +} diff --git a/vendor/psr/http-factory/.gitignore b/vendor/psr/http-factory/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d8a7996ab38543fe86834f6cffca7af09b935ec8 --- /dev/null +++ b/vendor/psr/http-factory/.gitignore @@ -0,0 +1,2 @@ +composer.lock +vendor/ diff --git a/vendor/psr/http-factory/.pullapprove.yml b/vendor/psr/http-factory/.pullapprove.yml new file mode 100644 index 0000000000000000000000000000000000000000..8cf081942c727499edb57c8f33df8701ef664748 --- /dev/null +++ b/vendor/psr/http-factory/.pullapprove.yml @@ -0,0 +1,7 @@ +extends: default +reviewers: + - + name: contributors + required: 1 + teams: + - http-factory-contributors diff --git a/vendor/psr/http-factory/LICENSE b/vendor/psr/http-factory/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..3f1559b2ad6a91d451af17c73208f58984d08e66 --- /dev/null +++ b/vendor/psr/http-factory/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 PHP-FIG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/psr/http-factory/README.md b/vendor/psr/http-factory/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f86868a0cff084dad3950929d35d113bdae4ee95 --- /dev/null +++ b/vendor/psr/http-factory/README.md @@ -0,0 +1,7 @@ +HTTP Factories +============== + +This is the implementation of [PSR-17 (HTTP Message Factories)][psr-17]. Please refer to the +specification for a description. + +[psr-17]: https://www.php-fig.org/psr/psr-17/ diff --git a/vendor/psr/http-factory/composer.json b/vendor/psr/http-factory/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..af62b290f918398db8fd557b2bcf6a5cae1e62f3 --- /dev/null +++ b/vendor/psr/http-factory/composer.json @@ -0,0 +1,35 @@ +{ + "name": "psr/http-factory", + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "psr", + "psr-7", + "psr-17", + "http", + "factory", + "message", + "request", + "response" + ], + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/vendor/psr/http-factory/src/RequestFactoryInterface.php b/vendor/psr/http-factory/src/RequestFactoryInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..cb39a08bf5c9969d9d8f8fc6bab847868583c465 --- /dev/null +++ b/vendor/psr/http-factory/src/RequestFactoryInterface.php @@ -0,0 +1,18 @@ +<?php + +namespace Psr\Http\Message; + +interface RequestFactoryInterface +{ + /** + * Create a new request. + * + * @param string $method The HTTP method associated with the request. + * @param UriInterface|string $uri The URI associated with the request. If + * the value is a string, the factory MUST create a UriInterface + * instance based on it. + * + * @return RequestInterface + */ + public function createRequest(string $method, $uri): RequestInterface; +} diff --git a/vendor/psr/http-factory/src/ResponseFactoryInterface.php b/vendor/psr/http-factory/src/ResponseFactoryInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..212562f00f3cb66e00d8534eb7dc88ec4b46f72d --- /dev/null +++ b/vendor/psr/http-factory/src/ResponseFactoryInterface.php @@ -0,0 +1,18 @@ +<?php + +namespace Psr\Http\Message; + +interface ResponseFactoryInterface +{ + /** + * Create a new response. + * + * @param int $code HTTP status code; defaults to 200 + * @param string $reasonPhrase Reason phrase to associate with status code + * in generated response; if none is provided implementations MAY use + * the defaults as suggested in the HTTP specification. + * + * @return ResponseInterface + */ + public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface; +} diff --git a/vendor/psr/http-factory/src/ServerRequestFactoryInterface.php b/vendor/psr/http-factory/src/ServerRequestFactoryInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..9fe031a8f4a1989a0779f45b7fb0584ff29fda61 --- /dev/null +++ b/vendor/psr/http-factory/src/ServerRequestFactoryInterface.php @@ -0,0 +1,24 @@ +<?php + +namespace Psr\Http\Message; + +interface ServerRequestFactoryInterface +{ + /** + * Create a new server request. + * + * Note that server-params are taken precisely as given - no parsing/processing + * of the given values is performed, and, in particular, no attempt is made to + * determine the HTTP method or URI, which must be provided explicitly. + * + * @param string $method The HTTP method associated with the request. + * @param UriInterface|string $uri The URI associated with the request. If + * the value is a string, the factory MUST create a UriInterface + * instance based on it. + * @param array $serverParams Array of SAPI parameters with which to seed + * the generated request instance. + * + * @return ServerRequestInterface + */ + public function createServerRequest(string $method, $uri, array $serverParams = []): ServerRequestInterface; +} diff --git a/vendor/psr/http-factory/src/StreamFactoryInterface.php b/vendor/psr/http-factory/src/StreamFactoryInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..ef4a936060ebf9b720eaae49dc7ba5a139a7aed5 --- /dev/null +++ b/vendor/psr/http-factory/src/StreamFactoryInterface.php @@ -0,0 +1,43 @@ +<?php + +namespace Psr\Http\Message; + +interface StreamFactoryInterface +{ + /** + * Create a new stream from a string. + * + * The stream SHOULD be created with a temporary resource. + * + * @param string $content String content with which to populate the stream. + * + * @return StreamInterface + */ + public function createStream(string $content = ''): StreamInterface; + + /** + * Create a stream from an existing file. + * + * The file MUST be opened using the given mode, which may be any mode + * supported by the `fopen` function. + * + * The `$filename` MAY be any string supported by `fopen()`. + * + * @param string $filename Filename or stream URI to use as basis of stream. + * @param string $mode Mode with which to open the underlying filename/stream. + * + * @return StreamInterface + */ + public function createStreamFromFile(string $filename, string $mode = 'r'): StreamInterface; + + /** + * Create a new stream from an existing resource. + * + * The stream MUST be readable and may be writable. + * + * @param resource $resource PHP resource to use as basis of stream. + * + * @return StreamInterface + */ + public function createStreamFromResource($resource): StreamInterface; +} diff --git a/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php b/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..7db4e30af736bffb28181cf8f454ea3328d0e833 --- /dev/null +++ b/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php @@ -0,0 +1,34 @@ +<?php + +namespace Psr\Http\Message; + +interface UploadedFileFactoryInterface +{ + /** + * Create a new uploaded file. + * + * If a size is not provided it will be determined by checking the size of + * the file. + * + * @see http://php.net/manual/features.file-upload.post-method.php + * @see http://php.net/manual/features.file-upload.errors.php + * + * @param StreamInterface $stream Underlying stream representing the + * uploaded file content. + * @param int $size in bytes + * @param int $error PHP file upload error + * @param string $clientFilename Filename as provided by the client, if any. + * @param string $clientMediaType Media type as provided by the client, if any. + * + * @return UploadedFileInterface + * + * @throws \InvalidArgumentException If the file resource is not readable. + */ + public function createUploadedFile( + StreamInterface $stream, + int $size = null, + int $error = \UPLOAD_ERR_OK, + string $clientFilename = null, + string $clientMediaType = null + ): UploadedFileInterface; +} diff --git a/vendor/psr/http-factory/src/UriFactoryInterface.php b/vendor/psr/http-factory/src/UriFactoryInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..06df0b46acd072a490ca9df1182abb2b01acbc14 --- /dev/null +++ b/vendor/psr/http-factory/src/UriFactoryInterface.php @@ -0,0 +1,17 @@ +<?php + +namespace Psr\Http\Message; + +interface UriFactoryInterface +{ + /** + * Create a new URI. + * + * @param string $uri + * + * @return UriInterface + * + * @throws \InvalidArgumentException If the given URI cannot be parsed. + */ + public function createUri(string $uri = ''): UriInterface; +} diff --git a/vendor/respect/validation/docs/concrete-api.md b/vendor/respect/validation/docs/concrete-api.md new file mode 100644 index 0000000000000000000000000000000000000000..735b6283d558ed32516a61b8ef6e5c87a2ee75da --- /dev/null +++ b/vendor/respect/validation/docs/concrete-api.md @@ -0,0 +1,77 @@ +# Concrete API + +There are many micro-frameworks that rely on magic methods. We don't. In this +document we're gonna explore the Respect\Validation API without fluent interfaces +or magic methods. We'll use a traditional dependency injection approach. + +```php +use Respect\Validation\Validator as v; + +$usernameValidator = v::alnum()->noWhitespace()->length(1,15); +$usernameValidator->validate('alganet'); // true +``` + +If you `var_dump($usernameValidator)`, you'll see a composite of objects with +`Respect\Validation\Rules\Alnum`, `Respect\Validation\Rules\NoWhitespace` and +`Respect\Validation\Rules\Length`. There is a specific object for each rule, and +the chain only builds the structure. You can build it by yourself: + +```php +use Respect\Validation\Rules; + +$usernameValidator = new Rules\AllOf( + new Rules\Alnum(), + new Rules\NoWhitespace(), + new Rules\Length(1, 15) +); +$usernameValidator->validate('alganet'); // true +``` + +This is still a very lean API. You can use it in any dependency injection +container or test it in the way you want. Nesting is still possible: + +```php +use Respect\Validation\Rules; + +$usernameValidator = new Rules\AllOf( + new Rules\Alnum(), + new Rules\NoWhitespace(), + new Rules\Length(1, 15) +); +$userValidator = new Rules\Key('name', $usernameValidator); +$userValidator->validate(['name' => 'alganet']); // true +``` + +## How It Works? + +The Respect\Validation chain is an +[internal DSL](http://martinfowler.com/bliki/InternalDslStyle.html). +It acts in the creational realm of objects (where Abstract Factories and Builders +live), and it's only job is to make rule construction terse and fluent. + +## FAQ + +> Is `v` in `v::something` a class name? + +No! The class is `Respect\Validation\Validator`, we suggest `v` as a very short alias. + +> Is `v::something()` a static call? + +Yes. Just like the default `DateTime::createFromFormat()` or +`Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration()`. It builds +something complex and returns for you. + +> I really don't like static calls, can I avoid it? + +Yes. Just use `$validator = new Validator();` each time you want a new validator, +and continue from there. + +> Do you have a static method for each rule? + +No. We use `__callStatic()`. + +> Magic methods are slow! Why do you use them? + +They're optional. If you use the `new` interface, they won't be called. + +(still, do some benchmarks, you'd be surprised with our implementation). diff --git a/vendor/respect/validation/docs/feature-guide.md b/vendor/respect/validation/docs/feature-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..5d96e007909c98625bbe10fb9f04f61a5ed98535 --- /dev/null +++ b/vendor/respect/validation/docs/feature-guide.md @@ -0,0 +1,301 @@ +# Feature Guide + +## Namespace import + +Respect\Validation is namespaced, but you can make your life easier by importing +a single class into your context: + +```php +use Respect\Validation\Validator as v; +``` + +## Simple validation + +The Hello World validator is something like this: + +```php +$number = 123; +v::numeric()->validate($number); // true +``` + +## Chained validation + +It is possible to use validators in a chain. Sample below validates a string +containing numbers and letters, no whitespace and length between 1 and 15. + +```php +$usernameValidator = v::alnum()->noWhitespace()->length(1, 15); +$usernameValidator->validate('alganet'); // true +``` + +## Validating object attributes + +Given this simple object: + +```php +$user = new stdClass; +$user->name = 'Alexandre'; +$user->birthdate = '1987-07-01'; +``` + +Is possible to validate its attributes in a single chain: + +```php +$userValidator = v::attribute('name', v::stringType()->length(1,32)) + ->attribute('birthdate', v::date()->age(18)); + +$userValidator->validate($user); // true +``` + +Validating array keys is also possible using `v::key()` + +Note that we used `v::stringType()` and `v::date()` in the beginning of the validator. +Although is not mandatory, it is a good practice to use the type of the +validated object as the first node in the chain. + +## Input optional + +On oldest versions of Respect\Validation all validators treat input as optional +and accept an empty string input as valid. Even though a useful feature that +caused a lot of troubles for our team and neither was an obvious behavior. Also +there was some people who likes to accept `null` as optional value, not only an +empty string. + +For that reason all rules are mandatory now but if you want to treat a value as +optional you can use `v::optional()` rule: + +```php +v::alpha()->validate(''); // false input required +v::alpha()->validate(null); // false input required + +v::optional(v::alpha())->validate(''); // true +v::optional(v::alpha())->validate(null); // true +``` + +By _optional_ we consider `null` or an empty string (`''`). + +See more on [Optional](rules/Optional.md). + +## Negating rules + +You can use the `v::not()` to negate any rule: + +```php +v::not(v::intVal())->validate(10); // false, input must not be integer +``` + +## Validator reuse + +Once created, you can reuse your validator anywhere. Remember `$usernameValidator`? + +```php +$usernameValidator->validate('respect'); //true +$usernameValidator->validate('alexandre gaigalas'); // false +$usernameValidator->validate('#$%'); //false +``` + +## Exception types + +* `Respect\Validation\Exceptions\ExceptionInterface`: + * All exceptions implement this interface; +* `Respect\Validation\Exceptions\ValidationException`: + * Implements the `Respect\Validation\Exceptions\ExceptionInterface` interface + * Thrown when the `check()` fails + * All validation exceptions extend this class + * Available methods: + * `getMainMessage()`; + * `setMode($mode)`; + * `setName($name)`; + * `setParam($name, $value)`; + * `setTemplate($template)`; + * more... +* `Respect\Validation\Exceptions\NestedValidationException`: + * Extends the `Respect\Validation\Exceptions\ValidationException` class + * Usually thrown when the `assert()` fails + * Available methods: + * `findMessages()`; + * `getFullMessage()`; + * `getMessages()`; + * more... + +## Informative exceptions + +When something goes wrong, Validation can tell you exactly what's going on. For this, +we use the `assert()` method instead of `validate()`: + +```php +use Respect\Validation\Exceptions\NestedValidationException; + +try { + $usernameValidator->assert('really messed up screen#name'); +} catch(NestedValidationException $exception) { + echo $exception->getFullMessage(); +} +``` + +The printed message is exactly this, as a nested Markdown list: + +```no-highlight +- All of the required rules must pass for "really messed up screen#name" + - "really messed up screen#name" must contain only letters (a-z) and digits (0-9) + - "really messed up screen#name" must not contain whitespace + - "really messed up screen#name" must have a length between 1 and 15 +``` + +## Getting all messages as an array + +The Markdown list is fine, but unusable on a HTML form or something more custom. +For that you can use `getMessages()`. + +It will return all messages from the rules that did not pass the validation. + +```php +try { + $usernameValidator->assert('really messed up screen#name'); +} catch(NestedValidationException $exception) { + print_r($exception->getMessages()); +} +``` + +The code above may display something like: + +```no-highlight +Array +( + [0] => "really messed up screen#name" must contain only letters (a-z) and digits (0-9) + [1] => "really messed up screen#name" must not contain whitespace + [2] => "really messed up screen#name" must have a length between 1 and 15 +) +``` + +## Getting messages as an array by name + +If you want to get specific message by name you can use `findMessages()` passing +the names of the rules you want: + +```php +try { + $usernameValidator->assert('really messed up screen#name'); +} catch(NestedValidationException $exception) { + print_r($exception->findMessages(['alnum', 'noWhitespace'])); +} +``` + +The `findMessages()` returns an array with messages from the requested validators, +like this: + +```no-highlight +Array +( + [alnum] => "really messed up screen#name" must contain only letters (a-z) and digits (0-9) + [noWhitespace] => "really messed up screen#name" must not contain whitespace +) +``` + +## Custom messages + +Getting messages as an array is fine, but sometimes you need to customize them in order +to present them to the user. This is possible using the `findMessages()` method as well: + +```php +$errors = $exception->findMessages([ + 'alnum' => '{{name}} must contain only letters and digits', + 'length' => '{{name}} must not have more than 15 chars', + 'noWhitespace' => '{{name}} cannot contain spaces' +]); +``` + +For all messages, the `{{name}}` variable is available for templates. If you +do not define a name it uses the input to replace this placeholder. + +## Message localization + +You're also able to translate your message to another language with Validation. +The only thing one must do is to define the param `translator` as a callable that +will handle the translation: + +```php +$exception->setParam('translator', 'gettext'); +``` + +The example above uses `gettext()` but you can use any other callable value, like +`[$translator, 'trans']` or `you_custom_function()`. + +After that, if you call `getMainMessage()` or `getFullMessage()` (for nested), +the message will be translated. + +Note that `getMessage()` will keep the original message. + +## Custom rules + +You also can use your own rules: + +```php +namespace My\Validation\Rules; + +use Respect\Validation\Rules\AbstractRule; + +class MyRule extends AbstractRule +{ + public function validate($input) + { + // Do something here with the $input and return a boolean value + } +} +``` + +If you do want Validation to execute you rule (or rules) in the chain, you must +use `v::with()` passing your rule's namespace as an argument: + +```php +v::with('My\\Validation\\Rules\\'); +v::myRule(); // Try to load "My\Validation\Rules\MyRule" if any +``` + +By default `with()` appends the given prefix, but you can change this behavior +in order to overwrite default rules: + +```php +v::with('My\\Validation\\Rules', true); +v::alnum(); // Try to use "My\Validation\Rules\Alnum" if any +``` + +## Validator name + +On `v::attribute()` and `v::key()`, `{{name}}` is the attribute/key name. For others, +is the same as the input. You can customize a validator name using: + +```php +v::date('Y-m-d')->between('1980-02-02', 'now')->setName('Member Since'); +``` + +## Zend/Symfony validators + +It is also possible to reuse validators from other frameworks if they are installed: + +```php +$hostnameValidator = v::zend('Hostname')->assert('google.com'); +$timeValidator = v::sf('Time')->assert('22:00:01'); +``` + +## Validation methods + +We've seen `validate()` that returns true or false and `assert()` that throws a complete +validation report. There is also a `check()` method that returns an Exception +only with the first error found: + +```php +use Respect\Validation\Exceptions\ValidationException; + +try { + $usernameValidator->check('really messed up screen#name'); +} catch(ValidationException $exception) { + echo $exception->getMainMessage(); +} +``` + +Message: + +```no-highlight +"really messed up screen#name" must contain only letters (a-z) and digits (0-9) +``` diff --git a/vendor/respect/validation/docs/index.md b/vendor/respect/validation/docs/index.md new file mode 100644 index 0000000000000000000000000000000000000000..433d433767db92c9f6814383afef5107525557e9 --- /dev/null +++ b/vendor/respect/validation/docs/index.md @@ -0,0 +1,16 @@ +# Overview + +[](http://travis-ci.org/Respect/Validation) +[](https://scrutinizer-ci.com/g/Respect/Validation/?branch=master) +[](https://scrutinizer-ci.com/g/Respect/Validation/?branch=master) +[](https://packagist.org/packages/respect/validation) +[](https://packagist.org/packages/respect/validation) +[](https://packagist.org/packages/respect/validation) + +[The most awesome validation engine ever created for PHP.](http://bit.ly/1a1oeQv) + +- Complex rules made simple: `v::numeric()->positive()->between(1, 255)->validate($input)`. +- [Granularity control](feature-guide.md#validation-methods) for advanced reporting. +- More than 100 (fully tested) validators. +- [A concrete API](concrete-api.md) for non fluent usage. +- Works on PHP 5.4+ or HHVM 3.3+ diff --git a/vendor/respect/validation/docs/installation.md b/vendor/respect/validation/docs/installation.md new file mode 100644 index 0000000000000000000000000000000000000000..9c74c657c944606dd752ed2426b06bfc3d26641b --- /dev/null +++ b/vendor/respect/validation/docs/installation.md @@ -0,0 +1,10 @@ +# Installation + +Package is available on [Packagist](http://packagist.org/packages/respect/validation), +you can install it using [Composer](http://getcomposer.org). + +```shell +composer require respect/validation +``` + +[PHP](https://php.net) 5.4+ or [HHVM](http://hhvm.com) 3.3+ are required. diff --git a/vendor/respect/validation/docs/license.md b/vendor/respect/validation/docs/license.md new file mode 100644 index 0000000000000000000000000000000000000000..ee76d0a384117a5fbdb0c17272b9cb04a6bc79b4 --- /dev/null +++ b/vendor/respect/validation/docs/license.md @@ -0,0 +1,30 @@ +# License + +Copyright (c) 2009-2015, [Alexandre Gomes Gaigalas](http://github.com/alganet). + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of Alexandre Gomes Gaigalas nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/respect/validation/docs/list-of-rules.md b/vendor/respect/validation/docs/list-of-rules.md new file mode 100644 index 0000000000000000000000000000000000000000..057be7bf323dd76f31ff934b7c594be7b327f37b --- /dev/null +++ b/vendor/respect/validation/docs/list-of-rules.md @@ -0,0 +1,329 @@ +# List of rules + +## Types + + * [ArrayVal](rules/ArrayVal.md) + * [ArrayType](rules/ArrayType.md) + * [BoolVal](rules/BoolVal.md) + * [BoolType](rules/BoolType.md) + * [CallableType](rules/CallableType.md) + * [Countable](rules/Countable.md) + * [Date](rules/Date.md) + * [FalseVal](rules/FalseVal.md) + * [FloatVal](rules/FloatVal.md) + * [FloatType](rules/FloatType.md) + * [Instance](rules/Instance.md) + * [IntVal](rules/IntVal.md) + * [IntType](rules/IntType.md) + * [IterableType](rules/IterableType.md) + * [NullType](rules/NullType.md) + * [Numeric](rules/Numeric.md) + * [ObjectType](rules/ObjectType.md) + * [ResourceType](rules/ResourceType.md) + * [ScalarVal](rules/ScalarVal.md) + * [StringType](rules/StringType.md) + * [TrueVal](rules/TrueVal.md) + * [Type](rules/Type.md) + * [Xdigit](rules/Xdigit.md) + +## Generics + + * [AlwaysInvalid](rules/AlwaysInvalid.md) + * [AlwaysValid](rules/AlwaysValid.md) + * [Call](rules/Call.md) + * [Callback](rules/Callback.md) + * [FilterVar](rules/FilterVar.md) + * [Not](rules/Not.md) + * [Optional](rules/Optional.md) + * [Type](rules/Type.md) + * [When](rules/When.md) + +## Comparing Values + + * [Age](rules/Age.md) + * [Between](rules/Between.md) + * [Equals](rules/Equals.md) + * [Identical](rules/Identical.md) + * [Max](rules/Max.md) + * [Min](rules/Min.md) + +## Numeric + + * [Between](rules/Between.md) + * [BoolType](rules/BoolType.md) + * [Even](rules/Even.md) + * [Factor](rules/Factor.md) + * [Fibonacci](rules/Fibonacci.md) + * [Finite](rules/Finite.md) + * [FloatVal](rules/FloatVal.md) + * [FloatType](rules/FloatType.md) + * [Infinite](rules/Infinite.md) + * [IntVal](rules/IntVal.md) + * [IntType](rules/IntType.md) + * [Multiple](rules/Multiple.md) + * [Negative](rules/Negative.md) + * [NotEmpty](rules/NotEmpty.md) + * [Numeric](rules/Numeric.md) + * [Odd](rules/Odd.md) + * [PerfectSquare](rules/PerfectSquare.md) + * [Positive](rules/Positive.md) + * [PrimeNumber](rules/PrimeNumber.md) + * [Roman](rules/Roman.md) + * [Xdigit](rules/Xdigit.md) + +## String + + * [Alnum](rules/Alnum.md) + * [Alpha](rules/Alpha.md) + * [Between](rules/Between.md) + * [Charset](rules/Charset.md) + * [Cntrl](rules/Cntrl.md) + * [Consonant](rules/Consonant.md) + * [Contains](rules/Contains.md) + * [Digit](rules/Digit.md) + * [EndsWith](rules/EndsWith.md) + * [Graph](rules/Graph.md) + * [In](rules/In.md) + * [Length](rules/Length.md) + * [Lowercase](rules/Lowercase.md) + * [NotEmpty](rules/NotEmpty.md) + * [NoWhitespace](rules/NoWhitespace.md) + * [PhpLabel](rules/PhpLabel.md) + * [Prnt](rules/Prnt.md) + * [Punct](rules/Punct.md) + * [Regex](rules/Regex.md) + * [ResourceType](rules/ResourceType.md) + * [Slug](rules/Slug.md) + * [Space](rules/Space.md) + * [StartsWith](rules/StartsWith.md) + * [Uppercase](rules/Uppercase.md) + * [Version](rules/Version.md) + * [Vowel](rules/Vowel.md) + * [Xdigit](rules/Xdigit.md) + +## Arrays + + * [ArrayVal](rules/ArrayVal.md) + * [ArrayType](rules/ArrayType.md) + * [Contains](rules/Contains.md) + * [Each](rules/Each.md) + * [EndsWith](rules/EndsWith.md) + * [In](rules/In.md) + * [Key](rules/Key.md) + * [KeyNested](rules/KeyNested.md) + * [KeySet](rules/KeySet.md) + * [KeyValue](rules/KeyValue.md) + * [Length](rules/Length.md) + * [NotEmpty](rules/NotEmpty.md) + * [StartsWith](rules/StartsWith.md) + +## Objects + + * [Attribute](rules/Attribute.md) + * [Instance](rules/Instance.md) + * [Length](rules/Length.md) + +## Date and Time + + * [Age](rules/Age.md) + * [Between](rules/Between.md) + * [Date](rules/Date.md) + * [LeapDate](rules/LeapDate.md) + * [LeapYear](rules/LeapYear.md) + * [MinimumAge](rules/MinimumAge.md) + +## Group Validators + + * [AllOf](rules/AllOf.md) + * [NoneOf](rules/NoneOf.md) + * [OneOf](rules/OneOf.md) + +## Regional + + * [CountryCode](rules/CountryCode.md) + * [CurrencyCode](rules/CurrencyCode.md) + * [IdentityCard](rules/IdentityCard.md) + * [LanguageCode](rules/LanguageCode.md) + * [PostalCode](rules/PostalCode.md) + * [SubdivisionCode](rules/SubdivisionCode.md) + * [Tld](rules/Tld.md) + +## Files + + * [Directory](rules/Directory.md) + * [Executable](rules/Executable.md) + * [Exists](rules/Exists.md) + * [Extension](rules/Extension.md) + * [File](rules/File.md) + * [Image](rules/Image.md) + * [Mimetype](rules/Mimetype.md) + * [Readable](rules/Readable.md) + * [Size](rules/Size.md) + * [SymbolicLink](rules/SymbolicLink.md) + * [Uploaded](rules/Uploaded.md) + * [Writable](rules/Writable.md) + +## Banking + + * [Bank](rules/Bank.md) + * [BankAccount](rules/BankAccount.md) + * [Bic](rules/Bic.md) + +## Other + + * [Bsn](rules/Bsn.md) + * [Cnh](rules/Cnh.md) + * [Cnpj](rules/Cnpj.md) + * [Cpf](rules/Cpf.md) + * [Domain](rules/Domain.md) + * [Email](rules/Email.md) + * [HexRgbColor](rules/HexRgbColor.md) + * [Imei](rules/Imei.md) + * [Ip](rules/Ip.md) + * [Json](rules/Json.md) + * [MacAddress](rules/MacAddress.md) + * [NfeAccessKey](rules/NfeAccessKey.md) + * [NotBlank](rules/NotBlank.md) + * [NotOptional](rules/NotOptional.md) + * [Pesel](rules/Pesel.md) + * [Phone](rules/Phone.md) + * [Sf](rules/Sf.md) + * [Url](rules/Url.md) + * [VideoUrl](rules/VideoUrl.md) + * [Zend](rules/Zend.md) + +## Yes/No + + * [No](rules/No.md) + * [Yes](rules/Yes.md) + +## Alphabetically + + * [Age](rules/Age.md) + * [AllOf](rules/AllOf.md) + * [Alnum](rules/Alnum.md) + * [Alpha](rules/Alpha.md) + * [AlwaysInvalid](rules/AlwaysInvalid.md) + * [AlwaysValid](rules/AlwaysValid.md) + * [ArrayVal](rules/ArrayVal.md) + * [ArrayType](rules/ArrayType.md) + * [Attribute](rules/Attribute.md) + * [Bank](rules/Bank.md) + * [BankAccount](rules/BankAccount.md) + * [Between](rules/Between.md) + * [Bic](rules/Bic.md) + * [BoolType](rules/BoolType.md) + * [Bsn](rules/Bsn.md) + * [Call](rules/Call.md) + * [CallableType](rules/CallableType.md) + * [Callback](rules/Callback.md) + * [Charset](rules/Charset.md) + * [Cnh](rules/Cnh.md) + * [Cnpj](rules/Cnpj.md) + * [Cntrl](rules/Cntrl.md) + * [Consonant](rules/Consonant.md) + * [Contains](rules/Contains.md) + * [Countable](rules/Countable.md) + * [CountryCode](rules/CountryCode.md) + * [Cpf](rules/Cpf.md) + * [CreditCard](rules/CreditCard.md) + * [Date](rules/Date.md) + * [Digit](rules/Digit.md) + * [Directory](rules/Directory.md) + * [Domain](rules/Domain.md) + * [Each](rules/Each.md) + * [Email](rules/Email.md) + * [EndsWith](rules/EndsWith.md) + * [Equals](rules/Equals.md) + * [Even](rules/Even.md) + * [Executable](rules/Executable.md) + * [Exists](rules/Exists.md) + * [Extension](rules/Extension.md) + * [Factor](rules/Factor.md) + * [FalseVal](rules/FalseVal.md) + * [Fibonacci](rules/Fibonacci.md) + * [File](rules/File.md) + * [FilterVar](rules/FilterVar.md) + * [Finite](rules/Finite.md) + * [FloatVal](rules/FloatVal.md) + * [FloatType](rules/FloatType.md) + * [Graph](rules/Graph.md) + * [HexRgbColor](rules/HexRgbColor.md) + * [Identical](rules/Identical.md) + * [IdentityCard](rules/IdentityCard.md) + * [Image](rules/Image.md) + * [Imei](rules/Imei.md) + * [In](rules/In.md) + * [Infinite](rules/Infinite.md) + * [Instance](rules/Instance.md) + * [IntVal](rules/IntVal.md) + * [IntType](rules/IntType.md) + * [Ip](rules/Ip.md) + * [IterableType](rules/IterableType.md) + * [Json](rules/Json.md) + * [Key](rules/Key.md) + * [KeyNested](rules/KeyNested.md) + * [KeySet](rules/KeySet.md) + * [KeyValue](rules/KeyValue.md) + * [LanguageCode](rules/LanguageCode.md) + * [LeapDate](rules/LeapDate.md) + * [LeapYear](rules/LeapYear.md) + * [Length](rules/Length.md) + * [Lowercase](rules/Lowercase.md) + * [MacAddress](rules/MacAddress.md) + * [Max](rules/Max.md) + * [Mimetype](rules/Mimetype.md) + * [Min](rules/Min.md) + * [MinimumAge](rules/MinimumAge.md) + * [Multiple](rules/Multiple.md) + * [Negative](rules/Negative.md) + * [NfeAccessKey](rules/NfeAccessKey.md) + * [No](rules/No.md) + * [NoWhitespace](rules/NoWhitespace.md) + * [NoneOf](rules/NoneOf.md) + * [Not](rules/Not.md) + * [NotBlank](rules/NotBlank.md) + * [NotEmpty](rules/NotEmpty.md) + * [NotOptional](rules/NotOptional.md) + * [NullType](rules/NullType.md) + * [Numeric](rules/Numeric.md) + * [ObjectType](rules/ObjectType.md) + * [Odd](rules/Odd.md) + * [OneOf](rules/OneOf.md) + * [Optional](rules/Optional.md) + * [PerfectSquare](rules/PerfectSquare.md) + * [Pesel](rules/Pesel.md) + * [Phone](rules/Phone.md) + * [PhpLabel](rules/PhpLabel.md) + * [Positive](rules/Positive.md) + * [PostalCode](rules/PostalCode.md) + * [PrimeNumber](rules/PrimeNumber.md) + * [Prnt](rules/Prnt.md) + * [Punct](rules/Punct.md) + * [Readable](rules/Readable.md) + * [Regex](rules/Regex.md) + * [ResourceType](rules/ResourceType.md) + * [Roman](rules/Roman.md) + * [ScalarVal](rules/ScalarVal.md) + * [Sf](rules/Sf.md) + * [Size](rules/Size.md) + * [Slug](rules/Slug.md) + * [Space](rules/Space.md) + * [StartsWith](rules/StartsWith.md) + * [StringType](rules/StringType.md) + * [SubdivisionCode](rules/SubdivisionCode.md) + * [SymbolicLink](rules/SymbolicLink.md) + * [Tld](rules/Tld.md) + * [TrueVal](rules/TrueVal.md) + * [Type](rules/Type.md) + * [Uploaded](rules/Uploaded.md) + * [Uppercase](rules/Uppercase.md) + * [Url](rules/Url.md) + * [Version](rules/Version.md) + * [VideoUrl](rules/VideoUrl.md) + * [Vowel](rules/Vowel.md) + * [When](rules/When.md) + * [Writable](rules/Writable.md) + * [Xdigit](rules/Xdigit.md) + * [Yes](rules/Yes.md) + * [Zend](rules/Zend.md) diff --git a/vendor/respect/validation/docs/rules/Age.md b/vendor/respect/validation/docs/rules/Age.md new file mode 100644 index 0000000000000000000000000000000000000000..740d7279b676e08c6062a1fdae87bc675fc6bbbc --- /dev/null +++ b/vendor/respect/validation/docs/rules/Age.md @@ -0,0 +1,46 @@ +# Age + +- `v::age(int $minAge)` +- `v::age(int $minAge, int $maxAge)` +- `v::age(null, int $maxAge)` + +Validates ranges of years. + +The validated values can be any date value; internally they will be transformed +into [DateTime](http://php.net/manual/en/class.datetime.php) objects according +to the defined locale settings. + +The examples below validate if the given dates are lower or equal to 18 years ago: +```php +v::age(18)->validate('17 years ago'); // false +v::age(18)->validate('18 years ago'); // true +v::age(18)->validate('19 years ago'); // true +v::age(18)->validate('1970-01-01'); // true +v::age(18)->validate('today'); // false +``` + +The examples below validate if the given dates are between 10 and 50 years ago: +```php +v::age(10, 50)->validate('9 years ago'); // false +v::age(10, 50)->validate('10 years ago'); // true +v::age(10, 50)->validate('30 years ago'); // true +v::age(10, 50)->validate('50 years ago'); // true +v::age(10, 50)->validate('51 years ago'); // false +``` + +The examples below validate if the given dates are greater than or equal to 70 years ago: +```php +v::age(null, 70)->validate('today'); // true +v::age(null, 70)->validate('70 years ago'); // true +v::age(null, 70)->validate('71 years ago'); // false +``` + +Message template for this validator includes `{{minAge}}` and `{{maxAge}}`. + +*** +See also: + + * [Between](Between.md) + * [Date](Date.md) + * [Max](Max.md) + * [Min](Min.md) diff --git a/vendor/respect/validation/docs/rules/AllOf.md b/vendor/respect/validation/docs/rules/AllOf.md new file mode 100644 index 0000000000000000000000000000000000000000..7bd2ecf0203be63de28fd5a27c59f0eb7dbe8ddc --- /dev/null +++ b/vendor/respect/validation/docs/rules/AllOf.md @@ -0,0 +1,30 @@ +# AllOf + +- `v::allOf(v $v1, v $v2, v $v3...)` + +Will validate if all inner validators validates. + +```php +v::allOf( + v::intVal(), + v::positive() +)->validate(15); // true +``` + +This is similar to the chain (which is an allOf already), but +its syntax allows you to set custom names for every node: + +```php +v::allOf( + v::intVal()->setName('Account Number'), + v::positive()->setName('Higher Than Zero') +)->setName('Positive integer') + ->validate(15); // true +``` + +*** +See also: + + * [OneOf](OneOf.md) + * [NoneOf](NoneOf.md) + * [When](When.md) diff --git a/vendor/respect/validation/docs/rules/Alnum.md b/vendor/respect/validation/docs/rules/Alnum.md new file mode 100644 index 0000000000000000000000000000000000000000..184c1e2cfb64c88fc4ee5340077c6a22e8a3710c --- /dev/null +++ b/vendor/respect/validation/docs/rules/Alnum.md @@ -0,0 +1,44 @@ +# Alnum + +- `v::alnum()` +- `v::alnum(string $additionalChars)` + +Validates alphanumeric characters from a-Z and 0-9. + +```php +v::alnum()->validate('foo 123'); // true +v::alnum()->validate('number 100%'); // false +v::alnum('%')->validate('number 100%'); // true +``` + +Because this rule allows whitespaces by default, you can separate additional +characters with a whitespace: + +```php +v::alnum('- ! :')->validate('foo :- 123 !'); // true +``` + +This validator allows whitespace, if you want to +remove them add `->noWhitespace()` to the chain: + +```php +v::alnum()->noWhitespace()->validate('foo 123'); // false +``` + +You can restrict case using the `->lowercase()` and +`->uppercase()` validators: + +```php +v::alnum()->uppercase()->validate('aaa'); // false +``` + +Message template for this validator includes `{{additionalChars}}` as +the string of extra chars passed as the parameter. + +*** +See also: + + * [Alpha](Alpha.md) + * [Digit](Digit.md) + * [Consonant](Consonant.md) + * [Vowel](Vowel.md) diff --git a/vendor/respect/validation/docs/rules/Alpha.md b/vendor/respect/validation/docs/rules/Alpha.md new file mode 100644 index 0000000000000000000000000000000000000000..44f4dc3714c3ebfd64c46a9da17bfa8a91c091f4 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Alpha.md @@ -0,0 +1,14 @@ +# Alpha + +- `v::alpha()` +- `v::alpha(string $additionalChars)` + +This is similar to `v::alnum()`, but it doesn't allow numbers. + +*** +See also: + + * [Alnum](Alnum.md) + * [Digit](Digit.md) + * [Consonant](Consonant.md) + * [Vowel](Vowel.md) diff --git a/vendor/respect/validation/docs/rules/AlwaysInvalid.md b/vendor/respect/validation/docs/rules/AlwaysInvalid.md new file mode 100644 index 0000000000000000000000000000000000000000..34b364deb352ea110706b05ade042e04f0ee079f --- /dev/null +++ b/vendor/respect/validation/docs/rules/AlwaysInvalid.md @@ -0,0 +1,14 @@ +# AlwaysInvalid + +- `v::alwaysInvalid()` + +Always return false. + +```php +v::alwaysInvalid()->validate($whatever); // false +``` + +*** +See also: + + * [AlwaysValid](AlwaysValid.md) diff --git a/vendor/respect/validation/docs/rules/AlwaysValid.md b/vendor/respect/validation/docs/rules/AlwaysValid.md new file mode 100644 index 0000000000000000000000000000000000000000..6a020bb420dfde6d6fe61722c7a15bbccd39a0bd --- /dev/null +++ b/vendor/respect/validation/docs/rules/AlwaysValid.md @@ -0,0 +1,14 @@ +# AlwaysValid + +- `v::alwaysValid()` + +Always returns true. + +```php +v::alwaysValid()->validate($whatever); // true +``` + +*** +See also: + + * [AlwaysInvalid](AlwaysInvalid.md) diff --git a/vendor/respect/validation/docs/rules/ArrayType.md b/vendor/respect/validation/docs/rules/ArrayType.md new file mode 100644 index 0000000000000000000000000000000000000000..ed72eb393ccccd6ccfdb443b8c9c94891a5d7fa9 --- /dev/null +++ b/vendor/respect/validation/docs/rules/ArrayType.md @@ -0,0 +1,27 @@ +# ArrayType + +- `v::arrayType()` + +Validates whether the type of an input is array. + +```php +v::arrayType()->validate([]); // true +v::arrayType()->validate([1, 2, 3]); // true +v::arrayType()->validate(new ArrayObject()); // false +``` + +*** +See also: + + * [ArrayVal](ArrayVal.md) + * [BoolType](BoolType.md) + * [CallableType](CallableType.md) + * [Countable](Countable.md) + * [FloatType](FloatType.md) + * [IntType](IntType.md) + * [IterableType](IterableType.md) + * [NullType](NullType.md) + * [ObjectType](ObjectType.md) + * [ResourceType](ResourceType.md) + * [StringType](StringType.md) + * [Type](Type.md) diff --git a/vendor/respect/validation/docs/rules/ArrayVal.md b/vendor/respect/validation/docs/rules/ArrayVal.md new file mode 100644 index 0000000000000000000000000000000000000000..ec9eaf066a3b42a0ea67dd7351b818bf828f0cd6 --- /dev/null +++ b/vendor/respect/validation/docs/rules/ArrayVal.md @@ -0,0 +1,22 @@ +# ArrayVal + +- `v::arrayVal()` + +Validates if the input is an array or if the input can be used as an array +(instance of `ArrayAccess`). + +```php +v::arrayVal()->validate([]); // true +v::arrayVal()->validate(new ArrayObject); // true +``` + +*** +See also: + + * [ArrayType](ArrayType.md) + * [Countable](Countable.md) + * [Each](Each.md) + * [IterableType](IterableType.md) + * [Key](Key.md) + * [KeySet](KeySet.md) + * [KeyValue](KeyValue.md) diff --git a/vendor/respect/validation/docs/rules/Attribute.md b/vendor/respect/validation/docs/rules/Attribute.md new file mode 100644 index 0000000000000000000000000000000000000000..e48b6b664bb2c58027149a4870bacf6468659b4a --- /dev/null +++ b/vendor/respect/validation/docs/rules/Attribute.md @@ -0,0 +1,33 @@ +# Attribute + +- `v::attribute(string $name)` +- `v::attribute(string $name, v $validator)` +- `v::attribute(string $name, v $validator, boolean $mandatory = true)` + +Validates an object attribute. + +```php +$obj = new stdClass; +$obj->foo = 'bar'; + +v::attribute('foo')->validate($obj); // true +``` + +You can also validate the attribute itself: + +```php +v::attribute('foo', v::equals('bar'))->validate($obj); // true +``` + +Third parameter makes the attribute presence optional: + +```php +v::attribute('lorem', v::stringType(), false)->validate($obj); // true +``` + +The name of this validator is automatically set to the attribute name. + +*** +See also: + + * [Key](Key.md) diff --git a/vendor/respect/validation/docs/rules/Bank.md b/vendor/respect/validation/docs/rules/Bank.md new file mode 100644 index 0000000000000000000000000000000000000000..028d71985d50b871bffeb9a9889c0cd8d81b27f2 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Bank.md @@ -0,0 +1,20 @@ +# Bank + +- `v::bank(string $countryCode)` + +Validates a bank. + +```php +v::bank("de")->validate("70169464"); // true +v::bank("de")->validate("12345"); // false +``` + +These country codes are supported: + + * "de" (Germany) - You must add `"malkusch/bav": "~1.0"` to your `require` property on composer.json file. + +*** +See also: + + * [BankAccount](BankAccount.md) + * [Bic](Bic.md) diff --git a/vendor/respect/validation/docs/rules/BankAccount.md b/vendor/respect/validation/docs/rules/BankAccount.md new file mode 100644 index 0000000000000000000000000000000000000000..f9d319d7f82c2ba7d6d681ab7f33ed43df3abfa4 --- /dev/null +++ b/vendor/respect/validation/docs/rules/BankAccount.md @@ -0,0 +1,20 @@ +# BankAccount + +- `v::bankAccount(string $countryCode, string $bank)` + +Validates a bank account for a given bank. + +```php +v::bankAccount("de", "70169464")->validate("1112"); // true +v::bankAccount("de", "70169464")->validate("1234"); // false +``` + +These country codes are supported: + + * "de" (Germany) - You must add `"malkusch/bav": "~1.0"` to your `require` property on composer.json file. + +*** +See also: + + * [Bank](Bank.md) + * [Bic](Bic.md) diff --git a/vendor/respect/validation/docs/rules/Between.md b/vendor/respect/validation/docs/rules/Between.md new file mode 100644 index 0000000000000000000000000000000000000000..5c0204afc9aed1fb1834d82d0050cb274b060152 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Between.md @@ -0,0 +1,44 @@ +# Between + +- `v::between(mixed $start, mixed $end)` +- `v::between(mixed $start, mixed $end, boolean $inclusive = true)` + +Validates ranges. Most simple example: + +```php +v::intVal()->between(10, 20)->validate(15); // true +``` + +The type as the first validator in a chain is a good practice, +since between accepts many types: + +```php +v::stringType()->between('a', 'f')->validate('c'); // true +``` + +Also very powerful with dates: + +```php +v::date()->between('2009-01-01', '2013-01-01')->validate('2010-01-01'); // true +``` + +Date ranges accept strtotime values: + +```php +v::date()->between('yesterday', 'tomorrow')->validate('now'); // true +``` + +A third parameter may be passed to validate the passed values inclusive: + +```php +v::date()->between(10, 20, true)->validate(20); // true +``` + +Message template for this validator includes `{{minValue}}` and `{{maxValue}}`. + +*** +See also: + + * [Length](Length.md) + * [Min](Min.md) + * [Max](Max.md) diff --git a/vendor/respect/validation/docs/rules/Bic.md b/vendor/respect/validation/docs/rules/Bic.md new file mode 100644 index 0000000000000000000000000000000000000000..82c67e8810a5caaadcd36cf798b35969935b1567 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Bic.md @@ -0,0 +1,20 @@ +# Bic + +- `v::bic(string $countryCode)` + +Validates a BIC (Bank Identifier Code) for a given country. + +```php +v::bic("de")->validate("VZVDDED1XXX"); // true +v::bic("de")->validate("VZVDDED1"); // true +``` + +Theses country codes are supported: + + * "de" (Germany) - You must add `"malkusch/bav": "~1.0"` to your `require` property on composer.json file. + +*** +See also: + + * [Bank](Bank.md) + * [BankAccount](BankAccount.md) diff --git a/vendor/respect/validation/docs/rules/BoolType.md b/vendor/respect/validation/docs/rules/BoolType.md new file mode 100644 index 0000000000000000000000000000000000000000..979562189815b5d858b03e316120796971063de5 --- /dev/null +++ b/vendor/respect/validation/docs/rules/BoolType.md @@ -0,0 +1,27 @@ +# BoolType + +- `v::boolType()` + +Validates if the input is a boolean value: + +```php +v::boolType()->validate(true); // true +v::boolType()->validate(false); // true +``` + +*** +See also: + + * [ArrayType](ArrayType.md) + * [CallableType](CallableType.md) + * [FloatType](FloatType.md) + * [FloatVal](FloatVal.md) + * [IntType](IntType.md) + * [No](No.md) + * [NullType](NullType.md) + * [ObjectType](ObjectType.md) + * [ResourceType](ResourceType.md) + * [StringType](StringType.md) + * [TrueVal](TrueVal.md) + * [Type](Type.md) + * [Yes](Yes.md) diff --git a/vendor/respect/validation/docs/rules/BoolVal.md b/vendor/respect/validation/docs/rules/BoolVal.md new file mode 100644 index 0000000000000000000000000000000000000000..26bf9a6d0d137efdb9707647190daf17041886ba --- /dev/null +++ b/vendor/respect/validation/docs/rules/BoolVal.md @@ -0,0 +1,31 @@ +# BoolVal + +- `v::boolVal()` + +Validates if the input results in a boolean value: + +```php +v::boolVal()->validate('on'); // true +v::boolVal()->validate('off'); // true +v::boolVal()->validate('yes'); // true +v::boolVal()->validate('no'); // true +v::boolVal()->validate(1); // true +v::boolVal()->validate(0); // true +``` + +*** +See also: + + * [BoolType](BoolType.md) + * [CallableType](CallableType.md) + * [FloatType](FloatType.md) + * [FloatVal](FloatVal.md) + * [IntType](IntType.md) + * [No](No.md) + * [NullType](NullType.md) + * [ObjectType](ObjectType.md) + * [ResourceType](ResourceType.md) + * [StringType](StringType.md) + * [TrueVal](TrueVal.md) + * [Type](Type.md) + * [Yes](Yes.md) diff --git a/vendor/respect/validation/docs/rules/Bsn.md b/vendor/respect/validation/docs/rules/Bsn.md new file mode 100644 index 0000000000000000000000000000000000000000..e67f55e70d22aeddfe110578ff0cd57ff05fb2e3 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Bsn.md @@ -0,0 +1,16 @@ +# Bsn + +- `v::bsn()` + +Validates a Dutch citizen service number ([BSN](https://nl.wikipedia.org/wiki/Burgerservicenummer)). + +```php +v::bsn()->validate('612890053'); // true +``` + +*** +See also: + + * [Cnh](Cnh.md) + * [Cnpj](Cnpj.md) + * [Cpf](Cpf.md) diff --git a/vendor/respect/validation/docs/rules/Call.md b/vendor/respect/validation/docs/rules/Call.md new file mode 100644 index 0000000000000000000000000000000000000000..f56b0a8e5e73b80188026d98206c916ae0fe8969 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Call.md @@ -0,0 +1,51 @@ +# Call + +- `v::call(callable $callback)` + +This is a very low level validator. It calls a function, method or closure +for the input and then validates it. Consider the following variable: + +```php +$url = 'http://www.google.com/search?q=respect.github.com' +``` + +To validate every part of this URL we could use the native `parse_url` +function to break its parts: + +```php +$parts = parse_url($url); +``` + +This function returns an array containing `scheme`, `host`, `path` and `query`. +We can validate them this way: + +```php +v::arrayVal()->key('scheme', v::startsWith('http')) + ->key('host', v::domain()) + ->key('path', v::stringType()) + ->key('query', v::notEmpty()); +``` + +Using `v::call()` you can do this in a single chain: + +```php +v::call( + 'parse_url', + v::arrayVal()->key('scheme', v::startsWith('http')) + ->key('host', v::domain()) + ->key('path', v::stringType()) + ->key('query', v::notEmpty()) +)->validate($url); +``` + +It is possible to call methods and closures as the first parameter: + +```php +v::call([$myObj, 'methodName'], v::intVal())->validate($myInput); +v::call(function($input) {}, v::intVal())->validate($myInput); +``` + +*** +See also: + + * [Callback](Callback.md) diff --git a/vendor/respect/validation/docs/rules/CallableType.md b/vendor/respect/validation/docs/rules/CallableType.md new file mode 100644 index 0000000000000000000000000000000000000000..7f24dca7b0dfcbb4ae4591061d75f75793d35709 --- /dev/null +++ b/vendor/respect/validation/docs/rules/CallableType.md @@ -0,0 +1,25 @@ +# CallableType + +- `v::callableType()` + +Validates if the input is a callable value. + +```php +v::callableType()->validate(function () {}); // true +v::callableType()->validate('trim'); // true +v::callableType()->validate([new ObjectType, 'methodName']); // true +``` + +*** +See also: + + * [ArrayType](ArrayType.md) + * [BoolType](BoolType.md) + * [Callback](Callback.md) + * [FloatType](FloatType.md) + * [IntType](IntType.md) + * [NullType](NullType.md) + * [ObjectType](ObjectType.md) + * [ResourceType](ResourceType.md) + * [StringType](StringType.md) + * [Type](Type.md) diff --git a/vendor/respect/validation/docs/rules/Callback.md b/vendor/respect/validation/docs/rules/Callback.md new file mode 100644 index 0000000000000000000000000000000000000000..d5ec6b86c62bea13d0b8b1e999129775b67e20e2 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Callback.md @@ -0,0 +1,21 @@ +# Callback + +- `v::callback(callable $callback)` + +This is a wildcard validator, it uses a function name, method or closure +to validate something: + +```php +v::callback('is_int')->validate(10); // true +``` + +(Please note that this is a sample, the `v::intVal()` validator is much better). + +As in `v::call()`, you can pass a method or closure to it. + +*** +See also: + + * [Call](Call.md) + * [CallableType](CallableType.md) + * [FilterVar](FilterVar.md) diff --git a/vendor/respect/validation/docs/rules/Charset.md b/vendor/respect/validation/docs/rules/Charset.md new file mode 100644 index 0000000000000000000000000000000000000000..43d889bdc687c4221eb82510f6fada2b39db8048 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Charset.md @@ -0,0 +1,19 @@ +# Charset + +- `v::charset(mixed $charset)` + +Validates if a string is in a specific charset. + +```php +v::charset('ASCII')->validate('açúcar'); // false +v::charset('ASCII')->validate('sugar'); //true +v::charset(['ISO-8859-1', 'EUC-JP'])->validate('日本国'); // true +``` + +The array format is a logic OR, not AND. + +*** +See also: + + * [Alnum](Alnum.md) + * [Alpha](Alpha.md) diff --git a/vendor/respect/validation/docs/rules/Cnh.md b/vendor/respect/validation/docs/rules/Cnh.md new file mode 100644 index 0000000000000000000000000000000000000000..6815929a3910d537c8e5131828dd68fd176d9d29 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Cnh.md @@ -0,0 +1,15 @@ +# Cnh + +- `v::cnh()` + +Validates a Brazillian driver's license. + +```php +v::cnh()->validate('02650306461'); // true +``` + +*** +See also: + + * [Cnpj](Cnpj.md) + * [Cpf](Cpf.md) diff --git a/vendor/respect/validation/docs/rules/Cnpj.md b/vendor/respect/validation/docs/rules/Cnpj.md new file mode 100644 index 0000000000000000000000000000000000000000..846d391762c2523cc527c61829c227ea3909f502 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Cnpj.md @@ -0,0 +1,12 @@ +# Cnpj + +- `v::cnpj()` + +Validates the Brazillian CNPJ number. Ignores non-digit chars, so +use `->digit()` if needed. + +*** +See also: + + * [Cpf](Cpf.md) + * [Cnh](Cnh.md) diff --git a/vendor/respect/validation/docs/rules/Cntrl.md b/vendor/respect/validation/docs/rules/Cntrl.md new file mode 100644 index 0000000000000000000000000000000000000000..7a6552aa8e0529dcbc08cd4017f9bd65434a1dc2 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Cntrl.md @@ -0,0 +1,17 @@ +# Cntrl + +- `v::cntrl()` +- `v::cntrl(string $additionalChars)` + +This is similar to `v::alnum()`, but only accepts control characters: + +```php +v::cntrl()->validate("\n\r\t"); // true +``` + +*** +See also: + + * [Alnum](Alnum.md) + * [Prnt](Prnt.md) + * [Space](Space.md) diff --git a/vendor/respect/validation/docs/rules/Consonant.md b/vendor/respect/validation/docs/rules/Consonant.md new file mode 100644 index 0000000000000000000000000000000000000000..fac1fe53319d7ba5afe0f39aef44f4116a1b6c71 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Consonant.md @@ -0,0 +1,18 @@ +# Consonant + +- `v::consonant()` +- `v::consonant(string $additionalChars)` + +Similar to `v::alnum()`. Validates strings that contain only consonants: + +```php +v::consonant()->validate('xkcd'); // true +``` + +*** +See also: + + * [Alnum](Alnum.md) + * [Digit](Digit.md) + * [Alpha](Alpha.md) + * [Vowel](Vowel.md) diff --git a/vendor/respect/validation/docs/rules/Contains.md b/vendor/respect/validation/docs/rules/Contains.md new file mode 100644 index 0000000000000000000000000000000000000000..6036494fe43cbbb06015a2e7edcc9fd4871d6d00 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Contains.md @@ -0,0 +1,28 @@ +# Contains + +- `v::contains(mixed $value)` +- `v::contains(mixed $value, boolean $identical = false)` + +For strings: + +```php +v::contains('ipsum')->validate('lorem ipsum'); // true +``` + +For arrays: + +```php +v::contains('ipsum')->validate(['ipsum', 'lorem']); // true +``` + +A second parameter may be passed for identical comparison instead +of equal comparison. + +Message template for this validator includes `{{containsValue}}`. + +*** +See also: + + * [StartsWith](StartsWith.md) + * [EndsWith](EndsWith.md) + * [In](In.md) diff --git a/vendor/respect/validation/docs/rules/Countable.md b/vendor/respect/validation/docs/rules/Countable.md new file mode 100644 index 0000000000000000000000000000000000000000..0353de4d7a748ed9f490149b8f07d1343f084036 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Countable.md @@ -0,0 +1,19 @@ +# Countable + +- `v::countable()` + +Validates if the input is countable, in other words, if you're allowed to use +[count()](http://php.net/count) function on it. + +```php +v::countable()->validate([]); // true +v::countable()->validate(new ArrayObject()); // true +v::countable()->validate('string'); // false +``` + +*** +See also: + + * [ArrayVal](ArrayVal.md) + * [Instance](Instance.md) + * [IterableType](IterableType.md) diff --git a/vendor/respect/validation/docs/rules/CountryCode.md b/vendor/respect/validation/docs/rules/CountryCode.md new file mode 100644 index 0000000000000000000000000000000000000000..469313db2dcb66a7306d53510b54c136afa758a8 --- /dev/null +++ b/vendor/respect/validation/docs/rules/CountryCode.md @@ -0,0 +1,14 @@ +# CountryCode + +- `v::countryCode()` + +Validates an ISO country code like US or BR. + +```php +v::countryCode()->validate('BR'); // true +``` + +*** +See also: + + * [Tld](Tld.md) diff --git a/vendor/respect/validation/docs/rules/Cpf.md b/vendor/respect/validation/docs/rules/Cpf.md new file mode 100644 index 0000000000000000000000000000000000000000..0fc3a717af13febc2d111218e534d9f61271e037 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Cpf.md @@ -0,0 +1,28 @@ +# Cpf + +- `v::cpf()` + +Validates a Brazillian CPF number. + +```php +v::cpf()->validate('44455566820'); // true +``` + +It ignores any non-digit char: + +```php +v::cpf()->validate('444.555.668-20'); // true +``` + +If you need to validate digits only, add `->digit()` to +the chain: + +```php +v::digit()->cpf()->validate('44455566820'); // true +``` + +*** +See also: + + * [Cnpj](Cnpj.md) + * [Cnh](Cnh.md) diff --git a/vendor/respect/validation/docs/rules/CreditCard.md b/vendor/respect/validation/docs/rules/CreditCard.md new file mode 100644 index 0000000000000000000000000000000000000000..aa9783a23304444b5871f7965eec499ec9de7408 --- /dev/null +++ b/vendor/respect/validation/docs/rules/CreditCard.md @@ -0,0 +1,39 @@ +# CreditCard + +- `v::creditCard()` +- `v::creditCard(string $brand)` + +Validates a credit card number. + +```php +v::creditCard()->validate('5376 7473 9720 8720'); // true + +v::creditCard('American Express')->validate('340316193809364'); // true +v::creditCard('Diners Club')->validate('30351042633884'); // true +v::creditCard('Discover')->validate('6011000990139424'); // true +v::creditCard('JCB')->validate('3566002020360505'); // true +v::creditCard('Master')->validate('5376747397208720'); // true +v::creditCard('Visa')->validate('4024007153361885'); // true +``` + +The current supported brands are: + +- American Express +- Diners Club +- Discover +- JCB +- MasterCard +- Visa + +It ignores any non-digit chars, so use `->digit()` when appropriate. + +```php +v::digit()->creditCard()->validate('5376747397208720'); // true +``` + +*** +See also: + + * [Bank](Bank.md) + * [BankAccount](BankAccount.md) + * [Bic](Bic.md) diff --git a/vendor/respect/validation/docs/rules/CurrencyCode.md b/vendor/respect/validation/docs/rules/CurrencyCode.md new file mode 100644 index 0000000000000000000000000000000000000000..95c13fae47325b977071590ec7304b7afdd5b3b6 --- /dev/null +++ b/vendor/respect/validation/docs/rules/CurrencyCode.md @@ -0,0 +1,15 @@ +# CurrencyCode + +- `v::currencyCode()` + +Validates an [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217) currency code like GBP or EUR. + +```php +v::currencyCode()->validate('GBP'); // true +``` + +*** +See also: + + * [CountryCode](CountryCode.md) + * [SubdivisionCode](SubdivisionCode.md) diff --git a/vendor/respect/validation/docs/rules/Date.md b/vendor/respect/validation/docs/rules/Date.md new file mode 100644 index 0000000000000000000000000000000000000000..4afb9ecbd56a4b49614375508f38bc18cb1b5170 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Date.md @@ -0,0 +1,40 @@ +# Date + +- `v::date()` +- `v::date(string $format)` + +Validates if input is a date: + +```php +v::date()->validate('2009-01-01'); // true +``` + +Also accepts strtotime values: + +```php +v::date()->validate('now'); // true +``` + +And DateTime instances: + +```php +v::date()->validate(new DateTime); // true +``` + +You can pass a format when validating strings: + +```php +v::date('Y-m-d')->validate('01-01-2009'); // false +``` + +Format has no effect when validating DateTime instances. + +Message template for this validator includes `{{format}}`. + +*** +See also: + + * [Between](Between.md) + * [MinimumAge](MinimumAge.md) + * [LeapDate](LeapDate.md) + * [LeapYear](LeapYear.md) diff --git a/vendor/respect/validation/docs/rules/Digit.md b/vendor/respect/validation/docs/rules/Digit.md new file mode 100644 index 0000000000000000000000000000000000000000..c4638483f4d6734817263c9891263a1ea2d41deb --- /dev/null +++ b/vendor/respect/validation/docs/rules/Digit.md @@ -0,0 +1,13 @@ +# Digit + +- `v::digit()` + +This is similar to `v::alnum()`, but it doesn't allow a-Z. + +*** +See also: + + * [Alnum](Alnum.md) + * [Alpha](Alpha.md) + * [Vowel](Vowel.md) + * [Consonant](Consonant.md) diff --git a/vendor/respect/validation/docs/rules/Directory.md b/vendor/respect/validation/docs/rules/Directory.md new file mode 100644 index 0000000000000000000000000000000000000000..7d49c63b726e0bec8c8d615092d3ed7ce275755c --- /dev/null +++ b/vendor/respect/validation/docs/rules/Directory.md @@ -0,0 +1,30 @@ +# Directory + +- `v::directory()` + +Validates directories. + +```php +v::directory()->validate(__DIR__); // true +v::directory()->validate(__FILE__); // false +``` + +This validator will consider SplFileInfo instances, so you can do something like: + +```php +v::directory()->validate(new \SplFileInfo($directory)); +``` + +*** +See also: + + * [Executable](Executable.md) + * [Exists](Exists.md) + * [Extension](Extension.md) + * [File](File.md) + * [Mimetype](Mimetype.md) + * [Readable](Readable.md) + * [Size](Size.md) + * [SymbolicLink](SymbolicLink.md) + * [Uploaded](Uploaded.md) + * [Writable](Writable.md) diff --git a/vendor/respect/validation/docs/rules/Domain.md b/vendor/respect/validation/docs/rules/Domain.md new file mode 100644 index 0000000000000000000000000000000000000000..ac5d76a7b77d89952de912a75c614fa3479f99aa --- /dev/null +++ b/vendor/respect/validation/docs/rules/Domain.md @@ -0,0 +1,40 @@ +# Domain + +- `v::domain()` +- `v::domain(boolean $tldCheck = true)` + +Validates domain names. + +```php +v::domain()->validate('google.com'); +``` + +You can skip *top level domain* (TLD) checks to validate internal +domain names: + +```php +v::domain(false)->validate('dev.machine.local'); +``` + +This is a composite validator, it validates several rules +internally: + + * If input is an IP address, it fails. + * If input contains whitespace, it fails. + * If input does not contain any dots, it fails. + * If input has less than two parts, it fails. + * Input must end with a top-level-domain to pass (if not skipped). + * Each part must be alphanumeric and not start with an hyphen. + * [PunnyCode][] is accepted for [Internationalizing Domain Names in Applications][IDNA]. + +Messages for this validator will reflect rules above. + +*** +See also: + + * [Ip](Ip.md) + * [MacAddress](MacAddress.md) + * [Tld](Tld.md) + +[PunnyCode]: http://en.wikipedia.org/wiki/Punycode "Wikipedia: Punnycode" +[IDNA]: http://en.wikipedia.org/wiki/Internationalized_domain_name#Internationalizing_Domain_Names_in_Applications "Wikipedia: Internationalized domain name" diff --git a/vendor/respect/validation/docs/rules/Each.md b/vendor/respect/validation/docs/rules/Each.md new file mode 100644 index 0000000000000000000000000000000000000000..ecc1c666359e921a9a33cdebe1a2c3ee5a6c4a92 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Each.md @@ -0,0 +1,27 @@ +# Each + +- `v::each(v $validatorForValue)` +- `v::each(null, v $validatorForKey)` +- `v::each(v $validatorForValue, v $validatorForKey)` + +Iterates over an array or Iterator and validates the value or key +of each entry: + +```php +$releaseDates = [ + 'validation' => '2010-01-01', + 'template' => '2011-01-01', + 'relational' => '2011-02-05', +]; + +v::arrayVal()->each(v::date())->validate($releaseDates); // true +v::arrayVal()->each(v::date(), v::stringType()->lowercase())->validate($releaseDates); // true +``` + +Using `arrayVal()` before `each()` is a best practice. + +*** +See also: + + * [Key](Key.md) + * [ArrayVal](ArrayVal.md) diff --git a/vendor/respect/validation/docs/rules/Email.md b/vendor/respect/validation/docs/rules/Email.md new file mode 100644 index 0000000000000000000000000000000000000000..64a4d7cf3c4896dd1786e20c99b74bd89adbf184 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Email.md @@ -0,0 +1,16 @@ +# Email + +- `v::email()` + +Validates an email address. + +```php +v::email()->validate('alexandre@gaigalas.net'); // true +``` + +*** +See also: + + * [Phone](Phone.md) + * [Url](Url.md) + * [VideoUrl](VideoUrl.md) diff --git a/vendor/respect/validation/docs/rules/EndsWith.md b/vendor/respect/validation/docs/rules/EndsWith.md new file mode 100644 index 0000000000000000000000000000000000000000..99ec5b215a194760e80132ea1083bd791b903b0e --- /dev/null +++ b/vendor/respect/validation/docs/rules/EndsWith.md @@ -0,0 +1,31 @@ +# EndsWith + +- `v::endsWith(mixed $value)` +- `v::endsWith(mixed $value, boolean $identical = false)` + +This validator is similar to `v::contains()`, but validates +only if the value is at the end of the input. + +For strings: + +```php +v::endsWith('ipsum')->validate('lorem ipsum'); // true +``` + +For arrays: + +```php +v::endsWith('ipsum')->validate(['lorem', 'ipsum']); // true +``` + +A second parameter may be passed for identical comparison instead +of equal comparison. + +Message template for this validator includes `{{endValue}}`. + +*** +See also: + + * [StartsWith](StartsWith.md) + * [Contains](Contains.md) + * [In](In.md) diff --git a/vendor/respect/validation/docs/rules/Equals.md b/vendor/respect/validation/docs/rules/Equals.md new file mode 100644 index 0000000000000000000000000000000000000000..e28f783dfcfd4128c7eecba94307e4ae53aeff1c --- /dev/null +++ b/vendor/respect/validation/docs/rules/Equals.md @@ -0,0 +1,17 @@ +# Equals + +- `v::equals(mixed $value)` + +Validates if the input is equal to some value. + +```php +v::equals('alganet')->validate('alganet'); // true +``` + +Message template for this validator includes `{{compareTo}}`. + +*** +See also: + + * [Contains](Contains.md) + * [Identical](Identical.md) diff --git a/vendor/respect/validation/docs/rules/Even.md b/vendor/respect/validation/docs/rules/Even.md new file mode 100644 index 0000000000000000000000000000000000000000..da52597b85c0793e85862dd42611df0f4da6a7cd --- /dev/null +++ b/vendor/respect/validation/docs/rules/Even.md @@ -0,0 +1,17 @@ +# Even + +- `v::even()` + +Validates an even number. + +```php +v::intVal()->even()->validate(2); // true +``` + +Using `int()` before `even()` is a best practice. + +*** +See also: + + * [Odd](Odd.md) + * [Multiple](Multiple.md) diff --git a/vendor/respect/validation/docs/rules/Executable.md b/vendor/respect/validation/docs/rules/Executable.md new file mode 100644 index 0000000000000000000000000000000000000000..7c1e1303dc350d4034dc1f8c6454e835943187e2 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Executable.md @@ -0,0 +1,23 @@ +# Executable + +- `v::executable()` + +Validates if a file is an executable. + +```php +v::email()->executable('script.sh'); // true +``` + +*** +See also: + + * [Directory](Directory.md) + * [Exists](Exists.md) + * [Extension](Extension.md) + * [File](File.md) + * [Mimetype](Mimetype.md) + * [Readable](Readable.md) + * [Size](Size.md) + * [SymbolicLink](SymbolicLink.md) + * [Uploaded](Uploaded.md) + * [Writable](Writable.md) diff --git a/vendor/respect/validation/docs/rules/Exists.md b/vendor/respect/validation/docs/rules/Exists.md new file mode 100644 index 0000000000000000000000000000000000000000..681c50743b70cd7b36548571ca47ae2d51cc4075 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Exists.md @@ -0,0 +1,30 @@ +# Exists + +- `v::exists()` + +Validates files or directories. + +```php +v::exists()->validate(__FILE__); // true +v::exists()->validate(__DIR__); // true +``` + +This validator will consider SplFileInfo instances, so you can do something like: + +```php +v::exists()->validate(new \SplFileInfo($file)); +``` + +*** +See also: + + * [Directory](Directory.md) + * [Executable](Executable.md) + * [Extension](Extension.md) + * [File](File.md) + * [Mimetype](Mimetype.md) + * [Readable](Readable.md) + * [Size](Size.md) + * [SymbolicLink](SymbolicLink.md) + * [Uploaded](Uploaded.md) + * [Writable](Writable.md) diff --git a/vendor/respect/validation/docs/rules/Extension.md b/vendor/respect/validation/docs/rules/Extension.md new file mode 100644 index 0000000000000000000000000000000000000000..4abc0d5ba51f701827dd166daac098ec79c65e3f --- /dev/null +++ b/vendor/respect/validation/docs/rules/Extension.md @@ -0,0 +1,25 @@ +# Extension + +- `v::extension(string $extension)` + +Validates if the file extension matches the expected one: + +```php +v::extension('png')->validate('image.png'); // true +``` + +This rule is case-sensitive. + +*** +See also: + + * [Directory](Directory.md) + * [Executable](Executable.md) + * [Exists](Exists.md) + * [File](File.md) + * [Mimetype](Mimetype.md) + * [Readable](Readable.md) + * [Size](Size.md) + * [SymbolicLink](SymbolicLink.md) + * [Uploaded](Uploaded.md) + * [Writable](Writable.md) diff --git a/vendor/respect/validation/docs/rules/Factor.md b/vendor/respect/validation/docs/rules/Factor.md new file mode 100644 index 0000000000000000000000000000000000000000..1e04276432d1bc8583fa89da6c004d43abdb2568 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Factor.md @@ -0,0 +1,19 @@ +# Factor + +- `v::factor(int $dividend)` + +Validates if the input is a factor of the defined dividend. + +```php +v::factor(0)->validate(5); // true +v::factor(4)->validate(2); // true +v::factor(4)->validate(3); // false +``` + +*** +See also: + + * [Digit](Digit.md) + * [Finite](Finite.md) + * [Infinite](Infinite.md) + * [Numeric](Numeric.md) diff --git a/vendor/respect/validation/docs/rules/FalseVal.md b/vendor/respect/validation/docs/rules/FalseVal.md new file mode 100644 index 0000000000000000000000000000000000000000..6ca060d33ca40dd587efb0e4583b7606b1000f03 --- /dev/null +++ b/vendor/respect/validation/docs/rules/FalseVal.md @@ -0,0 +1,21 @@ +# FalseVal + +- `v::falseVal()` + +Validates if a value is considered as `false`. + +```php +v::falseVal()->validate(false); // true +v::falseVal()->validate(0); // true +v::falseVal()->validate('0'); // true +v::falseVal()->validate('false'); // true +v::falseVal()->validate('off'); // true +v::falseVal()->validate('no'); // true +v::falseVal()->validate('0.5'); // false +v::falseVal()->validate('2'); // false +``` + +*** +See also: + + * [TrueVal](TrueVal.md) diff --git a/vendor/respect/validation/docs/rules/Fibonacci.md b/vendor/respect/validation/docs/rules/Fibonacci.md new file mode 100644 index 0000000000000000000000000000000000000000..fe8c5235b775e98fda3c81e43f1736e7e18dc30f --- /dev/null +++ b/vendor/respect/validation/docs/rules/Fibonacci.md @@ -0,0 +1,17 @@ +# Fibonacci + + - `v::fibonacci()` + +Validates whether the input follows the Fibonacci integer sequence. + +```php +v::fibonacci()->validate(1); // true +v::fibonacci()->validate('34'); // true +v::fibonacci()->validate(6); // false +``` + +*** +See also: + + * [PrimeNumber](PrimeNumber.md) + * [PerfectSquare](PerfectSquare.md) \ No newline at end of file diff --git a/vendor/respect/validation/docs/rules/File.md b/vendor/respect/validation/docs/rules/File.md new file mode 100644 index 0000000000000000000000000000000000000000..8454d0258d2d1922fc5105c71f1e6ea3a3ab28fb --- /dev/null +++ b/vendor/respect/validation/docs/rules/File.md @@ -0,0 +1,30 @@ +# File + +- `v::file()` + +Validates files. + +```php +v::file()->validate(__FILE__); // true +v::file()->validate(__DIR__); // false +``` + +This validator will consider SplFileInfo instances, so you can do something like: + +```php +v::file()->validate(new \SplFileInfo($file)); +``` + +*** +See also: + + * [Directory](Directory.md) + * [Executable](Executable.md) + * [Exists](Exists.md) + * [Extension](Extension.md) + * [Mimetype](Mimetype.md) + * [Readable](Readable.md) + * [Size](Size.md) + * [SymbolicLink](SymbolicLink.md) + * [Uploaded](Uploaded.md) + * [Writable](Writable.md) diff --git a/vendor/respect/validation/docs/rules/FilterVar.md b/vendor/respect/validation/docs/rules/FilterVar.md new file mode 100644 index 0000000000000000000000000000000000000000..a13d4fa091ffab6afb9a9df90b13d9adba374d64 --- /dev/null +++ b/vendor/respect/validation/docs/rules/FilterVar.md @@ -0,0 +1,18 @@ +# FilterVar + +- `v::filterVar(int $filter)` +- `v::filterVar(int $filter, mixed $options)` + +A wrapper for PHP's [filter_var()](http://php.net/filter_var) function. + +```php +v::filterVar(FILTER_VALIDATE_EMAIL)->validate('bob@example.com'); // true +v::filterVar(FILTER_VALIDATE_URL)->validate('http://example.com'); // true +v::filterVar(FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED)->validate('http://example.com'); // false +v::filterVar(FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED)->validate('http://example.com/path'); // true +``` + +*** +See also: + + * [Callback](Callback.md) diff --git a/vendor/respect/validation/docs/rules/Finite.md b/vendor/respect/validation/docs/rules/Finite.md new file mode 100644 index 0000000000000000000000000000000000000000..42ef9f30d6d833305e0140c368d87694dd9b887c --- /dev/null +++ b/vendor/respect/validation/docs/rules/Finite.md @@ -0,0 +1,18 @@ +# Finite + +- `v::finite()` + +Validates if the input is a finite number. + +```php +v::finite()->validate('10'); // true +v::finite()->validate(10); // true +``` + +*** +See also: + + * [Digit](Digit.md) + * [Infinite](Infinite.md) + * [IntVal](IntVal.md) + * [Numeric](Numeric.md) diff --git a/vendor/respect/validation/docs/rules/FloatType.md b/vendor/respect/validation/docs/rules/FloatType.md new file mode 100644 index 0000000000000000000000000000000000000000..87efee83511a971477a7ec4ca2f84fc4ab81dbcc --- /dev/null +++ b/vendor/respect/validation/docs/rules/FloatType.md @@ -0,0 +1,25 @@ +# FloatType + +- `v::floatType()` + +Validates whether the type of a value is float. + +```php +v::floatType()->validate(1.5); // true +v::floatType()->validate('1.5'); // false +v::floatType()->validate(0e5); // true +``` + +*** +See also: + + * [BoolType](BoolType.md) + * [CallableType](CallableType.md) + * [FloatVal](FloatVal.md) + * [IntType](IntType.md) + * [IntVal](IntVal.md) + * [NullType](NullType.md) + * [ObjectType](ObjectType.md) + * [ResourceType](ResourceType.md) + * [StringType](StringType.md) + * [Type](Type.md) diff --git a/vendor/respect/validation/docs/rules/FloatVal.md b/vendor/respect/validation/docs/rules/FloatVal.md new file mode 100644 index 0000000000000000000000000000000000000000..f73c2fc073094600820a00cba34c34ec6c378bd3 --- /dev/null +++ b/vendor/respect/validation/docs/rules/FloatVal.md @@ -0,0 +1,17 @@ +# FloatVal + +- `v::floatVal()` + +Validates a floating point number. + +```php +v::floatVal()->validate(1.5); // true +v::floatVal()->validate('1e5'); // true +``` + +*** +See also: + + * [FloatType](FloatType.md) + * [IntType](IntType.md) + * [IntVal](IntVal.md) diff --git a/vendor/respect/validation/docs/rules/Graph.md b/vendor/respect/validation/docs/rules/Graph.md new file mode 100644 index 0000000000000000000000000000000000000000..2c7503ad785414e4459968261f12b844a93db206 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Graph.md @@ -0,0 +1,15 @@ +# Graph + +- `v::graph()` +- `v::graph(string $additionalChars)` + +Validates all characters that are graphically represented. + +```php +v::graph()->validate('LKM@#$%4;'); // true +``` + +*** +See also: + + * [Prnt](Prnt.md) diff --git a/vendor/respect/validation/docs/rules/HexRgbColor.md b/vendor/respect/validation/docs/rules/HexRgbColor.md new file mode 100644 index 0000000000000000000000000000000000000000..3e4a1e98d9e538d3f90f4aa2f25ab88e85bfaf8e --- /dev/null +++ b/vendor/respect/validation/docs/rules/HexRgbColor.md @@ -0,0 +1,16 @@ +# HexRgbColor + +- `v::hexRgbColor()` + +Validates a hex RGB color + +```php +v::hexRgbColor()->validate('#FFFAAA'); // true +v::hexRgbColor()->validate('123123'); // true +v::hexRgbColor()->validate('FCD'); // true +``` + +*** +See also: + + * [Vxdigit](Vxdigit.md) diff --git a/vendor/respect/validation/docs/rules/Identical.md b/vendor/respect/validation/docs/rules/Identical.md new file mode 100644 index 0000000000000000000000000000000000000000..0a280678abbaa25cb0749d159cf47b5b117d7793 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Identical.md @@ -0,0 +1,18 @@ +# Identical + +- `v::identical(mixed $value)` + +Validates if the input is identical to some value. + +```php +v::identical(42)->validate(42); // true +v::identical(42)->validate('42'); // false +``` + +Message template for this validator includes `{{compareTo}}`. + +*** +See also: + + * [Contains](Contains.md) + * [Equals](Equals.md) diff --git a/vendor/respect/validation/docs/rules/IdentityCard.md b/vendor/respect/validation/docs/rules/IdentityCard.md new file mode 100644 index 0000000000000000000000000000000000000000..052eca1a28fd616d8538eae8d56d50cc2042a729 --- /dev/null +++ b/vendor/respect/validation/docs/rules/IdentityCard.md @@ -0,0 +1,21 @@ +# IdentityCard + +- `v::identityCard(string $countryCode)` + +Validates Identity Card numbers according to the defined country. + +```php +v::identityCard('PL')->validate('AYW036733'); // true +v::identityCard('PL')->validate('APH505567'); // true +v::identityCard('PL')->validate('APH 505567'); // false +v::identityCard('PL')->validate('AYW036731'); // false +``` + +For now this rule only accepts Polish Identity Card numbers (Dowód Osobisty). + +*** +See also: + + * [Bank](Bank.md) + * [Pesel](Pesel.md) + * [SubdivisionCode](SubdivisionCode.md) diff --git a/vendor/respect/validation/docs/rules/Image.md b/vendor/respect/validation/docs/rules/Image.md new file mode 100644 index 0000000000000000000000000000000000000000..5a84facf66d6e3f41314691b25d1fee0db21c383 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Image.md @@ -0,0 +1,32 @@ +# Image + +- `v::image()` +- `v::image(finfo $fileInfo)` + +Validates if the file is a valid image by checking its MIME type. + +```php +v::image()->validate('image.gif'); // true +v::image()->validate('image.jpg'); // true +v::image()->validate('image.png'); // true +``` + +All the validations above must return `false` if the input is not a valid file +or of the MIME doesn't match with the file extension. + +This rule relies on [fileinfo](http://php.net/fileinfo) PHP extension. + +*** +See also: + + * [Directory](Directory.md) + * [Executable](Executable.md) + * [Exists](Exists.md) + * [Extension](Extension.md) + * [File](File.md) + * [Mimetype](Mimetype.md) + * [Readable](Readable.md) + * [Size](Size.md) + * [SymbolicLink](SymbolicLink.md) + * [Uploaded](Uploaded.md) + * [Writable](Writable.md) diff --git a/vendor/respect/validation/docs/rules/Imei.md b/vendor/respect/validation/docs/rules/Imei.md new file mode 100644 index 0000000000000000000000000000000000000000..96ed8e0a2a9fd0175165d0c7dd96bdee6ae8d76b --- /dev/null +++ b/vendor/respect/validation/docs/rules/Imei.md @@ -0,0 +1,20 @@ +# Imei + +- `v::imei()` + +Validates is the input is a valid [IMEI][]. + +```php +v::imei()->validate('35-209900-176148-1'); // true +v::imei()->validate('490154203237518'); // true +``` + +*** +See also: + + * [Bsn](Bsn.md) + * [Cnh](Cnh.md) + * [Cnpj](Cnpj.md) + * [Cpf](Cpf.md) + +[IMEI]: https://en.wikipedia.org/wiki/International_Mobile_Station_Equipment_Identity "International Mobile Station Equipment Identity" diff --git a/vendor/respect/validation/docs/rules/In.md b/vendor/respect/validation/docs/rules/In.md new file mode 100644 index 0000000000000000000000000000000000000000..a8aa698141b844e55c90845c8acdefca31f05ba1 --- /dev/null +++ b/vendor/respect/validation/docs/rules/In.md @@ -0,0 +1,30 @@ +# In + +- `v::in(mixed $haystack)` +- `v::in(mixed $haystack, boolean $identical = false)` + +Validates if the input is contained in a specific haystack. + +For strings: + +```php +v::in('lorem ipsum')->validate('ipsum'); // true +``` + +For arrays: + +```php +v::in(['lorem', 'ipsum'])->validate('lorem'); // true +``` + +A second parameter may be passed for identical comparison instead +of equal comparison. + +Message template for this validator includes `{{haystack}}`. + +*** +See also: + + * [StartsWith](StartsWith.md) + * [EndsWith](EndsWith.md) + * [Contains](Contains.md) diff --git a/vendor/respect/validation/docs/rules/Infinite.md b/vendor/respect/validation/docs/rules/Infinite.md new file mode 100644 index 0000000000000000000000000000000000000000..d29c666a4f11afd0ae697fca58c4c837705a72b1 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Infinite.md @@ -0,0 +1,17 @@ +# Infinite + +- `v::infinite()` + +Validates if the input is an infinite number. + +```php +v::infinite()->validate(INF); // true +``` + +*** +See also: + + * [Digit](Digit.md) + * [Finite](Finite.md) + * [IntVal](IntVal.md) + * [Numeric](Numeric.md) diff --git a/vendor/respect/validation/docs/rules/Instance.md b/vendor/respect/validation/docs/rules/Instance.md new file mode 100644 index 0000000000000000000000000000000000000000..bbb45dd0c888a24183525f1d9e539c59bbd3c8cf --- /dev/null +++ b/vendor/respect/validation/docs/rules/Instance.md @@ -0,0 +1,17 @@ +# Instance + +- `v::instance(string $instanceName)` + +Validates if the input is an instance of the given class or interface. + +```php +v::instance('DateTime')->validate(new DateTime); // true +v::instance('Traversable')->validate(new ArrayObject); // true +``` + +Message template for this validator includes `{{instanceName}}`. + +*** +See also: + + * [ObjectType](ObjectType.md) diff --git a/vendor/respect/validation/docs/rules/IntType.md b/vendor/respect/validation/docs/rules/IntType.md new file mode 100644 index 0000000000000000000000000000000000000000..d4313657fccba3df7b4c9c9a4fd95744a6d10950 --- /dev/null +++ b/vendor/respect/validation/docs/rules/IntType.md @@ -0,0 +1,27 @@ +# IntType + +- `v::intType()` + +Validates whether the type of a value is integer. + +```php +v::intType()->validate(42); // true +v::intType()->validate('10'); // false +``` + +*** +See also: + + * [BoolType](BoolType.md) + * [CallableType](CallableType.md) + * [Digit](Digit.md) + * [Finite](Finite.md) + * [FloatType](FloatType.md) + * [Infinite](Infinite.md) + * [IntVal](IntVal.md) + * [NullType](NullType.md) + * [Numeric](Numeric.md) + * [ObjectType](ObjectType.md) + * [ResourceType](ResourceType.md) + * [StringType](StringType.md) + * [Type](Type.md) diff --git a/vendor/respect/validation/docs/rules/IntVal.md b/vendor/respect/validation/docs/rules/IntVal.md new file mode 100644 index 0000000000000000000000000000000000000000..18a04046192e8e3e6642d635d394946f16ec078f --- /dev/null +++ b/vendor/respect/validation/docs/rules/IntVal.md @@ -0,0 +1,18 @@ +# IntVal + +- `v::intVal()` + +Validates if the input is an integer. + +```php +v::intVal()->validate('10'); // true +v::intVal()->validate(10); // true +``` + +*** +See also: + + * [Digit](Digit.md) + * [Finite](Finite.md) + * [Infinite](Infinite.md) + * [Numeric](Numeric.md) diff --git a/vendor/respect/validation/docs/rules/Ip.md b/vendor/respect/validation/docs/rules/Ip.md new file mode 100644 index 0000000000000000000000000000000000000000..927dbc7ef618932495bd9e39f38e735675d27d43 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Ip.md @@ -0,0 +1,24 @@ +# Ip + +- `v::ip()` +- `v::ip(mixed $options)` + +Validates IP Addresses. This validator uses the native filter_var() +PHP function. + +```php +v::ip()->validate('192.168.0.1'); +``` + +You can pass a parameter with filter_var flags for IP. + +```php +v::ip(FILTER_FLAG_NO_PRIV_RANGE)->validate('127.0.0.1'); // false +``` + +*** +See also: + + * [Domain](Domain.md) + * [MacAddress](MacAddress.md) + * [Tld](Tld.md) diff --git a/vendor/respect/validation/docs/rules/Iterable.md b/vendor/respect/validation/docs/rules/Iterable.md new file mode 100644 index 0000000000000000000000000000000000000000..b64abe28899857ddec73717780d5e5acc4a4560c --- /dev/null +++ b/vendor/respect/validation/docs/rules/Iterable.md @@ -0,0 +1,5 @@ +# Iterable + +- `v::iterable()` + +**Deprecated**: Use [IterableType](IterableType.md) instead. diff --git a/vendor/respect/validation/docs/rules/IterableType.md b/vendor/respect/validation/docs/rules/IterableType.md new file mode 100644 index 0000000000000000000000000000000000000000..a246af271f9cba26a1b0dd538f1eb637e6056e14 --- /dev/null +++ b/vendor/respect/validation/docs/rules/IterableType.md @@ -0,0 +1,20 @@ +# IterableType + +- `v::iterableType()` + +Validates if the input is iterable, in other words, if you're able to iterate +over it with [foreach](http://php.net/foreach) language construct. + +```php +v::iterableType()->validate([]); // true +v::iterableType()->validate(new ArrayObject()); // true +v::iterableType()->validate(new stdClass()); // true +v::iterableType()->validate('string'); // false +``` + +*** +See also: + + * [ArrayVal](ArrayVal.md) + * [Countable](Countable.md) + * [Instance](Instance.md) diff --git a/vendor/respect/validation/docs/rules/Json.md b/vendor/respect/validation/docs/rules/Json.md new file mode 100644 index 0000000000000000000000000000000000000000..eb41367ceaf4ffe1b8060977dada30cad6981013 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Json.md @@ -0,0 +1,18 @@ +# Json + +- `v::json()` + +Validates if the given input is a valid JSON. + +```php +v::json()->validate('{"foo":"bar"}'); // true +``` + +*** +See also: + + * [Domain](Domain.md) + * [Email](Email.md) + * [FilterVar](FilterVar.md) + * [Phone](Phone.md) + * [VideoUrl](VideoUrl.md) diff --git a/vendor/respect/validation/docs/rules/Key.md b/vendor/respect/validation/docs/rules/Key.md new file mode 100644 index 0000000000000000000000000000000000000000..70a74c07a5a2836c4879799cddfbae89d377a23a --- /dev/null +++ b/vendor/respect/validation/docs/rules/Key.md @@ -0,0 +1,34 @@ +# Key + +- `v::key(string $name)` +- `v::key(string $name, v $validator)` +- `v::key(string $name, v $validator, boolean $mandatory = true)` + +Validates an array key. + +```php +$dict = [ + 'foo' => 'bar' +]; + +v::key('foo')->validate($dict); // true +``` + +You can also validate the key value itself: + +```php +v::key('foo', v::equals('bar'))->validate($dict); // true +``` + +Third parameter makes the key presence optional: + +```php +v::key('lorem', v::stringType(), false)->validate($dict); // true +``` + +The name of this validator is automatically set to the key name. + +*** +See also: + + * [Attribute](Attribute.md) diff --git a/vendor/respect/validation/docs/rules/KeyNested.md b/vendor/respect/validation/docs/rules/KeyNested.md new file mode 100644 index 0000000000000000000000000000000000000000..3129dde31c723082fab3332c9c0fa6a3ef81bd2e --- /dev/null +++ b/vendor/respect/validation/docs/rules/KeyNested.md @@ -0,0 +1,40 @@ +# KeyNested + +- `v::keyNested(string $name)` +- `v::keyNested(string $name, v $validator)` +- `v::keyNested(string $name, v $validator, boolean $mandatory = true)` + +Validates an array key or an object property using `.` to represent nested data. + +Validating keys from arrays or `ArrayAccess` instances: + +```php +$array = [ + 'foo' => [ + 'bar' => 123, + ], +]; + +v::keyNested('foo.bar')->validate($array); // true +``` + +Validating object properties: + +```php +$object = new stdClass(); +$object->foo = new stdClass(); +$object->foo->bar = 42; + +v::keyNested('foo.bar')->validate($object); // true +``` + +This rule was inspired by [Yii2 ArrayHelper][]. + +*** +See also: + + * [Attribute](Attribute.md) + * [Key](Key.md) + + +[Yii2 ArrayHelper]: https://github.com/yiisoft/yii2/blob/68c30c1/framework/helpers/BaseArrayHelper.php "Yii2 ArrayHelper" diff --git a/vendor/respect/validation/docs/rules/KeySet.md b/vendor/respect/validation/docs/rules/KeySet.md new file mode 100644 index 0000000000000000000000000000000000000000..faf40818aafbd384335127681e039e5c744ce1dc --- /dev/null +++ b/vendor/respect/validation/docs/rules/KeySet.md @@ -0,0 +1,51 @@ +# KeySet + +- `v::keySet(Key $rule...)` + +Validates a keys in a defined structure. + +```php +$dict = ['foo' => 42]; + +v::keySet( + v::key('foo', v::intVal()) +)->validate($dict); // true +``` + +Extra keys are not allowed: +```php +$dict = ['foo' => 42, 'bar' => 'String']; + +v::keySet( + v::key('foo', v::intVal()) +)->validate($dict); // false +``` + +Missing required keys are not allowed: +```php +$dict = ['foo' => 42, 'bar' => 'String']; + +v::keySet( + v::key('foo', v::intVal()), + v::key('bar', v::stringType()), + v::key('baz', v::boolType()) +)->validate($dict); // false +``` + +Missing non-required keys are allowed: +```php +$dict = ['foo' => 42, 'bar' => 'String']; + +v::keySet( + v::key('foo', v::intVal()), + v::key('bar', v::stringType()), + v::key('baz', v::boolType(), false) +)->validate($dict); // true +``` + +The keys' order is not considered in the validation. + +*** +See also: + + * [Key](Key.md) diff --git a/vendor/respect/validation/docs/rules/KeyValue.md b/vendor/respect/validation/docs/rules/KeyValue.md new file mode 100644 index 0000000000000000000000000000000000000000..98ee9db8731581b6fbda57e80f05742a5e4b4b0c --- /dev/null +++ b/vendor/respect/validation/docs/rules/KeyValue.md @@ -0,0 +1,62 @@ +# KeyValue + +- `keyValue(string $comparedKey, string $ruleName, string $baseKey)` + +Performs validation of `$comparedKey` using the rule named on `$ruleName` with +`$baseKey` as base. + +Sometimes, when validating arrays, the validation of a key value depends on +another key value and that may cause some ugly code since you need the input +before the validation, making some checking manually: + +```php +v::key('password')->check($_POST); +v::key('password_confirmation', v::equals($_POST['password']))->check($_POST); +``` + +The problem with the above code is because you do not know if `password` is a +valid key, so you must check it manually before performing the validation on +`password_confirmation`. + +The `keyValue()` rule makes this job easier by creating a rule named on +`$ruleName` passing `$baseKey` as the first argument of this rule, see an example: + +```php +v::keyValue('password_confirmation', 'equals', 'password')->validate($_POST); +``` + +The above code will result on `true` if _`$_POST['password_confirmation']` is +[equals](Equals.md) to `$_POST['password']`_, it's the same of: + +See another example: + +```php +v::keyValue('state', 'subdivisionCode', 'country')->validate($_POST); +``` + +The above code will result on `true` if _`$_POST['state']` is a +[subdivision code](SubdivisionCode.md) of `$_POST['country']`_: + +This rule will invalidate the input if `$comparedKey` or `$baseKey` don't exist, +or if the rule named on `$ruleName` could not be created (or don't exist). + +When using `assert()` or `check()` methods and the rule do not pass, it overwrites +all values in the validation exceptions with `$baseKey` and `$comparedKey`. + +```php +v::keyValue('password_confirmation', 'equals', 'password')->check($input); +``` + +The above code may generate the message: + +``` +password_confirmation must be equals "password" +``` + +*** +See also: + + * [Key](Key.md) + * [KeyNested](KeyNested.md) + * [KeySet](KeySet.md) + diff --git a/vendor/respect/validation/docs/rules/LanguageCode.md b/vendor/respect/validation/docs/rules/LanguageCode.md new file mode 100644 index 0000000000000000000000000000000000000000..a990f315a9a6f8d8b5261bfeab954fa5890a1bed --- /dev/null +++ b/vendor/respect/validation/docs/rules/LanguageCode.md @@ -0,0 +1,20 @@ +# LanguageCode + +- `v::languageCode()` + +Validates a language code based on ISO 639: + +```php +v::languageCode()->validate('pt'); // true +v::languageCode()->validate('en'); // true +v::languageCode()->validate('it'); // true +v::languageCode('alpha-3')->validate('ita'); // true +v::languageCode('alpha-3')->validate('eng'); // true +``` + +You can choose between alpha-2 and alpha-3, alpha-2 is set by default. + +*** +See also: + + * [CountryCode](CountryCode.md) \ No newline at end of file diff --git a/vendor/respect/validation/docs/rules/LeapDate.md b/vendor/respect/validation/docs/rules/LeapDate.md new file mode 100644 index 0000000000000000000000000000000000000000..aa0e7581f7ab4207e3f863dcd14a6c800cd5bd14 --- /dev/null +++ b/vendor/respect/validation/docs/rules/LeapDate.md @@ -0,0 +1,18 @@ +# LeapDate + +- `v::leapDate(string $format)` + +Validates if a date is leap. + +```php +v::leapDate('Y-m-d')->validate('1988-02-29'); // true +``` + +This validator accepts DateTime instances as well. The $format +parameter is mandatory. + +*** +See also: + + * [Date](Date.md) + * [LeapYear](LeapYear.md) diff --git a/vendor/respect/validation/docs/rules/LeapYear.md b/vendor/respect/validation/docs/rules/LeapYear.md new file mode 100644 index 0000000000000000000000000000000000000000..db208993164f717ab648968850f78013a8794f74 --- /dev/null +++ b/vendor/respect/validation/docs/rules/LeapYear.md @@ -0,0 +1,17 @@ +# LeapYear + +- `v::leapYear()` + +Validates if a year is leap. + +```php +v::leapYear()->validate('1988'); // true +``` + +This validator accepts DateTime instances as well. + +*** +See also: + + * [Date](Date.md) + * [LeapDate](LeapDate.md) diff --git a/vendor/respect/validation/docs/rules/Length.md b/vendor/respect/validation/docs/rules/Length.md new file mode 100644 index 0000000000000000000000000000000000000000..2fbf519536b85d41e705750ef6d05b57d0d59645 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Length.md @@ -0,0 +1,44 @@ +# Length + +- `v::length(int $min, int $max)` +- `v::length(int $min, null)` +- `v::length(null, int $max)` +- `v::length(int $min, int $max, boolean $inclusive = true)` + +Validates lengths. Most simple example: + +```php +v::stringType()->length(1, 5)->validate('abc'); // true +``` + +You can also validate only minimum length: + +```php +v::stringType()->length(5, null)->validate('abcdef'); // true +``` + +Only maximum length: + +```php +v::stringType()->length(null, 5)->validate('abc'); // true +``` + +The type as the first validator in a chain is a good practice, +since length accepts many types: + +```php +v::arrayVal()->length(1, 5)->validate(['foo', 'bar']); // true +``` + +A third parameter may be passed to validate the passed values inclusive: + +```php +v::stringType()->length(1, 5, true)->validate('a'); // true +``` + +Message template for this validator includes `{{minValue}}` and `{{maxValue}}`. + +*** +See also: + + * [Between](Between.md) diff --git a/vendor/respect/validation/docs/rules/Lowercase.md b/vendor/respect/validation/docs/rules/Lowercase.md new file mode 100644 index 0000000000000000000000000000000000000000..a79f82b76fdb91a36d71b1ceffa09daa00ea1b07 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Lowercase.md @@ -0,0 +1,14 @@ +# Lowercase + +- `v::lowercase()` + +Validates if string characters are lowercase in the input: + +```php +v::stringType()->lowercase()->validate('xkcd'); // true +``` + +*** +See also: + + * [Uppercase](Uppercase.md) diff --git a/vendor/respect/validation/docs/rules/MacAddress.md b/vendor/respect/validation/docs/rules/MacAddress.md new file mode 100644 index 0000000000000000000000000000000000000000..92f427af302b90114e4c6705be4687b1c87a3c29 --- /dev/null +++ b/vendor/respect/validation/docs/rules/MacAddress.md @@ -0,0 +1,17 @@ +# MacAddress + +- `v::macAddress()` + +Validates a Mac Address. + +```php +v::macAddress()->validate('00:11:22:33:44:55'); // true +v::macAddress()->validate('af-AA-22-33-44-55'); // true +``` + +*** +See also: + + * [Domain](Domain.md) + * [Ip](Ip.md) + * [Tld](Tld.md) diff --git a/vendor/respect/validation/docs/rules/Max.md b/vendor/respect/validation/docs/rules/Max.md new file mode 100644 index 0000000000000000000000000000000000000000..1c199b9497ad9067e2241117fbc8893543443996 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Max.md @@ -0,0 +1,36 @@ +# Max + +- `v::max(mixed $maxValue)` +- `v::max(mixed $maxValue, boolean $inclusive = true)` + +Validates if the input doesn't exceed the maximum value. + +```php +v::intVal()->max(15)->validate(20); // false +v::intVal()->max(20)->validate(20); // false +v::intVal()->max(20, true)->validate(20); // true +``` + +Also accepts dates: + +```php +v::date()->max('2012-01-01')->validate('2010-01-01'); // true +``` + +Also date intervals: + +```php +// Same of minimum age validation +v::date()->max('-18 years')->validate('1988-09-09'); // true +``` + +`true` may be passed as a parameter to indicate that inclusive +values must be used. + +Message template for this validator includes `{{maxValue}}`. + +*** +See also: + + * [Min](Min.md) + * [Between](Between.md) diff --git a/vendor/respect/validation/docs/rules/Mimetype.md b/vendor/respect/validation/docs/rules/Mimetype.md new file mode 100644 index 0000000000000000000000000000000000000000..a2af05e8c74aec337944d3a1566a5a050ba822b4 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Mimetype.md @@ -0,0 +1,25 @@ +# Mimetype + +- `v::mimetype(string $mimetype)` + +Validates if the file mimetype matches the expected one: + +```php +v::mimetype('image/png')->validate('image.png'); // true +``` + +This rule is case-sensitive and requires [fileinfo](http://php.net/fileinfo) PHP extension. + +*** +See also: + + * [Directory](Directory.md) + * [Executable](Executable.md) + * [Exists](Exists.md) + * [Extension](Extension.md) + * [File](File.md) + * [Readable](Readable.md) + * [Size](Size.md) + * [SymbolicLink](SymbolicLink.md) + * [Uploaded](Uploaded.md) + * [Writable](Writable.md) diff --git a/vendor/respect/validation/docs/rules/Min.md b/vendor/respect/validation/docs/rules/Min.md new file mode 100644 index 0000000000000000000000000000000000000000..460154f25f8435fe489caff1681dd0c1ee49ce37 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Min.md @@ -0,0 +1,29 @@ +# Min + +- `v::min(mixed $minValue)` +- `v::min(mixed $minValue, boolean $inclusive = true)` + +Validates if the input is greater than the minimum value. + +```php +v::intVal()->min(15)->validate(5); // false +v::intVal()->min(5)->validate(5); // false +v::intVal()->min(5, true)->validate(5); // true +``` + +Also accepts dates: + +```php +v::date()->min('2012-01-01')->validate('2015-01-01'); // true +``` + +`true` may be passed as a parameter to indicate that inclusive +values must be used. + +Message template for this validator includes `{{minValue}}`. + +*** +See also: + + * [Max](Max.md) + * [Between](Between.md) diff --git a/vendor/respect/validation/docs/rules/MinimumAge.md b/vendor/respect/validation/docs/rules/MinimumAge.md new file mode 100644 index 0000000000000000000000000000000000000000..33b457ae0b0ad2d3b34288a56569dee05e6e6188 --- /dev/null +++ b/vendor/respect/validation/docs/rules/MinimumAge.md @@ -0,0 +1,23 @@ +# MinimumAge + +This is going to be deprecated, please use [Age](Age.md) instead. + +- `v::minimumAge(int $age)` +- `v::minimumAge(int $age, string $format)` + +Validates a minimum age for a given date. + +```php +v::minimumAge(18)->validate('1987-01-01'); // true +v::minimumAge(18, 'd/m/Y')->validate('01/01/1987'); // true +``` + +Using `date()` before is a best-practice. + +Message template for this validator includes `{{age}}`. + +*** +See also: + + * [Age](Age.md) + * [Date](Date.md) diff --git a/vendor/respect/validation/docs/rules/Multiple.md b/vendor/respect/validation/docs/rules/Multiple.md new file mode 100644 index 0000000000000000000000000000000000000000..b6d8c7ff02ce91038d3b57c4abff84308cacc737 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Multiple.md @@ -0,0 +1,14 @@ +# Multiple + +- `v::multiple(int $multipleOf)` + +Validates if the input is a multiple of the given parameter + +```php +v::intVal()->multiple(3)->validate(9); // true +``` + +*** +See also: + + * [PrimeNumber](PrimeNumber.md) diff --git a/vendor/respect/validation/docs/rules/Negative.md b/vendor/respect/validation/docs/rules/Negative.md new file mode 100644 index 0000000000000000000000000000000000000000..efecb52018b0763c49d61deec12b3f45b1bbec7c --- /dev/null +++ b/vendor/respect/validation/docs/rules/Negative.md @@ -0,0 +1,14 @@ +# Negative + +- `v::negative()` + +Validates if a number is lower than zero + +```php +v::numeric()->negative()->validate(-15); // true +``` + +*** +See also: + + * [Positive](Positive.md) diff --git a/vendor/respect/validation/docs/rules/NfeAccessKey.md b/vendor/respect/validation/docs/rules/NfeAccessKey.md new file mode 100644 index 0000000000000000000000000000000000000000..2f9188f1b0ce52d960b4ef30f58dd17b203c6d61 --- /dev/null +++ b/vendor/respect/validation/docs/rules/NfeAccessKey.md @@ -0,0 +1,16 @@ +# NfeAccessKey + +- `v::nfeAccessKey(string $accessKey)` + +Validates the access key of the Brazilian electronic invoice (NFe). + +```php +v::nfeAccessKey()->validate('31841136830118868211870485416765268625116906'); // true +``` + +*** +See also: + + * [Cnh](Cnh.md) + * [Cnpj](Cnpj.md) + * [Cpf](Cpf.md) diff --git a/vendor/respect/validation/docs/rules/No.md b/vendor/respect/validation/docs/rules/No.md new file mode 100644 index 0000000000000000000000000000000000000000..e50b4c72becd343ad8682869488b9522d8fd456f --- /dev/null +++ b/vendor/respect/validation/docs/rules/No.md @@ -0,0 +1,24 @@ +# No + +- `v::no()` +- `v::no(boolean $locale)` + +Validates if value is considered as "No". + +```php +v::no()->validate('N'); // true +v::no()->validate('Nay'); // true +v::no()->validate('Nix'); // true +v::no()->validate('No'); // true +v::no()->validate('Nope'); // true +v::no()->validate('Not'); // true +``` + +This rule is case insensitive. + +If `$locale` is TRUE, uses the value of [nl_langinfo()](http://php.net/nl_langinfo) with `NOEXPR` constant. + +*** +See also: + + * [Yes](Yes.md) diff --git a/vendor/respect/validation/docs/rules/NoWhitespace.md b/vendor/respect/validation/docs/rules/NoWhitespace.md new file mode 100644 index 0000000000000000000000000000000000000000..052cfcdee028d66c24fe55bb1b6bce6ee64e7a27 --- /dev/null +++ b/vendor/respect/validation/docs/rules/NoWhitespace.md @@ -0,0 +1,21 @@ +# NoWhitespace + +- `v::noWhitespace()` + +Validates if a string contains no whitespace (spaces, tabs and line breaks); + +```php +v::noWhitespace()->validate('foo bar'); //false +v::noWhitespace()->validate("foo\nbar"); // false +``` + +This is most useful when chaining with other validators such as `v::alnum()` + +*** +See also: + + * [Alnum](Alnum.md) + * [Alpha](Alpha.md) + * [NotBlank](NotBlank.md) + * [NotEmpty](NotEmpty.md) + * [NotOptional](NotOptional.md) diff --git a/vendor/respect/validation/docs/rules/NoneOf.md b/vendor/respect/validation/docs/rules/NoneOf.md new file mode 100644 index 0000000000000000000000000000000000000000..44e91537e8754135bf7f3a0400e0d5259d036188 --- /dev/null +++ b/vendor/respect/validation/docs/rules/NoneOf.md @@ -0,0 +1,21 @@ +# NoneOf + +- `v::noneOf(v $v1, v $v2, v $v3...)` + +Validates if NONE of the given validators validate: + +```php +v::noneOf( + v::intVal(), + v::floatVal() +)->validate('foo'); // true +``` + +In the sample above, 'foo' isn't a integer nor a float, so noneOf returns true. + +*** +See also: + + * [Not](Not.md) + * [AllOf](AllOf.md) + * [OneOf](OneOf.md) diff --git a/vendor/respect/validation/docs/rules/Not.md b/vendor/respect/validation/docs/rules/Not.md new file mode 100644 index 0000000000000000000000000000000000000000..31f575bca1748ce768a9dbc54e4b9ed4d7d7e4c3 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Not.md @@ -0,0 +1,24 @@ +# Not + +- `v::not(v $negatedValidator)` + +Negates any rule. + +```php +v::not(v::ip())->validate('foo'); // true +``` + +In the sample above, validator returns true because 'foo' isn't an IP Address. + +You can negate complex, grouped or chained validators as well: + +```php +v::not(v::intVal()->positive())->validate(-1.5); // true +``` + +Each other validation has custom messages for negated rules. + +*** +See also: + + * [NoneOf](NoneOf.md) diff --git a/vendor/respect/validation/docs/rules/NotBlank.md b/vendor/respect/validation/docs/rules/NotBlank.md new file mode 100644 index 0000000000000000000000000000000000000000..35a5ef2de273e29918c98c4a743603b026ffd3ca --- /dev/null +++ b/vendor/respect/validation/docs/rules/NotBlank.md @@ -0,0 +1,34 @@ +# NotBlank + +- `v::notBlank()` + +Validates if the given input is not a blank value (`null`, zeros, empty strings +or empty arrays, recursively). + +```php +v::notBlank()->validate(null); // false +v::notBlank()->validate(''); // false +v::notBlank()->validate([]); // false +v::notBlank()->validate(' '); // false +v::notBlank()->validate(0); // false +v::notBlank()->validate('0'); // false +v::notBlank()->validate(0); // false +v::notBlank()->validate('0.0'); // false +v::notBlank()->validate(false); // false +v::notBlank()->validate(['']); // false +v::notBlank()->validate([' ']); // false +v::notBlank()->validate([0]); // false +v::notBlank()->validate(['0']); // false +v::notBlank()->validate([false]); // false +v::notBlank()->validate([[''], [0]]); // false +v::notBlank()->validate(new stdClass()); // false +``` + +It's similar to [NotEmpty](NotEmpty.md) but it's way more strict. + +*** +See also: + + * [NoWhitespace](NoWhitespace.md) + * [NotEmpty](NotEmpty.md) + * [NullType](NullType.md) diff --git a/vendor/respect/validation/docs/rules/NotEmpty.md b/vendor/respect/validation/docs/rules/NotEmpty.md new file mode 100644 index 0000000000000000000000000000000000000000..ab888f6a641664ad296b7de9cb616c4421500f08 --- /dev/null +++ b/vendor/respect/validation/docs/rules/NotEmpty.md @@ -0,0 +1,42 @@ +# NotEmpty + +- `v::notEmpty()` + +Validates if the given input is not empty or in other words is input mandatory and +required. This function also takes whitespace into account, use `noWhitespace()` +if no spaces or linebreaks and other whitespace anywhere in the input is desired. + +```php +v::stringType()->notEmpty()->validate(''); // false +``` + +Null values are empty: + +```php +v::notEmpty()->validate(null); // false +``` + +Numbers: + +```php +v::intVal()->notEmpty()->validate(0); // false +``` + +Empty arrays: + +```php +v::arrayVal()->notEmpty()->validate([]); // false +``` + +Whitespace: + +```php +v::stringType()->notEmpty()->validate(' '); //false +v::stringType()->notEmpty()->validate("\t \n \r"); //false +``` + +*** +See also: + + * [NoWhitespace](NoWhitespace.md) + * [NullType](NullType.md) diff --git a/vendor/respect/validation/docs/rules/NotOptional.md b/vendor/respect/validation/docs/rules/NotOptional.md new file mode 100644 index 0000000000000000000000000000000000000000..487e7f1ef253ff82ead7b3f150f7c07a3163209b --- /dev/null +++ b/vendor/respect/validation/docs/rules/NotOptional.md @@ -0,0 +1,39 @@ +# NotOptional + +- `v::notOptional()` + +Validates if the given input is not optional. By _optional_ we consider `null` +or an empty string (`''`). + +```php +v::notOptional()->validate(''); // false +v::notOptional()->validate(null); // false +``` + +Other values: + +```php +v::notOptional()->validate([]); // true +v::notOptional()->validate(' '); // true +v::notOptional()->validate(0); // true +v::notOptional()->validate('0'); // true +v::notOptional()->validate(0); // true +v::notOptional()->validate('0.0'); // true +v::notOptional()->validate(false); // true +v::notOptional()->validate(['']); // true +v::notOptional()->validate([' ']); // true +v::notOptional()->validate([0]); // true +v::notOptional()->validate(['0']); // true +v::notOptional()->validate([false]); // true +v::notOptional()->validate([[''), [0]]); // true +v::notOptional()->validate(new stdClass()); // true +``` + +*** +See also: + + * [NoWhitespace](NoWhitespace.md) + * [NotBlank](NotBlank.md) + * [NotEmpty](NotEmpty.md) + * [NullType](NullType.md) + * [Optional](Optional.md) diff --git a/vendor/respect/validation/docs/rules/NullType.md b/vendor/respect/validation/docs/rules/NullType.md new file mode 100644 index 0000000000000000000000000000000000000000..5b39feb6c2d0eb36a964fc982d2fcd58aa73cea8 --- /dev/null +++ b/vendor/respect/validation/docs/rules/NullType.md @@ -0,0 +1,25 @@ +# NullType + +- `v::nullType()` + +Validates if the input is null. + +```php +v::nullType()->validate(null); // true +``` + +*** +See also: + + * [BoolType](BoolType.md) + * [CallableType](CallableType.md) + * [FloatType](FloatType.md) + * [IntType](IntType.md) + * [NotBlank](NotBlank.md) + * [NotEmpty](NotEmpty.md) + * [NotOptional](NotOptional.md) + * [NullType](NullType.md) + * [ObjectType](ObjectType.md) + * [ResourceType](ResourceType.md) + * [StringType](StringType.md) + * [Type](Type.md) diff --git a/vendor/respect/validation/docs/rules/Numeric.md b/vendor/respect/validation/docs/rules/Numeric.md new file mode 100644 index 0000000000000000000000000000000000000000..d8121fb61c9ae621e4ebe74b45b80853e5c95721 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Numeric.md @@ -0,0 +1,18 @@ +# Numeric + +- `v::numeric()` + +Validates on any numeric value. + +```php +v::numeric()->validate(-12); // true +v::numeric()->validate('135.0'); // true +``` + +*** +See also: + + * [Digit](Digit.md) + * [Finite](Finite.md) + * [Infinite](Infinite.md) + * [IntVal](IntVal.md) diff --git a/vendor/respect/validation/docs/rules/ObjectType.md b/vendor/respect/validation/docs/rules/ObjectType.md new file mode 100644 index 0000000000000000000000000000000000000000..39212603155048570ca891161b495f1f8f41792c --- /dev/null +++ b/vendor/respect/validation/docs/rules/ObjectType.md @@ -0,0 +1,24 @@ +# ObjectType + +- `v::objectType()` + +Validates if the input is an object. + +```php +v::objectType()->validate(new stdClass); // true +``` + +*** +See also: + + * [Attribute](Attribute.md) + * [BoolType](BoolType.md) + * [CallableType](CallableType.md) + * [FloatType](FloatType.md) + * [Instance](Instance.md) + * [IntType](IntType.md) + * [NullType](NullType.md) + * [ObjectType](ObjectType.md) + * [ResourceType](ResourceType.md) + * [StringType](StringType.md) + * [Type](Type.md) diff --git a/vendor/respect/validation/docs/rules/Odd.md b/vendor/respect/validation/docs/rules/Odd.md new file mode 100644 index 0000000000000000000000000000000000000000..b1a8d05fc978f94cd5e074288b5988969c161868 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Odd.md @@ -0,0 +1,17 @@ +# Odd + +- `v::odd()` + +Validates an odd number. + +```php +v::intVal()->odd()->validate(3); // true +``` + +Using `int()` before `odd()` is a best practice. + +*** +See also: + + * [Even](Even.md) + * [Multiple](Multiple.md) diff --git a/vendor/respect/validation/docs/rules/OneOf.md b/vendor/respect/validation/docs/rules/OneOf.md new file mode 100644 index 0000000000000000000000000000000000000000..e16be50df043ad94aa622584da26a71746077ee0 --- /dev/null +++ b/vendor/respect/validation/docs/rules/OneOf.md @@ -0,0 +1,25 @@ +# OneOf + +- `v::oneOf(v $v1, v $v2, v $v3...)` + +This is a group validator that acts as an OR operator. + +```php +v::oneOf( + v::intVal(), + v::floatVal() +)->validate(15.5); // true +``` + +In the sample above, `v::intVal()` doesn't validates, but +`v::floatVal()` validates, so oneOf returns true. + +`v::oneOf` returns true if at least one inner validator +passes. + +*** +See also: + + * [AllOf](AllOf.md) + * [NoneOf](NoneOf.md) + * [When](When.md) diff --git a/vendor/respect/validation/docs/rules/Optional.md b/vendor/respect/validation/docs/rules/Optional.md new file mode 100644 index 0000000000000000000000000000000000000000..1a4aa5ec091f9731c70ae017489abc01c6424de1 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Optional.md @@ -0,0 +1,21 @@ +# Optional + +- `v::optional(v $rule)` + +Validates if the given input is optional or not. By _optional_ we consider `null` +or an empty string (`''`). + +```php +v::optional(v::alpha())->validate(''); // true +v::optional(v::digit())->validate(null); // true +``` + + +*** +See also: + + * [NoWhitespace](NoWhitespace.md) + * [NotBlank](NotBlank.md) + * [NotEmpty](NotEmpty.md) + * [NotOptional](NotOptional.md) + * [NullType](NullType.md) diff --git a/vendor/respect/validation/docs/rules/PerfectSquare.md b/vendor/respect/validation/docs/rules/PerfectSquare.md new file mode 100644 index 0000000000000000000000000000000000000000..3a344b27c9125bd28f0ac6afc1fa8b3d485d372b --- /dev/null +++ b/vendor/respect/validation/docs/rules/PerfectSquare.md @@ -0,0 +1,16 @@ +# PerfectSquare + +- `v::perfectSquare()` + +Validates a perfect square. + +```php +v::perfectSquare()->validate(25); // true (5*5) +v::perfectSquare()->validate(9); // true (3*3) +``` + +*** +See also: + + * [Factor](Factor.md) + * [PrimeNumber](PrimeNumber.md) diff --git a/vendor/respect/validation/docs/rules/Pesel.md b/vendor/respect/validation/docs/rules/Pesel.md new file mode 100644 index 0000000000000000000000000000000000000000..275ff7f8d3117304f091e08f9b3424aff30cbf65 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Pesel.md @@ -0,0 +1,12 @@ +# Pesel + +- `v::pesel()` + +Validates PESEL (Polish human identification number). + +```php +v::pesel()->validate('21120209256'); // true +v::pesel()->validate('97072704800'); // true +v::pesel()->validate('97072704801'); // false +v::pesel()->validate('PESEL123456'); // false +``` diff --git a/vendor/respect/validation/docs/rules/Phone.md b/vendor/respect/validation/docs/rules/Phone.md new file mode 100644 index 0000000000000000000000000000000000000000..ac3cba9b9582c7192467e65376d4c0e7dd8b0899 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Phone.md @@ -0,0 +1,22 @@ +# Phone + +- `v::phone()` + +Validates a valid 7, 10, 11 digit phone number (North America, Europe and most +Asian and Middle East countries), supporting country and area codes (in dot, +space or dashed notations) such as: + + (555)555-5555 + 555 555 5555 + +5(555)555.5555 + 33(1)22 22 22 22 + +33(1)22 22 22 22 + +33(020)7777 7777 + 03-6106666 + +*** +See also: + + * [Email](Email.md) + * [Url](Url.md) + * [VideoUrl](VideoUrl.md) diff --git a/vendor/respect/validation/docs/rules/PhpLabel.md b/vendor/respect/validation/docs/rules/PhpLabel.md new file mode 100644 index 0000000000000000000000000000000000000000..4295267d72fb63767b02985ce2fd2f4479226e43 --- /dev/null +++ b/vendor/respect/validation/docs/rules/PhpLabel.md @@ -0,0 +1,24 @@ +# PhpLabel + +- `v::phpLabel()` + +Validates if a value is considered a valid PHP Label, +so that it can be used as a *variable*, *function* or *class* name, for example. + +Reference: +http://php.net/manual/en/language.variables.basics.php + +```php +v::phpLabel()->validate('person'); //true +v::phpLabel()->validate('foo'); //true +v::phpLabel()->validate('4ccess'); //false +``` + +*** +See also: + + * [Regex](Regex.md) + * [ResourceType](ResourceType.md) + * [Slug](Slug.md) + * [Charset](Charset.md) + \ No newline at end of file diff --git a/vendor/respect/validation/docs/rules/Positive.md b/vendor/respect/validation/docs/rules/Positive.md new file mode 100644 index 0000000000000000000000000000000000000000..ecf75d9f00fd536907b1e56462fda4f184920501 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Positive.md @@ -0,0 +1,14 @@ +# Positive + +- `v::positive()` + +Validates if a number is higher than zero + +```php +v::numeric()->positive()->validate(-15); // false +``` + +*** +See also: + + * [Negative](Negative.md) diff --git a/vendor/respect/validation/docs/rules/PostalCode.md b/vendor/respect/validation/docs/rules/PostalCode.md new file mode 100644 index 0000000000000000000000000000000000000000..c18ec96ede6a146bddb14f0c964cb95b278a4670 --- /dev/null +++ b/vendor/respect/validation/docs/rules/PostalCode.md @@ -0,0 +1,22 @@ +# PostalCode + +- `v::postalCode(string $countryCode)` + +Validates a postal code according to the given country code. + +```php +v::postalCode('BR')->validate('02179000'); // true +v::postalCode('BR')->validate('02179-000'); // true +v::postalCode('US')->validate('02179-000'); // false +v::postalCode('US')->validate('55372'); // true +v::postalCode('PL')->validate('99-300'); // true +``` + +Message template for this validator includes `{{countryCode}}`. + +Extracted from [GeoNames](http://www.geonames.org/). + +*** +See also: + + * [CountryCode](CountryCode.md) diff --git a/vendor/respect/validation/docs/rules/PrimeNumber.md b/vendor/respect/validation/docs/rules/PrimeNumber.md new file mode 100644 index 0000000000000000000000000000000000000000..dee58eabd4c93b89b4e351fd856d9608beeddfa6 --- /dev/null +++ b/vendor/respect/validation/docs/rules/PrimeNumber.md @@ -0,0 +1,16 @@ +# PrimeNumber + +- `v::primeNumber()` + +Validates a prime number + +```php +v::primeNumber()->validate(7); // true +``` + +*** +See also: + + * [Factor](Factor.md) + * [PerfectSquare](PerfectSquare.md) + * [PrimeNumber](PrimeNumber.md) diff --git a/vendor/respect/validation/docs/rules/Prnt.md b/vendor/respect/validation/docs/rules/Prnt.md new file mode 100644 index 0000000000000000000000000000000000000000..29dc6d76397b0d52e1cb0b8a269d4f4395952913 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Prnt.md @@ -0,0 +1,15 @@ +# Prnt + +- `v::prnt()` +- `v::prnt(string $additionalChars)` + +Similar to `v::graph` but accepts whitespace. + +```php +v::prnt()->validate('LMKA0$% _123'); // true +``` + +*** +See also: + + * [Graph](Graph.md) diff --git a/vendor/respect/validation/docs/rules/Punct.md b/vendor/respect/validation/docs/rules/Punct.md new file mode 100644 index 0000000000000000000000000000000000000000..d49411aa90978c85ffe136eb0afdf574dc985fd5 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Punct.md @@ -0,0 +1,17 @@ +# Punct + +- `v::punct()` +- `v::punct(string $additionalChars)` + +Accepts only punctuation characters: + +```php +v::punct()->validate('&,.;[]'); // true +``` + +*** +See also: + + * [Cntrl](Cntrl.md) + * [Graph](Graph.md) + * [Prnt](Prnt.md) diff --git a/vendor/respect/validation/docs/rules/Readable.md b/vendor/respect/validation/docs/rules/Readable.md new file mode 100644 index 0000000000000000000000000000000000000000..00a074eb9142aa4700965e2bf593d6b3cbd67e3d --- /dev/null +++ b/vendor/respect/validation/docs/rules/Readable.md @@ -0,0 +1,23 @@ +# Readable + +- `v::readable()` + +Validates if the given data is a file exists and is readable. + +```php +v::readable()->validate('/path/of/a/readable/file'); // true +``` + +*** +See also: + + * [Directory](Directory.md) + * [Executable](Executable.md) + * [Exists](Exists.md) + * [Extension](Extension.md) + * [File](File.md) + * [Mimetype](Mimetype.md) + * [Size](Size.md) + * [SymbolicLink](SymbolicLink.md) + * [Uploaded](Uploaded.md) + * [Writable](Writable.md) diff --git a/vendor/respect/validation/docs/rules/Regex.md b/vendor/respect/validation/docs/rules/Regex.md new file mode 100644 index 0000000000000000000000000000000000000000..ed0d2517345e6fcb37c9ad8e68a3d83d98b815ab --- /dev/null +++ b/vendor/respect/validation/docs/rules/Regex.md @@ -0,0 +1,21 @@ +# Regex + +- `v::regex(string $regex)` + +Evaluates a regex on the input and validates if matches + +```php +v::regex('/[a-z]/')->validate('a'); // true +``` + +Message template for this validator includes `{{regex}}` + +*** +See also: + + * [Alnum](Alnum.md) + * [Alpha](Alpha.md) + * [Contains](Contains.md) + * [Digit](Digit.md) + * [EndsWith](EndsWith.md) + * [StartsWith](StartsWith.md) diff --git a/vendor/respect/validation/docs/rules/ResourceType.md b/vendor/respect/validation/docs/rules/ResourceType.md new file mode 100644 index 0000000000000000000000000000000000000000..c21a2f1d89b7a85c966d8eefdd07e3abe4d4e565 --- /dev/null +++ b/vendor/respect/validation/docs/rules/ResourceType.md @@ -0,0 +1,21 @@ +# ResourceType + +- `v::resourceType()` + +Validates if the input is a resource. + +```php +v::resourceType()->validate(fopen('/path/to/file.txt', 'w')); // true +``` + +*** +See also: + + * [BoolType](BoolType.md) + * [CallableType](CallableType.md) + * [FloatType](FloatType.md) + * [IntType](IntType.md) + * [NullType](NullType.md) + * [ObjectType](ObjectType.md) + * [StringType](StringType.md) + * [Type](Type.md) diff --git a/vendor/respect/validation/docs/rules/Roman.md b/vendor/respect/validation/docs/rules/Roman.md new file mode 100644 index 0000000000000000000000000000000000000000..b619930e1bf61ec67b70c246aa1aaa23bbfafb00 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Roman.md @@ -0,0 +1,16 @@ +# Roman + +- `v::roman()` + +Validates roman numbers + +```php +v::roman()->validate('IV'); // true +``` + +*** +See also: + + * [In](In.md) + * [Regex](Regex.md) + * [Uppercase](Uppercase.md) diff --git a/vendor/respect/validation/docs/rules/ScalarVal.md b/vendor/respect/validation/docs/rules/ScalarVal.md new file mode 100644 index 0000000000000000000000000000000000000000..366657854d77bda4e2df7eac79e9787b4c392fc1 --- /dev/null +++ b/vendor/respect/validation/docs/rules/ScalarVal.md @@ -0,0 +1,15 @@ +# ScalarVal + +- `v::scalarVal()` + +Validates if the input is a scalar value. + +```php +v::scalarVal()->validate([]); // false +v::scalarVal()->validate(135.0); // true +``` + +*** +See also: + + * [Type](Type.md) diff --git a/vendor/respect/validation/docs/rules/Sf.md b/vendor/respect/validation/docs/rules/Sf.md new file mode 100644 index 0000000000000000000000000000000000000000..a7988a8b98d4027c45045556046a7d7169bc4a0b --- /dev/null +++ b/vendor/respect/validation/docs/rules/Sf.md @@ -0,0 +1,19 @@ +# Sf + +- `v::sf(string $validator)` + +Use Symfony2 validators inside Respect\Validation flow. Messages +are preserved. + +```php +v::sf('Time')->validate('15:00:00'); +``` + + +You must add `"symfony/validator": "~2.6"` to your `require` property on composer.json file. + + +*** +See also: + + * [Zend](Zend.md) diff --git a/vendor/respect/validation/docs/rules/Size.md b/vendor/respect/validation/docs/rules/Size.md new file mode 100644 index 0000000000000000000000000000000000000000..13f5aee4e96aec1c383ef7bed1c78a471aa33f6f --- /dev/null +++ b/vendor/respect/validation/docs/rules/Size.md @@ -0,0 +1,48 @@ +# Size + +- `v::size(string $minSize)` +- `v::size(string $minSize, string $maxSize)` +- `v::size(null, string $maxSize)` + +Validates file sizes: + +```php +v::size('1KB')->validate($filename); // Must have at least 1KB size +v::size('1MB', '2MB')->validate($filename); // Must have the size between 1MB and 2MB +v::size(null, '1GB')->validate($filename); // Must not be greater than 1GB +``` + +Sizes are not case-sensitive and the accepted values are: + +- B +- KB +- MB +- GB +- TB +- PB +- EB +- ZB +- YB + +This validator will consider `SplFileInfo` instances, like: + +```php +$fileInfo = new SplFileInfo($filename); +v::size('1.5mb')->validate($fileInfo); // Will return true or false +``` + +Message template for this validator includes `{{minSize}}` and `{{maxSize}}`. + +*** +See also: + + * [Directory](Directory.md) + * [Executable](Executable.md) + * [Exists](Exists.md) + * [Extension](Extension.md) + * [File](File.md) + * [Mimetype](Mimetype.md) + * [Readable](Readable.md) + * [SymbolicLink](SymbolicLink.md) + * [Uploaded](Uploaded.md) + * [Writable](Writable.md) diff --git a/vendor/respect/validation/docs/rules/Slug.md b/vendor/respect/validation/docs/rules/Slug.md new file mode 100644 index 0000000000000000000000000000000000000000..599bbbaac904fdef72ddcf7fc753511aa67fc8a7 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Slug.md @@ -0,0 +1,17 @@ +# Slug + +- `v::slug()` + +Validates slug-like strings: + +```php +v::slug()->validate('my-wordpress-title'); // true +v::slug()->validate('my-wordpress--title'); // false +v::slug()->validate('my-wordpress-title-'); // false +``` + +*** +See also: + + * [Url](Url.md) + * [VideoUrl](VideoUrl.md) diff --git a/vendor/respect/validation/docs/rules/Space.md b/vendor/respect/validation/docs/rules/Space.md new file mode 100644 index 0000000000000000000000000000000000000000..a0faec57133569ef6457237c0eacd2f9e6782db0 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Space.md @@ -0,0 +1,15 @@ +# Space + +- `v::space()` +- `v::space(string $additionalChars)` + +Accepts only whitespace: + +```php +v::space()->validate(' '); // true +``` + +*** +See also: + + * [Cntrl](Cntrl.md) diff --git a/vendor/respect/validation/docs/rules/StartsWith.md b/vendor/respect/validation/docs/rules/StartsWith.md new file mode 100644 index 0000000000000000000000000000000000000000..842655d94b25b1460254e12d1d4618032cf77d5c --- /dev/null +++ b/vendor/respect/validation/docs/rules/StartsWith.md @@ -0,0 +1,31 @@ +# StartsWith + +- `v::startsWith(mixed $value)` +- `v::startsWith(mixed $value, boolean $identical = false)` + +This validator is similar to `v::contains()`, but validates +only if the value is at the beginning of the input. + +For strings: + +```php +v::startsWith('lorem')->validate('lorem ipsum'); // true +``` + +For arrays: + +```php +v::startsWith('lorem')->validate(['lorem', 'ipsum']); // true +``` + +`true` may be passed as a parameter to indicate identical comparison +instead of equal. + +Message template for this validator includes `{{startValue}}`. + +*** +See also: + + * [EndsWith](EndsWith.md) + * [Contains](Contains.md) + * [In](In.md) diff --git a/vendor/respect/validation/docs/rules/StringType.md b/vendor/respect/validation/docs/rules/StringType.md new file mode 100644 index 0000000000000000000000000000000000000000..624c3df8cfbe16b0774d69203d9d5d32a5c12f03 --- /dev/null +++ b/vendor/respect/validation/docs/rules/StringType.md @@ -0,0 +1,22 @@ +# StringType + +- `v::stringType()` + +Validates a string. + +```php +v::stringType()->validate('hi'); // true +``` + +*** +See also: + + * [Alnum](Alnum.md) + * [BoolType](BoolType.md) + * [CallableType](CallableType.md) + * [FloatType](FloatType.md) + * [IntType](IntType.md) + * [NullType](NullType.md) + * [ObjectType](ObjectType.md) + * [ResourceType](ResourceType.md) + * [Type](Type.md) diff --git a/vendor/respect/validation/docs/rules/SubdivisionCode.md b/vendor/respect/validation/docs/rules/SubdivisionCode.md new file mode 100644 index 0000000000000000000000000000000000000000..3cb031922eff171dcac07b05827f9420049fa83c --- /dev/null +++ b/vendor/respect/validation/docs/rules/SubdivisionCode.md @@ -0,0 +1,284 @@ +# SubdivisionCode + +- `v::subdivisionCode(string $countryCode)` + +Validates subdivision country codes according to [ISO 3166-2][]. + +The `$countryCode` must be a country in [ISO 3166-1 alpha-2][] format. + +```php +v::subdivisionCode('BR')->validate('SP'); // true +v::subdivisionCode('US')->validate('CA'); // true +``` + +This rule is case sensitive. + +## Available country codes + +- `AD`: Andorra +- `AE`: United Arab Emirates +- `AF`: Afghanistan +- `AG`: Antigua and Barbuda +- `AI`: Anguilla +- `AL`: Albania +- `AM`: Armenia +- `AN`: AN.html +- `AO`: Angola +- `AQ`: Antarctica +- `AR`: Argentina +- `AS`: American Samoa +- `AT`: Austria +- `AU`: Australia +- `AW`: Aruba +- `AX`: Ã…land +- `AZ`: Azerbaijan +- `BA`: Bosnia and Herzegovina +- `BB`: Barbados +- `BD`: Bangladesh +- `BE`: Belgium +- `BF`: Burkina Faso +- `BG`: Bulgaria +- `BH`: Bahrain +- `BI`: Burundi +- `BJ`: Benin +- `BL`: Saint Barthélemy +- `BM`: Bermuda +- `BN`: Brunei +- `BO`: Bolivia +- `BQ`: Bonaire +- `BR`: Brazil +- `BS`: Bahamas +- `BT`: Bhutan +- `BV`: Bouvet Island +- `BW`: Botswana +- `BY`: Belarus +- `BZ`: Belize +- `CA`: Canada +- `CC`: Cocos [Keeling] Islands +- `CD`: Democratic Republic of the Congo +- `CF`: Central African Republic +- `CG`: Republic of the Congo +- `CH`: Switzerland +- `CI`: Ivory Coast +- `CK`: Cook Islands +- `CL`: Chile +- `CM`: Cameroon +- `CN`: China +- `CO`: Colombia +- `CR`: Costa Rica +- `CS`: CS.html +- `CU`: Cuba +- `CV`: Cape Verde +- `CW`: Curacao +- `CX`: Christmas Island +- `CY`: Cyprus +- `CZ`: Czech Republic +- `DE`: Germany +- `DJ`: Djibouti +- `DK`: Denmark +- `DM`: Dominica +- `DO`: Dominican Republic +- `DZ`: Algeria +- `EC`: Ecuador +- `EE`: Estonia +- `EG`: Egypt +- `EH`: Western Sahara +- `ER`: Eritrea +- `ES`: Spain +- `ET`: Ethiopia +- `FI`: Finland +- `FJ`: Fiji +- `FK`: Falkland Islands +- `FM`: Micronesia +- `FO`: Faroe Islands +- `FR`: France +- `GA`: Gabon +- `GB`: United Kingdom +- `GD`: Grenada +- `GE`: Georgia +- `GF`: French Guiana +- `GG`: Guernsey +- `GH`: Ghana +- `GI`: Gibraltar +- `GL`: Greenland +- `GM`: Gambia +- `GN`: Guinea +- `GP`: Guadeloupe +- `GQ`: Equatorial Guinea +- `GR`: Greece +- `GS`: South Georgia and the South Sandwich Islands +- `GT`: Guatemala +- `GU`: Guam +- `GW`: Guinea-Bissau +- `GY`: Guyana +- `HK`: Hong Kong +- `HM`: Heard Island and McDonald Islands +- `HN`: Honduras +- `HR`: Croatia +- `HT`: Haiti +- `HU`: Hungary +- `ID`: Indonesia +- `IE`: Ireland +- `IL`: Israel +- `IM`: Isle of Man +- `IN`: India +- `IO`: British Indian Ocean Territory +- `IQ`: Iraq +- `IR`: Iran +- `IS`: Iceland +- `IT`: Italy +- `JE`: Jersey +- `JM`: Jamaica +- `JO`: Jordan +- `JP`: Japan +- `KE`: Kenya +- `KG`: Kyrgyzstan +- `KH`: Cambodia +- `KI`: Kiribati +- `KM`: Comoros +- `KN`: Saint Kitts and Nevis +- `KP`: North Korea +- `KR`: South Korea +- `KW`: Kuwait +- `KY`: Cayman Islands +- `KZ`: Kazakhstan +- `LA`: Laos +- `LB`: Lebanon +- `LC`: Saint Lucia +- `LI`: Liechtenstein +- `LK`: Sri Lanka +- `LR`: Liberia +- `LS`: Lesotho +- `LT`: Lithuania +- `LU`: Luxembourg +- `LV`: Latvia +- `LY`: Libya +- `MA`: Morocco +- `MC`: Monaco +- `MD`: Moldova +- `ME`: Montenegro +- `MF`: Saint Martin +- `MG`: Madagascar +- `MH`: Marshall Islands +- `MK`: Macedonia +- `ML`: Mali +- `MM`: Myanmar [Burma] +- `MN`: Mongolia +- `MO`: Macao +- `MP`: Northern Mariana Islands +- `MQ`: Martinique +- `MR`: Mauritania +- `MS`: Montserrat +- `MT`: Malta +- `MU`: Mauritius +- `MV`: Maldives +- `MW`: Malawi +- `MX`: Mexico +- `MY`: Malaysia +- `MZ`: Mozambique +- `NA`: Namibia +- `NC`: New Caledonia +- `NE`: Niger +- `NF`: Norfolk Island +- `NG`: Nigeria +- `NI`: Nicaragua +- `NL`: Netherlands +- `NO`: Norway +- `NP`: Nepal +- `NR`: Nauru +- `NU`: Niue +- `NZ`: New Zealand +- `OM`: Oman +- `PA`: Panama +- `PE`: Peru +- `PF`: French Polynesia +- `PG`: Papua New Guinea +- `PH`: Philippines +- `PK`: Pakistan +- `PL`: Poland +- `PM`: Saint Pierre and Miquelon +- `PN`: Pitcairn Islands +- `PR`: Puerto Rico +- `PS`: Palestine +- `PT`: Portugal +- `PW`: Palau +- `PY`: Paraguay +- `QA`: Qatar +- `RE`: Réunion +- `RO`: Romania +- `RS`: Serbia +- `RU`: Russia +- `RW`: Rwanda +- `SA`: Saudi Arabia +- `SB`: Solomon Islands +- `SC`: Seychelles +- `SD`: Sudan +- `SE`: Sweden +- `SG`: Singapore +- `SH`: Saint Helena +- `SI`: Slovenia +- `SJ`: Svalbard and Jan Mayen +- `SK`: Slovakia +- `SL`: Sierra Leone +- `SM`: San Marino +- `SN`: Senegal +- `SO`: Somalia +- `SR`: Suriname +- `SS`: South Sudan +- `ST`: São Tomé and PrÃncipe +- `SV`: El Salvador +- `SX`: Sint Maarten +- `SY`: Syria +- `SZ`: Swaziland +- `TC`: Turks and Caicos Islands +- `TD`: Chad +- `TF`: French Southern Territories +- `TG`: Togo +- `TH`: Thailand +- `TJ`: Tajikistan +- `TK`: Tokelau +- `TL`: East Timor +- `TM`: Turkmenistan +- `TN`: Tunisia +- `TO`: Tonga +- `TR`: Turkey +- `TT`: Trinidad and Tobago +- `TV`: Tuvalu +- `TW`: Taiwan +- `TZ`: Tanzania +- `UA`: Ukraine +- `UG`: Uganda +- `UM`: U.S. Minor Outlying Islands +- `US`: United States +- `UY`: Uruguay +- `UZ`: Uzbekistan +- `VA`: Vatican City +- `VC`: Saint Vincent and the Grenadines +- `VE`: Venezuela +- `VG`: British Virgin Islands +- `VI`: U.S. Virgin Islands +- `VN`: Vietnam +- `VU`: Vanuatu +- `WF`: Wallis and Futuna +- `WS`: Samoa +- `XK`: Kosovo +- `YE`: Yemen +- `YT`: Mayotte +- `ZA`: South Africa +- `ZM`: Zambia +- `ZW`: Zimbabwe + +All data was extrated from [GeoNames][] which is licensed under a +[Creative Commons Attribution 3.0 License][]. + +*** +See also: + + * [CountryCode](CountryCode.md) + * [Tld](Tld.md) + + +[Creative Commons Attribution 3.0 License]: http://creativecommons.org/licenses/by/3.0 "Creative Commons Attribution 3.0 License" +[GeoNames]: http://www.geonames.org "GetNames" +[ISO 3166-1 alpha-2]: http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 "ISO 3166-1 alpha-2" +[ISO 3166-2]: http://en.wikipedia.org/wiki/ISO_3166-2 "ISO 3166-2" diff --git a/vendor/respect/validation/docs/rules/SymbolicLink.md b/vendor/respect/validation/docs/rules/SymbolicLink.md new file mode 100644 index 0000000000000000000000000000000000000000..bc9019657bc68072e439020da43c0169169eab43 --- /dev/null +++ b/vendor/respect/validation/docs/rules/SymbolicLink.md @@ -0,0 +1,23 @@ +# SymbolicLink + +- `v::symbolicLink()` + +Validates if the given data is a path of a valid symbolic link. + +```php +v::symbolicLink()->validate('/path/of/valid/symbolic/link'); // true +``` + +*** +See also: + + * [Directory](Directory.md) + * [Executable](Executable.md) + * [Exists](Exists.md) + * [Extension](Extension.md) + * [File](File.md) + * [Mimetype](Mimetype.md) + * [Readable](Readable.md) + * [Size](Size.md) + * [Uploaded](Uploaded.md) + * [Writable](Writable.md) diff --git a/vendor/respect/validation/docs/rules/Tld.md b/vendor/respect/validation/docs/rules/Tld.md new file mode 100644 index 0000000000000000000000000000000000000000..db05452a196958e19b794707740c69487c99d5a2 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Tld.md @@ -0,0 +1,17 @@ +# Tld + +- `v::tld()` + +Validates a top-level domain + +```php +v::tld()->validate('com'); // true +v::tld()->validate('ly'); // true +v::tld()->validate('org'); // true +``` + +*** +See also: + + * [Domain](Domain.md) + * [CountryCode](CountryCode.md) diff --git a/vendor/respect/validation/docs/rules/TrueVal.md b/vendor/respect/validation/docs/rules/TrueVal.md new file mode 100644 index 0000000000000000000000000000000000000000..59869d200419e5db273de2f4fa7c6bb30847dbd7 --- /dev/null +++ b/vendor/respect/validation/docs/rules/TrueVal.md @@ -0,0 +1,21 @@ +# TrueVal + +- `v::trueVal()` + +Validates if a value is considered as `true`. + +```php +v::trueVal()->validate(true); // true +v::trueVal()->validate(1); // true +v::trueVal()->validate('1'); // true +v::trueVal()->validate('true'); // true +v::trueVal()->validate('on'); // true +v::trueVal()->validate('yes'); // true +v::trueVal()->validate('0.5'); // false +v::trueVal()->validate('2'); // false +``` + +*** +See also: + + * [FalseVal](FalseVal.md) diff --git a/vendor/respect/validation/docs/rules/Type.md b/vendor/respect/validation/docs/rules/Type.md new file mode 100644 index 0000000000000000000000000000000000000000..50f2abb9f9a75a2e1fa087a69b38274ad45d8631 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Type.md @@ -0,0 +1,31 @@ +# Type + +- `v::type(string $type)` + +Validates the type of input. + +```php +v::type('bool')->validate(true); // true +v::type('callable')->validate(function (){}); // true +v::type('object')->validate(new stdClass()); // true +``` + +*** +See also: + + * [ArrayVal](ArrayVal.md) + * [BoolType](BoolType.md) + * [CallableType](CallableType.md) + * [Finite](Finite.md) + * [FloatType](FloatType.md) + * [FloatVal](FloatVal.md) + * [Infinite](Infinite.md) + * [Instance](Instance.md) + * [IntType](IntType.md) + * [IntVal](IntVal.md) + * [NullType](NullType.md) + * [ObjectType](ObjectType.md) + * [ResourceType](ResourceType.md) + * [ScalarVal](ScalarVal.md) + * [StringType](StringType.md) + * [Type](Type.md) diff --git a/vendor/respect/validation/docs/rules/Uploaded.md b/vendor/respect/validation/docs/rules/Uploaded.md new file mode 100644 index 0000000000000000000000000000000000000000..774f9bb8216835034c4fa9c02263dfe2c9f898f5 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Uploaded.md @@ -0,0 +1,23 @@ +# Uploaded + +- `v::uploaded()` + +Validates if the given data is a file that was uploaded via HTTP POST. + +```php +v::uploaded()->validate('/path/of/an/uploaded/file'); // true +``` + +*** +See also: + + * [Directory](Directory.md) + * [Executable](Executable.md) + * [Exists](Exists.md) + * [Extension](Extension.md) + * [File](File.md) + * [Mimetype](Mimetype.md) + * [Readable](Readable.md) + * [Size](Size.md) + * [SymbolicLink](SymbolicLink.md) + * [Writable](Writable.md) diff --git a/vendor/respect/validation/docs/rules/Uppercase.md b/vendor/respect/validation/docs/rules/Uppercase.md new file mode 100644 index 0000000000000000000000000000000000000000..1dff7acf584a5ee43724526f6ff729879521ef2e --- /dev/null +++ b/vendor/respect/validation/docs/rules/Uppercase.md @@ -0,0 +1,14 @@ +# Uppercase + +- `v::uppercase()` + +Validates if string characters are uppercase in the input: + +```php +v::stringType()->uppercase()->validate('W3C'); // true +``` + +*** +See also: + + * [Lowercase](Lowercase.md) diff --git a/vendor/respect/validation/docs/rules/Url.md b/vendor/respect/validation/docs/rules/Url.md new file mode 100644 index 0000000000000000000000000000000000000000..5638cf55f4b364edceea324d80904c3f87ce3178 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Url.md @@ -0,0 +1,24 @@ +# Url + +- `v::url()` + +Validates if input is an URL: + +```php +v::url()->validate('http://example.com'); // true +v::url()->validate('https://www.youtube.com/watch?v=6FOUqQt3Kg0'); // true +v::url()->validate('ldap://[::1]'); // true +v::url()->validate('mailto:john.doe@example.com'); // true +v::url()->validate('news:new.example.com'); // true +``` + +This rule uses [FilterVar](FilterVar.md) + +*** +See also: + + * [Domain](Domain.md) + * [Email](Email.md) + * [FilterVar](FilterVar.md) + * [Phone](Phone.md) + * [VideoUrl](VideoUrl.md) diff --git a/vendor/respect/validation/docs/rules/Version.md b/vendor/respect/validation/docs/rules/Version.md new file mode 100644 index 0000000000000000000000000000000000000000..aad3ce8a3d02bc333d3bff0c11a9b359a67c66c7 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Version.md @@ -0,0 +1,16 @@ +# Version + +- `v::version()` + +Validates version numbers using Semantic Versioning. + +```php +v::version()->validate('1.0.0'); +``` + +*** +See also: + + * [Equals](Equals.md) + * [Regex](Regex.md) + * [Roman](Roman.md) diff --git a/vendor/respect/validation/docs/rules/VideoUrl.md b/vendor/respect/validation/docs/rules/VideoUrl.md new file mode 100644 index 0000000000000000000000000000000000000000..1ef962793bdc6082f57ad70d42f059a06095ca5a --- /dev/null +++ b/vendor/respect/validation/docs/rules/VideoUrl.md @@ -0,0 +1,35 @@ +# VideoUrl + +- `v::videoUrl()` +- `v::videoUrl(string $service)` + +Validates if the input is a video URL value: + +```php +v::videoUrl()->validate('https://player.vimeo.com/video/71787467'); // true +v::videoUrl()->validate('https://vimeo.com/71787467'); // true +v::videoUrl()->validate('https://www.youtube.com/embed/netHLn9TScY'); // true +v::videoUrl()->validate('https://www.youtube.com/watch?v=netHLn9TScY'); // true +v::videoUrl()->validate('https://youtu.be/netHLn9TScY'); // true + +v::videoUrl('youtube')->validate('https://www.youtube.com/watch?v=netHLn9TScY'); // true +v::videoUrl('vimeo')->validate('https://vimeo.com/71787467'); // true + +v::videoUrl()->validate('https://youtube.com'); // false +v::videoUrl('youtube')->validate('https://vimeo.com/71787467'); // false +``` + +The services accepted are: + +- YouTube +- Vimeo + +The `$service` value is not case-sensitive. + +Message template for this validator includes `{{service}}`. + + +*** +See also: + + * [Url](Url.md) diff --git a/vendor/respect/validation/docs/rules/Vowel.md b/vendor/respect/validation/docs/rules/Vowel.md new file mode 100644 index 0000000000000000000000000000000000000000..98d806f5d90b39658d61d9e69dec3d86b5330e2f --- /dev/null +++ b/vendor/respect/validation/docs/rules/Vowel.md @@ -0,0 +1,17 @@ +# Vowel + +- `v::vowel()` + +Similar to `v::alnum()`. Validates strings that contains only vowels: + +```php +v::vowel()->validate('aei'); // true +``` + +*** +See also: + + * [Alnum](Alnum.md) + * [Digit](Digit.md) + * [Alpha](Alpha.md) + * [Consonant](Consonant.md) diff --git a/vendor/respect/validation/docs/rules/When.md b/vendor/respect/validation/docs/rules/When.md new file mode 100644 index 0000000000000000000000000000000000000000..6254cb34d991733bd29c9b2281bad838f362a24e --- /dev/null +++ b/vendor/respect/validation/docs/rules/When.md @@ -0,0 +1,24 @@ +# When + +- `v::when(v $if, v $then, v $else)` +- `v::when(v $if, v $then)` + +A ternary validator that accepts three parameters. + +When the `$if` validates, returns validation for `$then`. +When the `$if` doesn't validate, returns validation for `$else`, if defined. + +```php +v::when(v::intVal(), v::positive(), v::notEmpty())->validate($input); +``` + +In the sample above, if `$input` is an integer, then it must be positive. +If `$input` is not an integer, then it must not me empty. +When `$else` is not defined use [AlwaysInvalid](AlwaysInvalid.md) + +*** +See also: + + * [AllOf](AllOf.md) + * [OneOf](OneOf.md) + * [NoneOf](NoneOf.md) diff --git a/vendor/respect/validation/docs/rules/Writable.md b/vendor/respect/validation/docs/rules/Writable.md new file mode 100644 index 0000000000000000000000000000000000000000..b7aa5e436534c6fee4bdf42b5fdafefc7494b08f --- /dev/null +++ b/vendor/respect/validation/docs/rules/Writable.md @@ -0,0 +1,23 @@ +# Writable + +- `v::writable()` + +Validates if the given input is writable file. + +```php +v::writable()->validate('/path/of/a/writable/file'); // true +``` + +*** +See also: + + * [Directory](Directory.md) + * [Executable](Executable.md) + * [Exists](Exists.md) + * [Extension](Extension.md) + * [File](File.md) + * [Mimetype](Mimetype.md) + * [Readable](Readable.md) + * [Size](Size.md) + * [SymbolicLink](SymbolicLink.md) + * [Uploaded](Uploaded.md) diff --git a/vendor/respect/validation/docs/rules/Xdigit.md b/vendor/respect/validation/docs/rules/Xdigit.md new file mode 100644 index 0000000000000000000000000000000000000000..9e79d0fdfc6b52ac263f8748ce5dc03c778c9c81 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Xdigit.md @@ -0,0 +1,22 @@ +# Xdigit + +- `v::xdigit()` + +Accepts an hexadecimal number: + +```php +v::xdigit()->validate('abc123'); // true +``` + +Notice, however, that it doesn't accept strings starting with 0x: + +```php +v::xdigit()->validate('0x1f'); // false +``` + +*** +See also: + + * [Digit](Digit.md) + * [Alnum](Alnum.md) + * [HexRgbColor](HexRgbColor.md) diff --git a/vendor/respect/validation/docs/rules/Yes.md b/vendor/respect/validation/docs/rules/Yes.md new file mode 100644 index 0000000000000000000000000000000000000000..9fef6d8f4d6b0e02e6b9dab619c39451b9f83db6 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Yes.md @@ -0,0 +1,23 @@ +# Yes + +- `v::yes()` +- `v::yes(boolean $locale)` + +Validates if value is considered as "Yes". + +```php +v::yes()->validate('Y'); // true +v::yes()->validate('Yea'); // true +v::yes()->validate('Yeah'); // true +v::yes()->validate('Yep'); // true +v::yes()->validate('Yes'); // true +``` + +This rule is case insensitive. + +If `$locale` is TRUE, uses the value of [nl_langinfo()](http://php.net/nl_langinfo) with `YESEXPR` constant. + +*** +See also: + + * [No](No.md) diff --git a/vendor/respect/validation/docs/rules/Zend.md b/vendor/respect/validation/docs/rules/Zend.md new file mode 100644 index 0000000000000000000000000000000000000000..8ec0ae8ed7ff8daf197e3ef1b5e42ed594ca2b94 --- /dev/null +++ b/vendor/respect/validation/docs/rules/Zend.md @@ -0,0 +1,17 @@ +# Zend + +- `v::zend(mixed $validator)` + +Use Zend validators inside Respect\Validation flow. Messages +are preserved. + +```php +v::zend('Hostname')->validate('google.com'); +``` + +You must add `"zendframework/zend-validator": "~2.3"` to your `require` property on composer.json file. + +*** +See also: + + * [Sf](Sf.md) diff --git a/vendor/setasign/fpdi/src/FpdfTplTrait.php b/vendor/setasign/fpdi/src/FpdfTplTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..11796b1f5ccff76673892c4f65a7aea085d91e50 --- /dev/null +++ b/vendor/setasign/fpdi/src/FpdfTplTrait.php @@ -0,0 +1,466 @@ +<?php +/** + * This file is part of FPDI + * + * @package setasign\Fpdi + * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com) + * @license http://opensource.org/licenses/mit-license The MIT License + */ + +namespace setasign\Fpdi; + +/** + * Trait FpdfTplTrait + * + * This class adds a templating feature to tFPDF. + * + * @package setasign\Fpdi + */ +trait FpdfTplTrait +{ + /** + * Data of all created templates. + * + * @var array + */ + protected $templates = []; + + /** + * The template id for the currently created template. + * + * @var null|int + */ + protected $currentTemplateId; + + /** + * A counter for template ids. + * + * @var int + */ + protected $templateId = 0; + + /** + * Set the page format of the current page. + * + * @param array $size An array with two values defining the size. + * @param string $orientation "L" for landscape, "P" for portrait. + * @throws \BadMethodCallException + */ + public function setPageFormat($size, $orientation) + { + if ($this->currentTemplateId !== null) { + throw new \BadMethodCallException('The page format cannot be changed when writing to a template.'); + } + + if (!\in_array($orientation, ['P', 'L'], true)) { + throw new \InvalidArgumentException(\sprintf( + 'Invalid page orientation "%s"! Only "P" and "L" are allowed!', + $orientation + )); + } + + $size = $this->_getpagesize($size); + + if ($orientation != $this->CurOrientation + || $size[0] != $this->CurPageSize[0] + || $size[1] != $this->CurPageSize[1] + ) { + // New size or orientation + if ($orientation === 'P') { + $this->w = $size[0]; + $this->h = $size[1]; + } else { + $this->w = $size[1]; + $this->h = $size[0]; + } + $this->wPt = $this->w * $this->k; + $this->hPt = $this->h * $this->k; + $this->PageBreakTrigger = $this->h - $this->bMargin; + $this->CurOrientation = $orientation; + $this->CurPageSize = $size; + + $this->PageInfo[$this->page]['size'] = array($this->wPt, $this->hPt); + } + } + + /** + * Draws a template onto the page or another template. + * + * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect + * ratio. + * + * @param mixed $tpl The template id + * @param array|float|int $x The abscissa of upper-left corner. Alternatively you could use an assoc array + * with the keys "x", "y", "width", "height", "adjustPageSize". + * @param float|int $y The ordinate of upper-left corner. + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @param bool $adjustPageSize + * @return array The size + * @see FpdfTplTrait::getTemplateSize() + */ + public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false) + { + if (!isset($this->templates[$tpl])) { + throw new \InvalidArgumentException('Template does not exist!'); + } + + if (\is_array($x)) { + unset($x['tpl']); + \extract($x, EXTR_IF_EXISTS); + /** @noinspection NotOptimalIfConditionsInspection */ + /** @noinspection CallableParameterUseCaseInTypeContextInspection */ + if (\is_array($x)) { + $x = 0; + } + } + + $template = $this->templates[$tpl]; + + $originalSize = $this->getTemplateSize($tpl); + $newSize = $this->getTemplateSize($tpl, $width, $height); + if ($adjustPageSize) { + $this->setPageFormat($newSize, $newSize['orientation']); + } + + $this->_out( + // reset standard values, translate and scale + \sprintf( + 'q 0 J 1 w 0 j 0 G 0 g %.4F 0 0 %.4F %.4F %.4F cm /%s Do Q', + ($newSize['width'] / $originalSize['width']), + ($newSize['height'] / $originalSize['height']), + $x * $this->k, + ($this->h - $y - $newSize['height']) * $this->k, + $template['id'] + ) + ); + + return $newSize; + } + + /** + * Get the size of a template. + * + * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect + * ratio. + * + * @param mixed $tpl The template id + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P) + */ + public function getTemplateSize($tpl, $width = null, $height = null) + { + if (!isset($this->templates[$tpl])) { + return false; + } + + if ($width === null && $height === null) { + $width = $this->templates[$tpl]['width']; + $height = $this->templates[$tpl]['height']; + } elseif ($width === null) { + $width = $height * $this->templates[$tpl]['width'] / $this->templates[$tpl]['height']; + } + + if ($height === null) { + $height = $width * $this->templates[$tpl]['height'] / $this->templates[$tpl]['width']; + } + + if ($height <= 0. || $width <= 0.) { + throw new \InvalidArgumentException('Width or height parameter needs to be larger than zero.'); + } + + return [ + 'width' => $width, + 'height' => $height, + 0 => $width, + 1 => $height, + 'orientation' => $width > $height ? 'L' : 'P' + ]; + } + + /** + * Begins a new template. + * + * @param float|int|null $width The width of the template. If null, the current page width is used. + * @param float|int|null $height The height of the template. If null, the current page height is used. + * @param bool $groupXObject Define the form XObject as a group XObject to support transparency (if used). + * @return int A template identifier. + */ + public function beginTemplate($width = null, $height = null, $groupXObject = false) + { + if ($width === null) { + $width = $this->w; + } + + if ($height === null) { + $height = $this->h; + } + + $templateId = $this->getNextTemplateId(); + + // initiate buffer with current state of FPDF + $buffer = "2 J\n" + . \sprintf('%.2F w', $this->LineWidth * $this->k) . "\n"; + + if ($this->FontFamily) { + $buffer .= \sprintf("BT /F%d %.2F Tf ET\n", $this->CurrentFont['i'], $this->FontSizePt); + } + + if ($this->DrawColor !== '0 G') { + $buffer .= $this->DrawColor . "\n"; + } + if ($this->FillColor !== '0 g') { + $buffer .= $this->FillColor . "\n"; + } + + if ($groupXObject && \version_compare('1.4', $this->PDFVersion, '>')) { + $this->PDFVersion = '1.4'; + } + + $this->templates[$templateId] = [ + 'objectNumber' => null, + 'id' => 'TPL' . $templateId, + 'buffer' => $buffer, + 'width' => $width, + 'height' => $height, + 'groupXObject' => $groupXObject, + 'state' => [ + 'x' => $this->x, + 'y' => $this->y, + 'AutoPageBreak' => $this->AutoPageBreak, + 'bMargin' => $this->bMargin, + 'tMargin' => $this->tMargin, + 'lMargin' => $this->lMargin, + 'rMargin' => $this->rMargin, + 'h' => $this->h, + 'w' => $this->w, + 'FontFamily' => $this->FontFamily, + 'FontStyle' => $this->FontStyle, + 'FontSizePt' => $this->FontSizePt, + 'FontSize' => $this->FontSize, + 'underline' => $this->underline, + 'TextColor' => $this->TextColor, + 'DrawColor' => $this->DrawColor, + 'FillColor' => $this->FillColor, + 'ColorFlag' => $this->ColorFlag + ] + ]; + + $this->SetAutoPageBreak(false); + $this->currentTemplateId = $templateId; + + $this->h = $height; + $this->w = $width; + + $this->SetXY($this->lMargin, $this->tMargin); + $this->SetRightMargin($this->w - $width + $this->rMargin); + + return $templateId; + } + + /** + * Ends a template. + * + * @return bool|int|null A template identifier. + */ + public function endTemplate() + { + if (null === $this->currentTemplateId) { + return false; + } + + $templateId = $this->currentTemplateId; + $template = $this->templates[$templateId]; + + $state = $template['state']; + $this->SetXY($state['x'], $state['y']); + $this->tMargin = $state['tMargin']; + $this->lMargin = $state['lMargin']; + $this->rMargin = $state['rMargin']; + $this->h = $state['h']; + $this->w = $state['w']; + $this->SetAutoPageBreak($state['AutoPageBreak'], $state['bMargin']); + + $this->FontFamily = $state['FontFamily']; + $this->FontStyle = $state['FontStyle']; + $this->FontSizePt = $state['FontSizePt']; + $this->FontSize = $state['FontSize']; + + $this->TextColor = $state['TextColor']; + $this->DrawColor = $state['DrawColor']; + $this->FillColor = $state['FillColor']; + $this->ColorFlag = $state['ColorFlag']; + + $this->underline = $state['underline']; + + $fontKey = $this->FontFamily . $this->FontStyle; + if ($fontKey) { + $this->CurrentFont =& $this->fonts[$fontKey]; + } else { + unset($this->CurrentFont); + } + + $this->currentTemplateId = null; + + return $templateId; + } + + /** + * Get the next template id. + * + * @return int + */ + protected function getNextTemplateId() + { + return $this->templateId++; + } + + /* overwritten FPDF methods: */ + + /** + * @inheritdoc + */ + public function AddPage($orientation = '', $size = '', $rotation = 0) + { + if ($this->currentTemplateId !== null) { + throw new \BadMethodCallException('Pages cannot be added when writing to a template.'); + } + parent::AddPage($orientation, $size, $rotation); + } + + /** + * @inheritdoc + */ + public function Link($x, $y, $w, $h, $link) + { + if ($this->currentTemplateId !== null) { + throw new \BadMethodCallException('Links cannot be set when writing to a template.'); + } + parent::Link($x, $y, $w, $h, $link); + } + + /** + * @inheritdoc + */ + public function SetLink($link, $y = 0, $page = -1) + { + if ($this->currentTemplateId !== null) { + throw new \BadMethodCallException('Links cannot be set when writing to a template.'); + } + return parent::SetLink($link, $y, $page); + } + + /** + * @inheritdoc + */ + public function SetDrawColor($r, $g = null, $b = null) + { + parent::SetDrawColor($r, $g, $b); + if ($this->page === 0 && $this->currentTemplateId !== null) { + $this->_out($this->DrawColor); + } + } + + /** + * @inheritdoc + */ + public function SetFillColor($r, $g = null, $b = null) + { + parent::SetFillColor($r, $g, $b); + if ($this->page === 0 && $this->currentTemplateId !== null) { + $this->_out($this->FillColor); + } + } + + /** + * @inheritdoc + */ + public function SetLineWidth($width) + { + parent::SetLineWidth($width); + if ($this->page === 0 && $this->currentTemplateId !== null) { + $this->_out(\sprintf('%.2F w', $width * $this->k)); + } + } + + /** + * @inheritdoc + */ + public function SetFont($family, $style = '', $size = 0) + { + parent::SetFont($family, $style, $size); + if ($this->page === 0 && $this->currentTemplateId !== null) { + $this->_out(\sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt)); + } + } + + /** + * @inheritdoc + */ + public function SetFontSize($size) + { + parent::SetFontSize($size); + if ($this->page === 0 && $this->currentTemplateId !== null) { + $this->_out(sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt)); + } + } + + /** + * @inheritdoc + */ + protected function _putimages() + { + parent::_putimages(); + + foreach ($this->templates as $key => $template) { + $this->_newobj(); + $this->templates[$key]['objectNumber'] = $this->n; + + $this->_put('<</Type /XObject /Subtype /Form /FormType 1'); + $this->_put(\sprintf('/BBox[0 0 %.2F %.2F]', $template['width'] * $this->k, $template['height'] * $this->k)); + $this->_put('/Resources 2 0 R'); // default resources dictionary of FPDF + + if ($this->compress) { + $buffer = \gzcompress($template['buffer']); + $this->_put('/Filter/FlateDecode'); + } else { + $buffer = $template['buffer']; + } + + $this->_put('/Length ' . \strlen($buffer)); + + if ($template['groupXObject']) { + $this->_put('/Group <</Type/Group/S/Transparency>>'); + } + + $this->_put('>>'); + $this->_putstream($buffer); + $this->_put('endobj'); + } + } + + /** + * @inheritdoc + */ + protected function _putxobjectdict() + { + foreach ($this->templates as $key => $template) { + $this->_put('/' . $template['id'] . ' ' . $template['objectNumber'] . ' 0 R'); + } + + parent::_putxobjectdict(); + } + + /** + * @inheritdoc + */ + public function _out($s) + { + if ($this->currentTemplateId !== null) { + $this->templates[$this->currentTemplateId]['buffer'] .= $s . "\n"; + } else { + parent::_out($s); + } + } +} \ No newline at end of file diff --git a/vendor/setasign/fpdi/src/Tcpdf/Fpdi.php b/vendor/setasign/fpdi/src/Tcpdf/Fpdi.php new file mode 100644 index 0000000000000000000000000000000000000000..27e209b3080265853f24cf0161c001fb20bafe0a --- /dev/null +++ b/vendor/setasign/fpdi/src/Tcpdf/Fpdi.php @@ -0,0 +1,260 @@ +<?php + +namespace setasign\Fpdi\Tcpdf; + +use setasign\Fpdi\FpdiTrait; +use setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException; +use setasign\Fpdi\PdfParser\Filter\AsciiHex; +use setasign\Fpdi\PdfParser\PdfParserException; +use setasign\Fpdi\PdfParser\Type\PdfHexString; +use setasign\Fpdi\PdfParser\Type\PdfIndirectObject; +use setasign\Fpdi\PdfParser\Type\PdfNull; +use setasign\Fpdi\PdfParser\Type\PdfNumeric; +use setasign\Fpdi\PdfParser\Type\PdfStream; +use setasign\Fpdi\PdfParser\Type\PdfString; +use setasign\Fpdi\PdfParser\Type\PdfType; +use setasign\Fpdi\PdfParser\Type\PdfTypeException; + +/** + * Class Fpdi + * + * This class let you import pages of existing PDF documents into a reusable structure for TCPDF. + * + * @package setasign\Fpdi + */ +class Fpdi extends \TCPDF +{ + use FpdiTrait { + writePdfType as fpdiWritePdfType; + useImportedPage as fpdiUseImportedPage; + } + + /** + * FPDI version + * + * @string + */ + const VERSION = '2.1.0'; + + /** + * A counter for template ids. + * + * @var int + */ + protected $templateId = 0; + + /** + * The currently used object number. + * + * @var int + */ + protected $currentObjectNumber; + + /** + * Get the next template id. + * + * @return int + */ + protected function getNextTemplateId() + { + return $this->templateId++; + } + + /** + * Draws an imported page onto the page or another template. + * + * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect + * ratio. + * + * @param mixed $tpl The template id + * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array + * with the keys "x", "y", "width", "height", "adjustPageSize". + * @param float|int $y The ordinate of upper-left corner. + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @param bool $adjustPageSize + * @return array The size + * @see FpdiTrait::getTemplateSize() + */ + public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false) + { + return $this->useImportedPage($tpl, $x, $y, $width, $height, $adjustPageSize); + } + + /** + * Draws an imported page onto the page. + * + * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect + * ratio. + * + * @param mixed $pageId The page id + * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array + * with the keys "x", "y", "width", "height", "adjustPageSize". + * @param float|int $y The ordinate of upper-left corner. + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @param bool $adjustPageSize + * @return array The size. + * @see Fpdi::getTemplateSize() + */ + public function useImportedPage($pageId, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false) + { + $size = $this->fpdiUseImportedPage($pageId, $x, $y, $width, $height, $adjustPageSize); + if ($this->inxobj) { + $importedPage = $this->importedPages[$pageId]; + $this->xobjects[$this->xobjid]['importedPages'][$importedPage['id']] = $pageId; + } + + return $size; + } + + /** + * Get the size of an imported page. + * + * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect + * ratio. + * + * @param mixed $tpl The template id + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P) + */ + public function getTemplateSize($tpl, $width = null, $height = null) + { + return $this->getImportedPageSize($tpl, $width, $height); + } + + /** + * @inheritdoc + */ + protected function _getxobjectdict() + { + $out = parent::_getxobjectdict(); + + foreach ($this->importedPages as $key => $pageData) { + $out .= '/' . $pageData['id'] . ' ' . $pageData['objectNumber'] . ' 0 R '; + } + + return $out; + } + + /** + * @inheritdoc + * @throws CrossReferenceException + * @throws PdfParserException + */ + protected function _putxobjects() + { + foreach ($this->importedPages as $key => $pageData) { + $this->currentObjectNumber = $this->_newobj(); + $this->importedPages[$key]['objectNumber'] = $this->currentObjectNumber; + $this->currentReaderId = $pageData['readerId']; + $this->writePdfType($pageData['stream']); + $this->_put('endobj'); + } + + foreach (\array_keys($this->readers) as $readerId) { + $parser = $this->getPdfReader($readerId)->getParser(); + $this->currentReaderId = $readerId; + + while (($objectNumber = \array_pop($this->objectsToCopy[$readerId])) !== null) { + try { + $object = $parser->getIndirectObject($objectNumber); + + } catch (CrossReferenceException $e) { + if ($e->getCode() === CrossReferenceException::OBJECT_NOT_FOUND) { + $object = PdfIndirectObject::create($objectNumber, 0, new PdfNull()); + } else { + throw $e; + } + } + + $this->writePdfType($object); + } + } + + // let's prepare resources for imported pages in templates + foreach ($this->xobjects as $xObjectId => $data) { + if (!isset($data['importedPages'])) { + continue; + } + + foreach ($data['importedPages'] as $id => $pageKey) { + $page = $this->importedPages[$pageKey]; + $this->xobjects[$xObjectId]['xobjects'][$id] = ['n' => $page['objectNumber']]; + } + } + + + parent::_putxobjects(); + $this->currentObjectNumber = null; + } + + /** + * Append content to the buffer of TCPDF. + * + * @param string $s + * @param bool $newLine + */ + protected function _put($s, $newLine = true) + { + if ($newLine) { + $this->setBuffer($s . "\n"); + } else { + $this->setBuffer($s); + } + } + + /** + * Begin a new object and return the object number. + * + * @param int|string $objid Object ID (leave empty to get a new ID). + * @return int object number + */ + protected function _newobj($objid = '') + { + $this->_out($this->_getobj($objid)); + return $this->n; + } + + /** + * Writes a PdfType object to the resulting buffer. + * + * @param PdfType $value + * @throws PdfTypeException + */ + protected function writePdfType(PdfType $value) + { + if (!$this->encrypted) { + $this->fpdiWritePdfType($value); + return; + } + + if ($value instanceof PdfString) { + $string = PdfString::unescape($value->value); + $string = $this->_encrypt_data($this->currentObjectNumber, $string); + $value->value = \TCPDF_STATIC::_escape($string); + + } elseif ($value instanceof PdfHexString) { + $filter = new AsciiHex(); + $string = $filter->decode($value->value); + $string = $this->_encrypt_data($this->currentObjectNumber, $string); + $value->value = $filter->encode($string, true); + + } elseif ($value instanceof PdfStream) { + $stream = $value->getStream(); + $stream = $this->_encrypt_data($this->currentObjectNumber, $stream); + $dictionary = $value->value; + $dictionary->value['Length'] = PdfNumeric::create(\strlen($stream)); + $value = PdfStream::create($dictionary, $stream); + + } elseif ($value instanceof PdfIndirectObject) { + /** + * @var $value PdfIndirectObject + */ + $this->currentObjectNumber = $this->objectMap[$this->currentReaderId][$value->objectNumber]; + } + + $this->fpdiWritePdfType($value); + } +} \ No newline at end of file diff --git a/vendor/setasign/fpdi/src/Tfpdf/FpdfTpl.php b/vendor/setasign/fpdi/src/Tfpdf/FpdfTpl.php new file mode 100644 index 0000000000000000000000000000000000000000..0b527a783febd3c498f2a144b92b5c4ce265c4e0 --- /dev/null +++ b/vendor/setasign/fpdi/src/Tfpdf/FpdfTpl.php @@ -0,0 +1,99 @@ +<?php +/** + * This file is part of FPDI + * + * @package setasign\Fpdi + * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com) + * @license http://opensource.org/licenses/mit-license The MIT License + */ + +namespace setasign\Fpdi\Tfpdf; + +use setasign\Fpdi\FpdfTplTrait; + +/** + * Class FpdfTpl + * + * We need to change some access levels and implement the setPageFormat() method to bring back compatibility to tFPDF. + * + * @package setasign\Fpdi\Tfpdf + */ +class FpdfTpl extends \tFPDF +{ + use FpdfTplTrait { + _putimages as _protectedPutimages; + _putxobjectdict as _protectedPutxobjectdict; + } + + /** + * Make the method public as in tFPDF. + */ + public function _putimages() + { + $this->_protectedPutimages(); + } + + /** + * Make the method public as in tFPDF. + */ + public function _putxobjectdict() + { + $this->_protectedPutxobjectdict(); + } + + /** + * Set the page format of the current page. + * + * @param array $size An array with two values defining the size. + * @param string $orientation "L" for landscape, "P" for portrait. + * @throws \BadMethodCallException + */ + public function setPageFormat($size, $orientation) + { + if ($this->currentTemplateId !== null) { + throw new \BadMethodCallException('The page format cannot be changed when writing to a template.'); + } + + if (!\in_array($orientation, ['P', 'L'], true)) { + throw new \InvalidArgumentException(\sprintf( + 'Invalid page orientation "%s"! Only "P" and "L" are allowed!', + $orientation + )); + } + + $size = $this->_getpagesize($size); + + if ($orientation != $this->CurOrientation + || $size[0] != $this->CurPageSize[0] + || $size[1] != $this->CurPageSize[1] + ) { + // New size or orientation + if ($orientation === 'P') { + $this->w = $size[0]; + $this->h = $size[1]; + } else { + $this->w = $size[1]; + $this->h = $size[0]; + } + $this->wPt = $this->w * $this->k; + $this->hPt = $this->h * $this->k; + $this->PageBreakTrigger = $this->h - $this->bMargin; + $this->CurOrientation = $orientation; + $this->CurPageSize = $size; + + $this->PageSizes[$this->page] = array($this->wPt, $this->hPt); + } + } + + /** + * @inheritdoc + */ + protected function _put($s, $newLine = true) + { + if ($newLine) { + $this->buffer .= $s . "\n"; + } else { + $this->buffer .= $s; + } + } +} \ No newline at end of file diff --git a/vendor/setasign/fpdi/src/Tfpdf/Fpdi.php b/vendor/setasign/fpdi/src/Tfpdf/Fpdi.php new file mode 100644 index 0000000000000000000000000000000000000000..2e4a0fa3515ba6cb70c7a35115c0a3cdbe170eb2 --- /dev/null +++ b/vendor/setasign/fpdi/src/Tfpdf/Fpdi.php @@ -0,0 +1,158 @@ +<?php +/** + * This file is part of FPDI + * + * @package setasign\Fpdi + * @copyright Copyright (c) 2018 Setasign - Jan Slabon (https://www.setasign.com) + * @license http://opensource.org/licenses/mit-license The MIT License + */ + +namespace setasign\Fpdi\Tfpdf; + +use setasign\Fpdi\FpdiTrait; +use setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException; +use setasign\Fpdi\PdfParser\PdfParserException; +use setasign\Fpdi\PdfParser\Type\PdfIndirectObject; +use setasign\Fpdi\PdfParser\Type\PdfNull; + +/** + * Class Fpdi + * + * This class let you import pages of existing PDF documents into a reusable structure for tFPDF. + * + * @package setasign\Fpdi + */ +class Fpdi extends FpdfTpl +{ + use FpdiTrait; + + /** + * FPDI version + * + * @string + */ + const VERSION = '2.1.0'; + + /** + * Draws an imported page or a template onto the page or another template. + * + * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect + * ratio. + * + * @param mixed $tpl The template id + * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array + * with the keys "x", "y", "width", "height", "adjustPageSize". + * @param float|int $y The ordinate of upper-left corner. + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @param bool $adjustPageSize + * @return array The size + * @see Fpdi::getTemplateSize() + */ + public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false) + { + if (isset($this->importedPages[$tpl])) { + $size = $this->useImportedPage($tpl, $x, $y, $width, $height, $adjustPageSize); + if ($this->currentTemplateId !== null) { + $this->templates[$this->currentTemplateId]['resources']['templates']['importedPages'][$tpl] = $tpl; + } + return $size; + } + + return parent::useTemplate($tpl, $x, $y, $width, $height, $adjustPageSize); + } + + /** + * Get the size of an imported page or template. + * + * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect + * ratio. + * + * @param mixed $tpl The template id + * @param float|int|null $width The width. + * @param float|int|null $height The height. + * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P) + */ + public function getTemplateSize($tpl, $width = null, $height = null) + { + $size = parent::getTemplateSize($tpl, $width, $height); + if ($size === false) { + return $this->getImportedPageSize($tpl, $width, $height); + } + + return $size; + } + + /** + * @inheritdoc + * @throws CrossReferenceException + * @throws PdfParserException + */ + public function _putimages() + { + $this->currentReaderId = null; + parent::_putimages(); + + foreach ($this->importedPages as $key => $pageData) { + $this->_newobj(); + $this->importedPages[$key]['objectNumber'] = $this->n; + $this->currentReaderId = $pageData['readerId']; + $this->writePdfType($pageData['stream']); + $this->_put('endobj'); + } + + foreach (\array_keys($this->readers) as $readerId) { + $parser = $this->getPdfReader($readerId)->getParser(); + $this->currentReaderId = $readerId; + + while (($objectNumber = \array_pop($this->objectsToCopy[$readerId])) !== null) { + try { + $object = $parser->getIndirectObject($objectNumber); + + } catch (CrossReferenceException $e) { + if ($e->getCode() === CrossReferenceException::OBJECT_NOT_FOUND) { + $object = PdfIndirectObject::create($objectNumber, 0, new PdfNull()); + } else { + throw $e; + } + } + + $this->writePdfType($object); + } + } + + $this->currentReaderId = null; + } + + /** + * @inheritdoc + */ + public function _putxobjectdict() + { + foreach ($this->importedPages as $key => $pageData) { + $this->_put('/' . $pageData['id'] . ' ' . $pageData['objectNumber'] . ' 0 R'); + } + + parent::_putxobjectdict(); + } + + /** + * @inheritdoc + */ + public function _newobj($n = null) + { + // Begin a new object + if($n === null) + $n = ++$this->n; + $this->offsets[$n] = $this->_getoffset(); + $this->_put($n.' 0 obj'); + } + + /** + * @inheritdoc + */ + protected function _getoffset() + { + return strlen($this->buffer); + } +} \ No newline at end of file diff --git a/vendor/slim/slim/Slim/Http/StatusCode.php b/vendor/slim/slim/Slim/Http/StatusCode.php new file mode 100644 index 0000000000000000000000000000000000000000..301bdd932f46307050d7621a4b98b9d63cb9fbda --- /dev/null +++ b/vendor/slim/slim/Slim/Http/StatusCode.php @@ -0,0 +1,81 @@ +<?php +/** + * Slim Framework (https://slimframework.com) + * + * @link https://github.com/slimphp/Slim + * @copyright Copyright (c) 2011-2017 Josh Lockhart + * @license https://github.com/slimphp/Slim/blob/3.x/LICENSE.md (MIT License) + */ +namespace Slim\Http; + +class StatusCode +{ + const HTTP_CONTINUE = 100; + const HTTP_SWITCHING_PROTOCOLS = 101; + const HTTP_PROCESSING = 102; + + const HTTP_OK = 200; + const HTTP_CREATED = 201; + const HTTP_ACCEPTED = 202; + const HTTP_NONAUTHORITATIVE_INFORMATION = 203; + const HTTP_NO_CONTENT = 204; + const HTTP_RESET_CONTENT = 205; + const HTTP_PARTIAL_CONTENT = 206; + const HTTP_MULTI_STATUS = 207; + const HTTP_ALREADY_REPORTED = 208; + const HTTP_IM_USED = 226; + + const HTTP_MULTIPLE_CHOICES = 300; + const HTTP_MOVED_PERMANENTLY = 301; + const HTTP_FOUND = 302; + const HTTP_SEE_OTHER = 303; + const HTTP_NOT_MODIFIED = 304; + const HTTP_USE_PROXY = 305; + const HTTP_UNUSED= 306; + const HTTP_TEMPORARY_REDIRECT = 307; + const HTTP_PERMANENT_REDIRECT = 308; + + const HTTP_BAD_REQUEST = 400; + const HTTP_UNAUTHORIZED = 401; + const HTTP_PAYMENT_REQUIRED = 402; + const HTTP_FORBIDDEN = 403; + const HTTP_NOT_FOUND = 404; + const HTTP_METHOD_NOT_ALLOWED = 405; + const HTTP_NOT_ACCEPTABLE = 406; + const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; + const HTTP_REQUEST_TIMEOUT = 408; + const HTTP_CONFLICT = 409; + const HTTP_GONE = 410; + const HTTP_LENGTH_REQUIRED = 411; + const HTTP_PRECONDITION_FAILED = 412; + const HTTP_REQUEST_ENTITY_TOO_LARGE = 413; + const HTTP_REQUEST_URI_TOO_LONG = 414; + const HTTP_UNSUPPORTED_MEDIA_TYPE = 415; + const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416; + const HTTP_EXPECTATION_FAILED = 417; + const HTTP_IM_A_TEAPOT = 418; + const HTTP_MISDIRECTED_REQUEST = 421; + const HTTP_UNPROCESSABLE_ENTITY = 422; + const HTTP_LOCKED = 423; + const HTTP_FAILED_DEPENDENCY = 424; + const HTTP_UPGRADE_REQUIRED = 426; + const HTTP_PRECONDITION_REQUIRED = 428; + const HTTP_TOO_MANY_REQUESTS = 429; + const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; + const HTTP_CONNECTION_CLOSED_WITHOUT_RESPONSE = 444; + const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; + const HTTP_CLIENT_CLOSED_REQUEST = 499; + + const HTTP_INTERNAL_SERVER_ERROR = 500; + const HTTP_NOT_IMPLEMENTED = 501; + const HTTP_BAD_GATEWAY = 502; + const HTTP_SERVICE_UNAVAILABLE = 503; + const HTTP_GATEWAY_TIMEOUT = 504; + const HTTP_VERSION_NOT_SUPPORTED = 505; + const HTTP_VARIANT_ALSO_NEGOTIATES = 506; + const HTTP_INSUFFICIENT_STORAGE = 507; + const HTTP_LOOP_DETECTED = 508; + const HTTP_NOT_EXTENDED = 510; + const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; + const HTTP_NETWORK_CONNECTION_TIMEOUT_ERROR = 599; +} diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php new file mode 100644 index 0000000000000000000000000000000000000000..2a8f6e73b99301469991b2bb835324b39d96cd60 --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php @@ -0,0 +1,5 @@ +<?php + +// from Case_Ignorable in https://unicode.org/Public/UNIDATA/DerivedCoreProperties.txt + +return '/(?<![\x{0027}\x{002E}\x{003A}\x{005E}\x{0060}\x{00A8}\x{00AD}\x{00AF}\x{00B4}\x{00B7}\x{00B8}\x{02B0}-\x{02C1}\x{02C2}-\x{02C5}\x{02C6}-\x{02D1}\x{02D2}-\x{02DF}\x{02E0}-\x{02E4}\x{02E5}-\x{02EB}\x{02EC}\x{02ED}\x{02EE}\x{02EF}-\x{02FF}\x{0300}-\x{036F}\x{0374}\x{0375}\x{037A}\x{0384}-\x{0385}\x{0387}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{0559}\x{0591}-\x{05BD}\x{05BF}\x{05C1}-\x{05C2}\x{05C4}-\x{05C5}\x{05C7}\x{05F4}\x{0600}-\x{0605}\x{0610}-\x{061A}\x{061C}\x{0640}\x{064B}-\x{065F}\x{0670}\x{06D6}-\x{06DC}\x{06DD}\x{06DF}-\x{06E4}\x{06E5}-\x{06E6}\x{06E7}-\x{06E8}\x{06EA}-\x{06ED}\x{070F}\x{0711}\x{0730}-\x{074A}\x{07A6}-\x{07B0}\x{07EB}-\x{07F3}\x{07F4}-\x{07F5}\x{07FA}\x{07FD}\x{0816}-\x{0819}\x{081A}\x{081B}-\x{0823}\x{0824}\x{0825}-\x{0827}\x{0828}\x{0829}-\x{082D}\x{0859}-\x{085B}\x{08D3}-\x{08E1}\x{08E2}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0971}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C81}\x{0CBC}\x{0CBF}\x{0CC6}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E46}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EB9}\x{0EBB}-\x{0EBC}\x{0EC6}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{10FC}\x{135D}-\x{135F}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17D7}\x{17DD}\x{180B}-\x{180D}\x{180E}\x{1843}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AA7}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1C78}-\x{1C7D}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1D2C}-\x{1D6A}\x{1D78}\x{1D9B}-\x{1DBF}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{1FBD}\x{1FBF}-\x{1FC1}\x{1FCD}-\x{1FCF}\x{1FDD}-\x{1FDF}\x{1FED}-\x{1FEF}\x{1FFD}-\x{1FFE}\x{200B}-\x{200F}\x{2018}\x{2019}\x{2024}\x{2027}\x{202A}-\x{202E}\x{2060}-\x{2064}\x{2066}-\x{206F}\x{2071}\x{207F}\x{2090}-\x{209C}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2C7C}-\x{2C7D}\x{2CEF}-\x{2CF1}\x{2D6F}\x{2D7F}\x{2DE0}-\x{2DFF}\x{2E2F}\x{3005}\x{302A}-\x{302D}\x{3031}-\x{3035}\x{303B}\x{3099}-\x{309A}\x{309B}-\x{309C}\x{309D}-\x{309E}\x{30FC}-\x{30FE}\x{A015}\x{A4F8}-\x{A4FD}\x{A60C}\x{A66F}\x{A670}-\x{A672}\x{A674}-\x{A67D}\x{A67F}\x{A69C}-\x{A69D}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A700}-\x{A716}\x{A717}-\x{A71F}\x{A720}-\x{A721}\x{A770}\x{A788}\x{A789}-\x{A78A}\x{A7F8}-\x{A7F9}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}\x{A9CF}\x{A9E5}\x{A9E6}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA70}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AADD}\x{AAEC}-\x{AAED}\x{AAF3}-\x{AAF4}\x{AAF6}\x{AB5B}\x{AB5C}-\x{AB5F}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1E}\x{FBB2}-\x{FBC1}\x{FE00}-\x{FE0F}\x{FE13}\x{FE20}-\x{FE2F}\x{FE52}\x{FE55}\x{FEFF}\x{FF07}\x{FF0E}\x{FF1A}\x{FF3E}\x{FF40}\x{FF70}\x{FF9E}-\x{FF9F}\x{FFE3}\x{FFF9}-\x{FFFB}\x{101FD}\x{102E0}\x{10376}-\x{1037A}\x{10A01}-\x{10A03}\x{10A05}-\x{10A06}\x{10A0C}-\x{10A0F}\x{10A38}-\x{10A3A}\x{10A3F}\x{10AE5}-\x{10AE6}\x{10D24}-\x{10D27}\x{10F46}-\x{10F50}\x{11001}\x{11038}-\x{11046}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{110BD}\x{110CD}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{11A01}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C3F}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16B40}-\x{16B43}\x{16F8F}-\x{16F92}\x{16F93}-\x{16F9F}\x{16FE0}-\x{16FE1}\x{1BC9D}-\x{1BC9E}\x{1BCA0}-\x{1BCA3}\x{1D167}-\x{1D169}\x{1D173}-\x{1D17A}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D242}-\x{1D244}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E8D0}-\x{1E8D6}\x{1E944}-\x{1E94A}\x{1F3FB}-\x{1F3FF}\x{E0001}\x{E0020}-\x{E007F}\x{E0100}-\x{E01EF}])(\pL)(\pL*+)/u';