1
0
mirror of https://github.com/typemill/typemill.git synced 2025-07-26 08:50:34 +02:00

Remove Vendor Folder

This commit is contained in:
trendschau
2023-12-17 21:28:39 +01:00
parent 532ddb095d
commit f66b44dd1c
701 changed files with 0 additions and 69995 deletions

View File

@@ -1,3 +0,0 @@
build
vendor
.phpunit.result.cache

View File

@@ -1,25 +0,0 @@
sudo: false
language: php
php:
- 7.0
- 7.1
- 7.2
- nightly
matrix:
allow_failures:
- php: nightly
before_install:
- composer self-update
install:
- travis_retry composer install --no-interaction --ignore-platform-reqs --prefer-source
- composer info -i
script:
- vendor/bin/phpcs
- vendor/bin/phpunit

View File

@@ -1,26 +0,0 @@
Copyright (c) 2015, Rob Allen (rob@akrabat.com)
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.
* The name of Rob Allen may not 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.

View File

@@ -1,40 +0,0 @@
# Proxy Scheme, Host and Port detection middleware
[![Build status][Master image]][Master]
PSR-7 Middleware that determines the scheme, host and port from the 'X-Forwarded-Proto', 'X-Forwarded-Host' and 'X-Forwarded-Port' headers and updates the Request's Uri object.
You can set a list of proxies that are trusted as the second constructor parameter. If this list is set, then the proxy headers will only be checked if the `REMOTE_ADDR` is in the trusted list.
## Installation
`composer require akrabat/proxy-detection-middleware`
## Usage
In Slim 3:
```php
$trustedProxies = ['10.0.0.1', '10.0.0.2'];
$app->add(new RKA\Middleware\ProxyDetection($trustedProxies));
$app->get('/', function ($request, $response, $args) {
$scheme = $request->getUri()->getScheme();
$host = $request->getUri()->getHost();
$port = $request->getUri()->getPort();
return $response;
});
```
## Testing
* Code coverage: ``$ vendor/bin/phpcs``
* Unit tests: ``$ vendor/bin/phpunit``
* Code coverage: ``$ vendor/bin/phpunit --coverage-html ./build``
[Master]: https://travis-ci.org/akrabat/rka-content-type-renderer
[Master image]: https://secure.travis-ci.org/akrabat/rka-content-type-renderer.svg?branch=master

View File

@@ -1,32 +0,0 @@
{
"name": "akrabat/proxy-detection-middleware",
"description": "PSR-7/PSR-15 Middleware that determines the scheme, host and port from the 'X-Forwarded-Proto', 'X-Forwarded-Host' and 'X-Forwarded-Port' headers and updates the Request's Uri object.",
"keywords": [
"psr7", "middleware", "ip"
],
"homepage": "http://github.com/akrabat/proxy-detection-middleware",
"type": "library",
"license": "BSD-3-Clause",
"authors": [
{
"name": "Rob Allen",
"email": "rob@akrabat.com",
"homepage": "http://akrabat.com"
}
],
"require": {
"psr/http-message": "^1.0",
"psr/http-server-middleware": "^1.0"
},
"require-dev": {
"php": "^8.0",
"phpunit/phpunit": "^9.6",
"squizlabs/php_codesniffer": "^3.7",
"laminas/laminas-diactoros": "^2.24"
},
"autoload": {
"psr-4": {
"RKA\\Middleware\\": "src"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +0,0 @@
<?xml version="1.0"?>
<ruleset name="RKA">
<rule ref="PSR2"/>
<!-- Check src and tests directories -->
<file>src</file>
<file>tests</file>
</ruleset>

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
beStrictAboutTestsThatDoNotTestAnything="true"
beStrictAboutChangesToGlobalState="true"
beStrictAboutOutputDuringTests="true"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
>
<testsuites>
<testsuite name="Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./src</directory>
</include>
</coverage>
</phpunit>

View File

@@ -1,143 +0,0 @@
<?php
namespace RKA\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\UriInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class ProxyDetection implements MiddlewareInterface
{
/**
* List of trusted proxy IP addresses
*
* If not empty, then one of these IP addresses must be in $_SERVER['REMOTE_ADDR']
* in order for the proxy headers to be looked at.
*
* @var array
*/
protected $trustedProxies;
/**
* Constructor
*
* @param array $trustedProxies List of IP addresses of trusted proxies
*/
public function __construct($trustedProxies = [])
{
$this->trustedProxies = $trustedProxies;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
return $handler->handle($this->updateRequest($request));
}
/**
* Override the request URI's scheme, host and port as determined from the proxy headers
*
* @param ServerRequestInterface $request PSR7 request
* @param ResponseInterface $response PSR7 response
* @param callable $next Next middleware
*
* @return ResponseInterface
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
{
if (!$next) {
return $response;
}
return $next($this->updateRequest($request), $response);
}
protected function updateRequest(ServerRequestInterface $request): ServerRequestInterface
{
if (!empty($this->trustedProxies)) {
// get IP address from REMOTE_ADDR
$ipAddress = null;
$serverParams = $request->getServerParams();
if (isset($serverParams['REMOTE_ADDR']) && $this->isValidIpAddress($serverParams['REMOTE_ADDR'])) {
$ipAddress = $serverParams['REMOTE_ADDR'];
}
if (!in_array($ipAddress, $this->trustedProxies)) {
return $request;
}
}
$uri = $request->getUri();
$uri = $this->processProtoHeader($request, $uri);
$uri = $this->processPortHeader($request, $uri);
$uri = $this->processHostHeader($request, $uri);
return $request->withUri($uri);
}
/**
* Check that a given string is a valid IP address
*
* @param string $ip
* @return boolean
*/
protected function isValidIpAddress($ip)
{
$flags = FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6;
if (filter_var($ip, FILTER_VALIDATE_IP, $flags) === false) {
return false;
}
return true;
}
protected function processProtoHeader(ServerRequestInterface $request, UriInterface $uri)
{
if ($request->hasHeader('X-Forwarded-Proto')) {
$scheme = $request->getHeaderLine('X-Forwarded-Proto');
if (in_array($scheme, ['http', 'https'])) {
return $uri->withScheme($scheme);
}
}
return $uri;
}
protected function processPortHeader(ServerRequestInterface $request, UriInterface $uri)
{
if ($request->hasHeader('X-Forwarded-Port')) {
$port = trim(current(explode(',', $request->getHeaderLine('X-Forwarded-Port'))));
if (preg_match('/^\d+\z/', $port)) {
return $uri->withPort((int) $port);
}
}
return $uri;
}
protected function processHostHeader(ServerRequestInterface $request, UriInterface $uri)
{
if ($request->hasHeader('X-Forwarded-Host')) {
$host = trim(current(explode(',', $request->getHeaderLine('X-Forwarded-Host'))));
$port = null;
if (preg_match('/^(\[[a-fA-F0-9:.]+\])(:\d+)?\z/', $host, $matches)) {
$host = $matches[1];
if ($matches[2]) {
$port = (int) substr($matches[2], 1);
}
} else {
$pos = strpos($host, ':');
if ($pos !== false) {
$port = (int) substr($host, $pos + 1);
$host = strstr($host, ':', true);
}
}
$uri = $uri->withHost($host);
if ($port) {
$uri = $uri->withPort($port);
}
}
return $uri;
}
}

View File

@@ -1,136 +0,0 @@
<?php
namespace RKA\Middleware\Test;
use PHPUnit\Framework\TestCase;
use RKA\Middleware\ProxyDetection;
use Laminas\Diactoros\Response;
use Laminas\Diactoros\ServerRequestFactory;
class ProxyDetectionTest extends TestCase
{
public function testSchemeAndHostAndPortWithPortInHostHeader()
{
$request = ServerRequestFactory::fromGlobals([
'REMOTE_ADDR' => '1.2.3.4',
'HTTP_HOST' => 'foo.com',
'HTTP_X_FORWARDED_PROTO' => 'https',
'HTTP_X_FORWARDED_HOST' => 'example.com:1234',
]);
$response = new Response();
$middleware = new ProxyDetection();
$middleware($request, $response, function ($request, $response) use (&$scheme, &$host, &$port) {
// simply store the values
$scheme = $request->getUri()->getScheme();
$host = $request->getUri()->getHost();
$port = $request->getUri()->getPort();
return $response;
});
$this->assertSame('https', $scheme);
$this->assertSame('example.com', $host);
$this->assertSame(1234, $port);
}
public function testSchemeAndHostAndPortWithPortInPortHeader()
{
$request = ServerRequestFactory::fromGlobals([
'REMOTE_ADDR' => '1.2.3.4',
'HTTP_HOST' => 'foo.com',
'HTTP_X_FORWARDED_PROTO' => 'https',
'HTTP_X_FORWARDED_HOST' => 'example.com',
'HTTP_X_FORWARDED_PORT' => '1234',
]);
$response = new Response();
$middleware = new ProxyDetection();
$middleware($request, $response, function ($request, $response) use (&$scheme, &$host, &$port) {
// simply store the values
$scheme = $request->getUri()->getScheme();
$host = $request->getUri()->getHost();
$port = $request->getUri()->getPort();
return $response;
});
$this->assertSame('https', $scheme);
$this->assertSame('example.com', $host);
$this->assertSame(1234, $port);
}
public function testSchemeAndHostAndPortWithPortInHostAndPortHeader()
{
$request = ServerRequestFactory::fromGlobals([
'REMOTE_ADDR' => '1.2.3.4',
'HTTP_HOST' => 'foo.com',
'HTTP_X_FORWARDED_PROTO' => 'https',
'HTTP_X_FORWARDED_HOST' => 'example.com:1000',
'HTTP_X_FORWARDED_PORT' => '2000',
]);
$response = new Response();
$middleware = new ProxyDetection();
$middleware($request, $response, function ($request, $response) use (&$scheme, &$host, &$port) {
// simply store the values
$scheme = $request->getUri()->getScheme();
$host = $request->getUri()->getHost();
$port = $request->getUri()->getPort();
return $response;
});
$this->assertSame('https', $scheme);
$this->assertSame('example.com', $host);
$this->assertSame(1000, $port);
}
public function testTrustedProxies()
{
$request = ServerRequestFactory::fromGlobals([
'REMOTE_ADDR' => '1.2.3.4',
'HTTP_HOST' => 'foo.com',
'HTTP_X_FORWARDED_PROTO' => 'https',
'HTTP_X_FORWARDED_HOST' => 'example.com:1234',
]);
$response = new Response();
$middleware = new ProxyDetection(['1.2.3.4']);
$middleware($request, $response, function ($request, $response) use (&$scheme, &$host, &$port) {
// simply store the values
$scheme = $request->getUri()->getScheme();
$host = $request->getUri()->getHost();
$port = $request->getUri()->getPort();
return $response;
});
$this->assertSame('https', $scheme);
$this->assertSame('example.com', $host);
$this->assertSame(1234, $port);
}
public function testNonTrustedProxiesIgnoreXForwardedHost()
{
$request = ServerRequestFactory::fromGlobals([
'REMOTE_ADDR' => '4.3.2.1',
'HTTP_HOST' => 'foo.com',
'HTTP_X_FORWARDED_HOST' => 'example.com:1234',
]);
$response = new Response();
$middleware = new ProxyDetection(['1.2.3.4']);
$middleware($request, $response, function ($request, $response) use (&$scheme, &$host, &$port) {
// simply store the values
$scheme = $request->getUri()->getScheme();
$host = $request->getUri()->getHost();
$port = $request->getUri()->getPort();
return $response;
});
$this->assertSame('http', $scheme);
$this->assertSame('foo.com', $host);
$this->assertSame(null, $port);
}
}

View File

@@ -1,12 +0,0 @@
<?php
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
exit(1);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit836351be733ecbf4741aea17e1973480::getLoader();

View File

@@ -1,117 +0,0 @@
#!/usr/bin/env php
<?php
/**
* Proxy PHP file generated by Composer
*
* This file includes the referenced bin path (../symfony/yaml/Resources/bin/yaml-lint)
* using a stream wrapper to prevent the shebang from being output on PHP<8
*
* @generated
*/
namespace Composer;
$GLOBALS['_composer_bin_dir'] = __DIR__;
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
if (PHP_VERSION_ID < 80000) {
if (!class_exists('Composer\BinProxyWrapper')) {
/**
* @internal
*/
final class BinProxyWrapper
{
private $handle;
private $position;
private $realpath;
public function stream_open($path, $mode, $options, &$opened_path)
{
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
$opened_path = substr($path, 17);
$this->realpath = realpath($opened_path) ?: $opened_path;
$opened_path = $this->realpath;
$this->handle = fopen($this->realpath, $mode);
$this->position = 0;
return (bool) $this->handle;
}
public function stream_read($count)
{
$data = fread($this->handle, $count);
if ($this->position === 0) {
$data = preg_replace('{^#!.*\r?\n}', '', $data);
}
$this->position += strlen($data);
return $data;
}
public function stream_cast($castAs)
{
return $this->handle;
}
public function stream_close()
{
fclose($this->handle);
}
public function stream_lock($operation)
{
return $operation ? flock($this->handle, $operation) : true;
}
public function stream_seek($offset, $whence)
{
if (0 === fseek($this->handle, $offset, $whence)) {
$this->position = ftell($this->handle);
return true;
}
return false;
}
public function stream_tell()
{
return $this->position;
}
public function stream_eof()
{
return feof($this->handle);
}
public function stream_stat()
{
return array();
}
public function stream_set_option($option, $arg1, $arg2)
{
return true;
}
public function url_stat($path, $flags)
{
$path = substr($path, 17);
if (file_exists($path)) {
return stat($path);
}
return false;
}
}
}
if (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) {
include("phpvfscomposer://" . __DIR__ . '/..'.'/symfony/yaml/Resources/bin/yaml-lint');
exit(0);
}
}
include __DIR__ . '/..'.'/symfony/yaml/Resources/bin/yaml-lint';

View File

@@ -1,572 +0,0 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see https://www.php-fig.org/psr/psr-0/
* @see https://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
/** @var ?string */
private $vendorDir;
// PSR-4
/**
* @var array[]
* @psalm-var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, array<int, string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* @var array[]
* @psalm-var array<string, array<string, string[]>>
*/
private $prefixesPsr0 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr0 = array();
/** @var bool */
private $useIncludePath = false;
/**
* @var string[]
* @psalm-var array<string, string>
*/
private $classMap = array();
/** @var bool */
private $classMapAuthoritative = false;
/**
* @var bool[]
* @psalm-var array<string, bool>
*/
private $missingClasses = array();
/** @var ?string */
private $apcuPrefix;
/**
* @var self[]
*/
private static $registeredLoaders = array();
/**
* @param ?string $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
}
/**
* @return string[]
*/
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
}
return array();
}
/**
* @return array[]
* @psalm-return array<string, array<int, string>>
*/
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
/**
* @return string[] Array of classname => path
* @psalm-return array<string, string>
*/
public function getClassMap()
{
return $this->classMap;
}
/**
* @param string[] $classMap Class to filename map
* @psalm-param array<string, string> $classMap
*
* @return void
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories
*
* @return void
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*
* @return void
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*
* @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*
* @return void
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*
* @return void
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
if (null === $this->vendorDir) {
return;
}
if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
}
/**
* Unregisters this instance as an autoloader.
*
* @return void
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
return null;
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
*
* @return self[]
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
/**
* @param string $class
* @param string $ext
* @return string|false
*/
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
* @private
*/
function includeFile($file)
{
include $file;
}

View File

@@ -1,352 +0,0 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer;
use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
/**
* This class is copied in every Composer installed project and available to all
*
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
*
* To require its presence, you can require `composer-runtime-api ^2.0`
*
* @final
*/
class InstalledVersions
{
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
*/
private static $installed;
/**
* @var bool|null
*/
private static $canGetVendors;
/**
* @var array[]
* @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
*/
private static $installedByVendor = array();
/**
* Returns a list of all package names which are present, either by being installed, replaced or provided
*
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackages()
{
$packages = array();
foreach (self::getInstalled() as $installed) {
$packages[] = array_keys($installed['versions']);
}
if (1 === \count($packages)) {
return $packages[0];
}
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
}
/**
* Returns a list of all package names with a specific type e.g. 'library'
*
* @param string $type
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackagesByType($type)
{
$packagesByType = array();
foreach (self::getInstalled() as $installed) {
foreach ($installed['versions'] as $name => $package) {
if (isset($package['type']) && $package['type'] === $type) {
$packagesByType[] = $name;
}
}
}
return $packagesByType;
}
/**
* Checks whether the given package is installed
*
* This also returns true if the package name is provided or replaced by another package
*
* @param string $packageName
* @param bool $includeDevRequirements
* @return bool
*/
public static function isInstalled($packageName, $includeDevRequirements = true)
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
}
}
return false;
}
/**
* Checks whether the given package satisfies a version constraint
*
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
*
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
*
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
* @param string $packageName
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
* @return bool
*/
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints($constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
}
/**
* Returns a version constraint representing all the range(s) which are installed for a given package
*
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
* whether a given version of a package is installed, and not just whether it exists
*
* @param string $packageName
* @return string Version constraint usable with composer/semver
*/
public static function getVersionRanges($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
$ranges = array();
if (isset($installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
}
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
}
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
}
if (array_key_exists('provided', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
}
return implode(' || ', $ranges);
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['version'])) {
return null;
}
return $installed['versions'][$packageName]['version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getPrettyVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
return null;
}
return $installed['versions'][$packageName]['pretty_version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
*/
public static function getReference($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['reference'])) {
return null;
}
return $installed['versions'][$packageName]['reference'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
*/
public static function getInstallPath($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @return array
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
*/
public static function getRootPackage()
{
$installed = self::getInstalled();
return $installed[0]['root'];
}
/**
* Returns the raw installed.php data for custom implementations
*
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
* @return array[]
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
*/
public static function getRawData()
{
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = include __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
return self::$installed;
}
/**
* Returns the raw data of all installed.php which are currently loaded for custom implementations
*
* @return array[]
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
*/
public static function getAllRawData()
{
return self::getInstalled();
}
/**
* Lets you reload the static array from another file
*
* This is only useful for complex integrations in which a project needs to use
* this class but then also needs to execute another project's autoloader in process,
* and wants to ensure both projects have access to their version of installed.php.
*
* A typical case would be PHPUnit, where it would need to make sure it reads all
* the data it needs from this class, then call reload() with
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
* the project in which it runs can then also use this class safely, without
* interference between PHPUnit's dependencies and the project's dependencies.
*
* @param array[] $data A vendor/composer/installed.php data set
* @return void
*
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
*/
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
*/
private static function getInstalled()
{
if (null === self::$canGetVendors) {
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
}
$installed = array();
if (self::$canGetVendors) {
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $installed[count($installed) - 1];
}
}
}
}
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = require __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
$installed[] = self::$installed;
return $installed;
}
}

View File

@@ -1,21 +0,0 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1,17 +0,0 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname(dirname($vendorDir));
return array(
'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'CURLStringFile' => $vendorDir . '/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php',
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
'ReturnTypeWillChange' => $vendorDir . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php',
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
);

View File

@@ -1,17 +0,0 @@
<?php
// autoload_files.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname(dirname($vendorDir));
return array(
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'253c157292f75eb38082b5acb06f3f01' => $vendorDir . '/nikic/fast-route/src/functions.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'b33e3d135e5d9e47d845c576147bda89' => $vendorDir . '/php-di/php-di/src/functions.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php',
);

View File

@@ -1,12 +0,0 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname(dirname($vendorDir));
return array(
'URLify' => array($vendorDir . '/jbroadway/urlify'),
'ParsedownExtra' => array($vendorDir . '/erusev/parsedown-extra'),
'Parsedown' => array($vendorDir . '/erusev/parsedown'),
);

View File

@@ -1,41 +0,0 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname(dirname($vendorDir));
return array(
'Valitron\\' => array($vendorDir . '/vlucas/valitron/src/Valitron'),
'Typemill\\' => array($baseDir . '/system/typemill'),
'Twig\\' => array($vendorDir . '/twig/twig/src'),
'Symfony\\Polyfill\\Php81\\' => array($vendorDir . '/symfony/polyfill-php81'),
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
'Symfony\\Contracts\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher-contracts'),
'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
'Slim\\Views\\' => array($vendorDir . '/slim/twig-view/src'),
'Slim\\Psr7\\' => array($vendorDir . '/slim/psr7/src'),
'Slim\\Flash\\' => array($vendorDir . '/slim/flash/src'),
'Slim\\Csrf\\' => array($vendorDir . '/slim/csrf/src'),
'Slim\\' => array($vendorDir . '/slim/slim/Slim'),
'RKA\\Middleware\\' => array($vendorDir . '/akrabat/proxy-detection-middleware/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/src'),
'Psr\\Http\\Server\\' => array($vendorDir . '/psr/http-server-handler/src', $vendorDir . '/psr/http-server-middleware/src'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
'Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'Plugins\\' => array($baseDir . '/plugins'),
'PhpDocReader\\' => array($vendorDir . '/php-di/phpdoc-reader/src/PhpDocReader'),
'Laravel\\SerializableClosure\\' => array($vendorDir . '/laravel/serializable-closure/src'),
'Laminas\\Permissions\\Acl\\' => array($vendorDir . '/laminas/laminas-permissions-acl/src'),
'Invoker\\' => array($vendorDir . '/php-di/invoker/src'),
'Gregwar\\' => array($vendorDir . '/gregwar/captcha/src/Gregwar'),
'Fig\\Http\\Message\\' => array($vendorDir . '/fig/http-message-util/src'),
'FastRoute\\' => array($vendorDir . '/nikic/fast-route/src'),
'DI\\Bridge\\Slim\\' => array($vendorDir . '/php-di/slim-bridge/src'),
'DI\\' => array($vendorDir . '/php-di/php-di/src'),
);

View File

@@ -1,57 +0,0 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit836351be733ecbf4741aea17e1973480
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit836351be733ecbf4741aea17e1973480', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit836351be733ecbf4741aea17e1973480', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit836351be733ecbf4741aea17e1973480::getInitializer($loader));
$loader->register(true);
$includeFiles = \Composer\Autoload\ComposerStaticInit836351be733ecbf4741aea17e1973480::$files;
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire836351be733ecbf4741aea17e1973480($fileIdentifier, $file);
}
return $loader;
}
}
/**
* @param string $fileIdentifier
* @param string $file
* @return void
*/
function composerRequire836351be733ecbf4741aea17e1973480($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
require $file;
}
}

View File

@@ -1,260 +0,0 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInit836351be733ecbf4741aea17e1973480
{
public static $files = array (
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'253c157292f75eb38082b5acb06f3f01' => __DIR__ . '/..' . '/nikic/fast-route/src/functions.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'b33e3d135e5d9e47d845c576147bda89' => __DIR__ . '/..' . '/php-di/php-di/src/functions.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
'23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php',
);
public static $prefixLengthsPsr4 = array (
'V' =>
array (
'Valitron\\' => 9,
),
'T' =>
array (
'Typemill\\' => 9,
'Twig\\' => 5,
),
'S' =>
array (
'Symfony\\Polyfill\\Php81\\' => 23,
'Symfony\\Polyfill\\Php80\\' => 23,
'Symfony\\Polyfill\\Mbstring\\' => 26,
'Symfony\\Polyfill\\Ctype\\' => 23,
'Symfony\\Contracts\\EventDispatcher\\' => 34,
'Symfony\\Component\\Yaml\\' => 23,
'Symfony\\Component\\Finder\\' => 25,
'Symfony\\Component\\EventDispatcher\\' => 34,
'Slim\\Views\\' => 11,
'Slim\\Psr7\\' => 10,
'Slim\\Flash\\' => 11,
'Slim\\Csrf\\' => 10,
'Slim\\' => 5,
),
'R' =>
array (
'RKA\\Middleware\\' => 15,
),
'P' =>
array (
'Psr\\Log\\' => 8,
'Psr\\Http\\Server\\' => 16,
'Psr\\Http\\Message\\' => 17,
'Psr\\EventDispatcher\\' => 20,
'Psr\\Container\\' => 14,
'Plugins\\' => 8,
'PhpDocReader\\' => 13,
),
'L' =>
array (
'Laravel\\SerializableClosure\\' => 28,
'Laminas\\Permissions\\Acl\\' => 24,
),
'I' =>
array (
'Invoker\\' => 8,
),
'G' =>
array (
'Gregwar\\' => 8,
),
'F' =>
array (
'Fig\\Http\\Message\\' => 17,
'FastRoute\\' => 10,
),
'D' =>
array (
'DI\\Bridge\\Slim\\' => 15,
'DI\\' => 3,
),
);
public static $prefixDirsPsr4 = array (
'Valitron\\' =>
array (
0 => __DIR__ . '/..' . '/vlucas/valitron/src/Valitron',
),
'Typemill\\' =>
array (
0 => __DIR__ . '/../../..' . '/system/typemill',
),
'Twig\\' =>
array (
0 => __DIR__ . '/..' . '/twig/twig/src',
),
'Symfony\\Polyfill\\Php81\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php81',
),
'Symfony\\Polyfill\\Php80\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
),
'Symfony\\Polyfill\\Mbstring\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
),
'Symfony\\Polyfill\\Ctype\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
),
'Symfony\\Contracts\\EventDispatcher\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts',
),
'Symfony\\Component\\Yaml\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/yaml',
),
'Symfony\\Component\\Finder\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/finder',
),
'Symfony\\Component\\EventDispatcher\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/event-dispatcher',
),
'Slim\\Views\\' =>
array (
0 => __DIR__ . '/..' . '/slim/twig-view/src',
),
'Slim\\Psr7\\' =>
array (
0 => __DIR__ . '/..' . '/slim/psr7/src',
),
'Slim\\Flash\\' =>
array (
0 => __DIR__ . '/..' . '/slim/flash/src',
),
'Slim\\Csrf\\' =>
array (
0 => __DIR__ . '/..' . '/slim/csrf/src',
),
'Slim\\' =>
array (
0 => __DIR__ . '/..' . '/slim/slim/Slim',
),
'RKA\\Middleware\\' =>
array (
0 => __DIR__ . '/..' . '/akrabat/proxy-detection-middleware/src',
),
'Psr\\Log\\' =>
array (
0 => __DIR__ . '/..' . '/psr/log/src',
),
'Psr\\Http\\Server\\' =>
array (
0 => __DIR__ . '/..' . '/psr/http-server-handler/src',
1 => __DIR__ . '/..' . '/psr/http-server-middleware/src',
),
'Psr\\Http\\Message\\' =>
array (
0 => __DIR__ . '/..' . '/psr/http-factory/src',
1 => __DIR__ . '/..' . '/psr/http-message/src',
),
'Psr\\EventDispatcher\\' =>
array (
0 => __DIR__ . '/..' . '/psr/event-dispatcher/src',
),
'Psr\\Container\\' =>
array (
0 => __DIR__ . '/..' . '/psr/container/src',
),
'Plugins\\' =>
array (
0 => __DIR__ . '/../../..' . '/plugins',
),
'PhpDocReader\\' =>
array (
0 => __DIR__ . '/..' . '/php-di/phpdoc-reader/src/PhpDocReader',
),
'Laravel\\SerializableClosure\\' =>
array (
0 => __DIR__ . '/..' . '/laravel/serializable-closure/src',
),
'Laminas\\Permissions\\Acl\\' =>
array (
0 => __DIR__ . '/..' . '/laminas/laminas-permissions-acl/src',
),
'Invoker\\' =>
array (
0 => __DIR__ . '/..' . '/php-di/invoker/src',
),
'Gregwar\\' =>
array (
0 => __DIR__ . '/..' . '/gregwar/captcha/src/Gregwar',
),
'Fig\\Http\\Message\\' =>
array (
0 => __DIR__ . '/..' . '/fig/http-message-util/src',
),
'FastRoute\\' =>
array (
0 => __DIR__ . '/..' . '/nikic/fast-route/src',
),
'DI\\Bridge\\Slim\\' =>
array (
0 => __DIR__ . '/..' . '/php-di/slim-bridge/src',
),
'DI\\' =>
array (
0 => __DIR__ . '/..' . '/php-di/php-di/src',
),
);
public static $prefixesPsr0 = array (
'U' =>
array (
'URLify' =>
array (
0 => __DIR__ . '/..' . '/jbroadway/urlify',
),
),
'P' =>
array (
'ParsedownExtra' =>
array (
0 => __DIR__ . '/..' . '/erusev/parsedown-extra',
),
'Parsedown' =>
array (
0 => __DIR__ . '/..' . '/erusev/parsedown',
),
),
);
public static $classMap = array (
'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'CURLStringFile' => __DIR__ . '/..' . '/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php',
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
'ReturnTypeWillChange' => __DIR__ . '/..' . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php',
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit836351be733ecbf4741aea17e1973480::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit836351be733ecbf4741aea17e1973480::$prefixDirsPsr4;
$loader->prefixesPsr0 = ComposerStaticInit836351be733ecbf4741aea17e1973480::$prefixesPsr0;
$loader->classMap = ComposerStaticInit836351be733ecbf4741aea17e1973480::$classMap;
}, null, ClassLoader::class);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,390 +0,0 @@
<?php return array(
'root' => array(
'pretty_version' => '2.x-dev',
'version' => '2.9999999.9999999.9999999-dev',
'type' => 'project',
'install_path' => __DIR__ . '/../../../',
'aliases' => array(),
'reference' => '8fb86495b65737eaa0e413eaf1e22cc2ffd2e022',
'name' => 'typemill/typemill',
'dev' => true,
),
'versions' => array(
'akrabat/proxy-detection-middleware' => array(
'pretty_version' => '1.0',
'version' => '1.0.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../akrabat/proxy-detection-middleware',
'aliases' => array(),
'reference' => '90472f490e56ad23afc36b0d95c24cd48fa331d7',
'dev_requirement' => false,
),
'erusev/parsedown' => array(
'pretty_version' => '1.8.0-beta-7',
'version' => '1.8.0.0-beta7',
'type' => 'library',
'install_path' => __DIR__ . '/../erusev/parsedown',
'aliases' => array(),
'reference' => 'fe7a50eceb4a3c867cc9fa9c0aa906b1067d1955',
'dev_requirement' => false,
),
'erusev/parsedown-extra' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'type' => 'library',
'install_path' => __DIR__ . '/../erusev/parsedown-extra',
'aliases' => array(
0 => '9999999-dev',
),
'reference' => 'fd33d68349630d18d56367712a64445a6e0bc83e',
'dev_requirement' => false,
),
'fig/http-message-util' => array(
'pretty_version' => '1.1.5',
'version' => '1.1.5.0',
'type' => 'library',
'install_path' => __DIR__ . '/../fig/http-message-util',
'aliases' => array(),
'reference' => '9d94dc0154230ac39e5bf89398b324a86f63f765',
'dev_requirement' => false,
),
'gregwar/captcha' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'type' => 'library',
'install_path' => __DIR__ . '/../gregwar/captcha',
'aliases' => array(
0 => '9999999-dev',
),
'reference' => '229d3cdfe33d6f1349e0aec94a26e9205a6db08e',
'dev_requirement' => false,
),
'jbroadway/urlify' => array(
'pretty_version' => '1.1.3-stable',
'version' => '1.1.3.0',
'type' => 'library',
'install_path' => __DIR__ . '/../jbroadway/urlify',
'aliases' => array(),
'reference' => '37fe4e7680a1c8cd68ac43a27dac7ef4be476300',
'dev_requirement' => false,
),
'laminas/laminas-permissions-acl' => array(
'pretty_version' => '2.14.0',
'version' => '2.14.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../laminas/laminas-permissions-acl',
'aliases' => array(),
'reference' => '86cecb540cf8f2e088d70d8acef1fc9203ed5023',
'dev_requirement' => false,
),
'laravel/serializable-closure' => array(
'pretty_version' => 'v1.3.3',
'version' => '1.3.3.0',
'type' => 'library',
'install_path' => __DIR__ . '/../laravel/serializable-closure',
'aliases' => array(),
'reference' => '3dbf8a8e914634c48d389c1234552666b3d43754',
'dev_requirement' => false,
),
'nikic/fast-route' => array(
'pretty_version' => 'v1.3.0',
'version' => '1.3.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../nikic/fast-route',
'aliases' => array(),
'reference' => '181d480e08d9476e61381e04a71b34dc0432e812',
'dev_requirement' => false,
),
'php-di/invoker' => array(
'pretty_version' => '2.3.4',
'version' => '2.3.4.0',
'type' => 'library',
'install_path' => __DIR__ . '/../php-di/invoker',
'aliases' => array(),
'reference' => '33234b32dafa8eb69202f950a1fc92055ed76a86',
'dev_requirement' => false,
),
'php-di/php-di' => array(
'pretty_version' => '6.4.0',
'version' => '6.4.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../php-di/php-di',
'aliases' => array(),
'reference' => 'ae0f1b3b03d8b29dff81747063cbfd6276246cc4',
'dev_requirement' => false,
),
'php-di/phpdoc-reader' => array(
'pretty_version' => '2.2.1',
'version' => '2.2.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../php-di/phpdoc-reader',
'aliases' => array(),
'reference' => '66daff34cbd2627740ffec9469ffbac9f8c8185c',
'dev_requirement' => false,
),
'php-di/slim-bridge' => array(
'pretty_version' => '3.4.0',
'version' => '3.4.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../php-di/slim-bridge',
'aliases' => array(),
'reference' => 'd14c95b34b3c5ba2e8c40020dd93fdcc8f3ba875',
'dev_requirement' => false,
),
'psr/container' => array(
'pretty_version' => '1.1.2',
'version' => '1.1.2.0',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/container',
'aliases' => array(),
'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea',
'dev_requirement' => false,
),
'psr/container-implementation' => array(
'dev_requirement' => false,
'provided' => array(
0 => '^1.0',
),
),
'psr/event-dispatcher' => array(
'pretty_version' => '1.0.0',
'version' => '1.0.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/event-dispatcher',
'aliases' => array(),
'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0',
'dev_requirement' => false,
),
'psr/event-dispatcher-implementation' => array(
'dev_requirement' => false,
'provided' => array(
0 => '1.0',
),
),
'psr/http-factory' => array(
'pretty_version' => '1.0.2',
'version' => '1.0.2.0',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/http-factory',
'aliases' => array(),
'reference' => 'e616d01114759c4c489f93b099585439f795fe35',
'dev_requirement' => false,
),
'psr/http-factory-implementation' => array(
'dev_requirement' => false,
'provided' => array(
0 => '1.0',
),
),
'psr/http-message' => array(
'pretty_version' => '1.1',
'version' => '1.1.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/http-message',
'aliases' => array(),
'reference' => 'cb6ce4845ce34a8ad9e68117c10ee90a29919eba',
'dev_requirement' => false,
),
'psr/http-message-implementation' => array(
'dev_requirement' => false,
'provided' => array(
0 => '1.0',
),
),
'psr/http-server-handler' => array(
'pretty_version' => '1.0.2',
'version' => '1.0.2.0',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/http-server-handler',
'aliases' => array(),
'reference' => '84c4fb66179be4caaf8e97bd239203245302e7d4',
'dev_requirement' => false,
),
'psr/http-server-middleware' => array(
'pretty_version' => '1.0.2',
'version' => '1.0.2.0',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/http-server-middleware',
'aliases' => array(),
'reference' => 'c1481f747daaa6a0782775cd6a8c26a1bf4a3829',
'dev_requirement' => false,
),
'psr/log' => array(
'pretty_version' => '3.0.0',
'version' => '3.0.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/log',
'aliases' => array(),
'reference' => 'fe5ea303b0887d5caefd3d431c3e61ad47037001',
'dev_requirement' => false,
),
'ralouphie/getallheaders' => array(
'pretty_version' => '3.0.3',
'version' => '3.0.3.0',
'type' => 'library',
'install_path' => __DIR__ . '/../ralouphie/getallheaders',
'aliases' => array(),
'reference' => '120b605dfeb996808c31b6477290a714d356e822',
'dev_requirement' => false,
),
'slim/csrf' => array(
'pretty_version' => '1.3.0',
'version' => '1.3.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../slim/csrf',
'aliases' => array(),
'reference' => 'ebaaf295fd6d7224078d8ae3bba45329b31798c7',
'dev_requirement' => false,
),
'slim/flash' => array(
'pretty_version' => '0.4.0',
'version' => '0.4.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../slim/flash',
'aliases' => array(),
'reference' => '9aaff5fded3b54f4e519ec3d4ac74d3d1f2cbbbc',
'dev_requirement' => false,
),
'slim/psr7' => array(
'pretty_version' => '1.6.1',
'version' => '1.6.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../slim/psr7',
'aliases' => array(),
'reference' => '72d2b2bac94ab4575d369f605dbfafbe168d3163',
'dev_requirement' => false,
),
'slim/slim' => array(
'pretty_version' => '4.12.0',
'version' => '4.12.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../slim/slim',
'aliases' => array(),
'reference' => 'e9e99c2b24398b967841c6c4c3048622cc7e2b18',
'dev_requirement' => false,
),
'slim/twig-view' => array(
'pretty_version' => '3.3.0',
'version' => '3.3.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../slim/twig-view',
'aliases' => array(),
'reference' => 'df6dd6af6bbe28041be49c9fb8470c2e9b70cd98',
'dev_requirement' => false,
),
'symfony/deprecation-contracts' => array(
'pretty_version' => 'v2.5.2',
'version' => '2.5.2.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
'aliases' => array(),
'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66',
'dev_requirement' => false,
),
'symfony/event-dispatcher' => array(
'pretty_version' => 'v5.4.26',
'version' => '5.4.26.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/event-dispatcher',
'aliases' => array(),
'reference' => '5dcc00e03413f05c1e7900090927bb7247cb0aac',
'dev_requirement' => false,
),
'symfony/event-dispatcher-contracts' => array(
'pretty_version' => 'v2.5.2',
'version' => '2.5.2.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/event-dispatcher-contracts',
'aliases' => array(),
'reference' => 'f98b54df6ad059855739db6fcbc2d36995283fe1',
'dev_requirement' => false,
),
'symfony/event-dispatcher-implementation' => array(
'dev_requirement' => false,
'provided' => array(
0 => '2.0',
),
),
'symfony/finder' => array(
'pretty_version' => 'v5.4.27',
'version' => '5.4.27.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/finder',
'aliases' => array(),
'reference' => 'ff4bce3c33451e7ec778070e45bd23f74214cd5d',
'dev_requirement' => false,
),
'symfony/polyfill-ctype' => array(
'pretty_version' => 'v1.28.0',
'version' => '1.28.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
'aliases' => array(),
'reference' => 'ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb',
'dev_requirement' => false,
),
'symfony/polyfill-mbstring' => array(
'pretty_version' => 'v1.28.0',
'version' => '1.28.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
'aliases' => array(),
'reference' => '42292d99c55abe617799667f454222c54c60e229',
'dev_requirement' => false,
),
'symfony/polyfill-php80' => array(
'pretty_version' => 'v1.28.0',
'version' => '1.28.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
'aliases' => array(),
'reference' => '6caa57379c4aec19c0a12a38b59b26487dcfe4b5',
'dev_requirement' => false,
),
'symfony/polyfill-php81' => array(
'pretty_version' => 'v1.28.0',
'version' => '1.28.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php81',
'aliases' => array(),
'reference' => '7581cd600fa9fd681b797d00b02f068e2f13263b',
'dev_requirement' => false,
),
'symfony/yaml' => array(
'pretty_version' => 'v5.4.31',
'version' => '5.4.31.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/yaml',
'aliases' => array(),
'reference' => 'f387675d7f5fc4231f7554baa70681f222f73563',
'dev_requirement' => false,
),
'twig/twig' => array(
'pretty_version' => 'v3.8.0',
'version' => '3.8.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../twig/twig',
'aliases' => array(),
'reference' => '9d15f0ac07f44dc4217883ec6ae02fd555c6f71d',
'dev_requirement' => false,
),
'typemill/typemill' => array(
'pretty_version' => '2.x-dev',
'version' => '2.9999999.9999999.9999999-dev',
'type' => 'project',
'install_path' => __DIR__ . '/../../../',
'aliases' => array(),
'reference' => '8fb86495b65737eaa0e413eaf1e22cc2ffd2e022',
'dev_requirement' => false,
),
'vlucas/valitron' => array(
'pretty_version' => 'v1.4.11',
'version' => '1.4.11.0',
'type' => 'library',
'install_path' => __DIR__ . '/../vlucas/valitron',
'aliases' => array(),
'reference' => 'fadce39f5f235755bb9794b2573af2d5bfcba85f',
'dev_requirement' => false,
),
),
);

View File

@@ -1,26 +0,0 @@
<?php
// platform_check.php @generated by Composer
$issues = array();
if (!(PHP_VERSION_ID >= 80000)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.0.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
} elseif (!headers_sent()) {
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
}
}
trigger_error(
'Composer detected issues in your platform: ' . implode(' ', $issues),
E_USER_ERROR
);
}

Submodule system/vendor/erusev/parsedown-extra deleted from fd33d68349

View File

@@ -1,20 +0,0 @@
The MIT License (MIT)
Copyright (c) 2013-2018 Emanuil Rusev, erusev.com
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

File diff suppressed because it is too large Load Diff

View File

@@ -1,97 +0,0 @@
> I also make [Caret](https://caret.io?ref=parsedown) - a Markdown editor for Mac and PC.
## Parsedown
[![Build Status](https://img.shields.io/travis/erusev/parsedown/master.svg?style=flat-square)](https://travis-ci.org/erusev/parsedown)
<!--[![Total Downloads](http://img.shields.io/packagist/dt/erusev/parsedown.svg?style=flat-square)](https://packagist.org/packages/erusev/parsedown)-->
Better Markdown Parser in PHP
[Demo](http://parsedown.org/demo) |
[Benchmarks](http://parsedown.org/speed) |
[Tests](http://parsedown.org/tests/) |
[Documentation](https://github.com/erusev/parsedown/wiki/)
### Features
* One File
* No Dependencies
* Super Fast
* Extensible
* [GitHub flavored](https://help.github.com/articles/github-flavored-markdown)
* Tested in 5.3 to 7.2 and in HHVM
* [Markdown Extra extension](https://github.com/erusev/parsedown-extra)
### Installation
#### Composer
Install the [composer package] by running the following command:
composer require erusev/parsedown
#### Manual
1. Download the "Source code" from the [latest release]
2. Include `Parsedown.php`
[composer package]: https://packagist.org/packages/erusev/parsedown "The Parsedown package on packagist.org"
[latest release]: https://github.com/erusev/parsedown/releases/latest "The latest release of Parsedown"
### Example
``` php
$Parsedown = new Parsedown();
echo $Parsedown->text('Hello _Parsedown_!'); # prints: <p>Hello <em>Parsedown</em>!</p>
// you can also parse inline markdown only
echo $Parsedown->line('Hello _Parsedown_!'); # prints: Hello <em>Parsedown</em>!
```
More examples in [the wiki](https://github.com/erusev/parsedown/wiki/) and in [this video tutorial](http://youtu.be/wYZBY8DEikI).
### Security
Parsedown is capable of escaping user-input within the HTML that it generates. Additionally Parsedown will apply sanitisation to additional scripting vectors (such as scripting link destinations) that are introduced by the markdown syntax itself.
To tell Parsedown that it is processing untrusted user-input, use the following:
```php
$parsedown = new Parsedown;
$parsedown->setSafeMode(true);
```
If instead, you wish to allow HTML within untrusted user-input, but still want output to be free from XSS it is recommended that you make use of a HTML sanitiser that allows HTML tags to be whitelisted, like [HTML Purifier](http://htmlpurifier.org/).
In both cases you should strongly consider employing defence-in-depth measures, like [deploying a Content-Security-Policy](https://scotthelme.co.uk/content-security-policy-an-introduction/) (a browser security feature) so that your page is likely to be safe even if an attacker finds a vulnerability in one of the first lines of defence above.
#### Security of Parsedown Extensions
Safe mode does not necessarily yield safe results when using extensions to Parsedown. Extensions should be evaluated on their own to determine their specific safety against XSS.
### Escaping HTML
> ⚠️  **WARNING:** This method isn't safe from XSS!
If you wish to escape HTML **in trusted input**, you can use the following:
```php
$parsedown = new Parsedown;
$parsedown->setMarkupEscaped(true);
```
Beware that this still allows users to insert unsafe scripting vectors, such as links like `[xss](javascript:alert%281%29)`.
### Questions
**How does Parsedown work?**
It tries to read Markdown like a human. First, it looks at the lines. Its interested in how the lines start. This helps it recognise blocks. It knows, for example, that if a line starts with a `-` then perhaps it belongs to a list. Once it recognises the blocks, it continues to the content. As it reads, it watches out for special characters. This helps it recognise inline elements (or inlines).
We call this approach "line based". We believe that Parsedown is the first Markdown parser to use it. Since the release of Parsedown, other developers have used the same approach to develop other Markdown parsers in PHP and in other languages.
**Is it compliant with CommonMark?**
It passes most of the CommonMark tests. Most of the tests that don't pass deal with cases that are quite uncommon. Still, as CommonMark matures, compliance should improve.
**Who uses it?**
[Laravel Framework](https://laravel.com/), [Bolt CMS](http://bolt.cm/), [Grav CMS](http://getgrav.org/), [Herbie CMS](http://www.getherbie.org/), [Kirby CMS](http://getkirby.com/), [October CMS](http://octobercms.com/), [Pico CMS](http://picocms.org), [Statamic CMS](http://www.statamic.com/), [phpDocumentor](http://www.phpdoc.org/), [RaspberryPi.org](http://www.raspberrypi.org/), [Symfony demo](https://github.com/symfony/symfony-demo) and [more](https://packagist.org/packages/erusev/parsedown/dependents).
**How can I help?**
Use it, star it, share it and if you feel generous, [donate](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=528P3NZQMP8N2).

View File

@@ -1,33 +0,0 @@
{
"name": "erusev/parsedown",
"description": "Parser for Markdown.",
"keywords": ["markdown", "parser"],
"homepage": "http://parsedown.org",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Emanuil Rusev",
"email": "hello@erusev.com",
"homepage": "http://erusev.com"
}
],
"require": {
"php": ">=5.3.0",
"ext-mbstring": "*"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35"
},
"autoload": {
"psr-0": {"Parsedown": ""}
},
"autoload-dev": {
"psr-0": {
"TestParsedown": "test/",
"ParsedownTest": "test/",
"CommonMarkTest": "test/",
"CommonMarkTestWeak": "test/"
}
}
}

View File

@@ -1 +0,0 @@
vendor/

View File

@@ -1,147 +0,0 @@
# Changelog
All notable changes to this project will be documented in this file, in reverse chronological order by release.
## 1.1.5 - 2020-11-24
### Added
- [#19](https://github.com/php-fig/http-message-util/pull/19) adds support for PHP 8.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.
## 1.1.4 - 2020-02-05
### Added
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- [#15](https://github.com/php-fig/http-message-util/pull/15) removes the dependency on psr/http-message, as it is not technically necessary for usage of this package.
### Fixed
- Nothing.
## 1.1.3 - 2018-11-19
### Added
- [#10](https://github.com/php-fig/http-message-util/pull/10) adds the constants `StatusCodeInterface::STATUS_EARLY_HINTS` (103) and
`StatusCodeInterface::STATUS_TOO_EARLY` (425).
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.
## 1.1.2 - 2017-02-09
### Added
- [#4](https://github.com/php-fig/http-message-util/pull/4) adds the constant
`StatusCodeInterface::STATUS_MISDIRECTED_REQUEST` (421).
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.
## 1.1.1 - 2017-02-06
### Added
- [#3](https://github.com/php-fig/http-message-util/pull/3) adds the constant
`StatusCodeInterface::STATUS_IM_A_TEAPOT` (418).
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.
## 1.1.0 - 2016-09-19
### Added
- [#1](https://github.com/php-fig/http-message-util/pull/1) adds
`Fig\Http\Message\StatusCodeInterface`, with constants named after common
status reason phrases, with values indicating the status codes themselves.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.
## 1.0.0 - 2017-08-05
### Added
- Adds `Fig\Http\Message\RequestMethodInterface`, with constants covering the
most common HTTP request methods as specified by the IETF.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.

View File

@@ -1,19 +0,0 @@
Copyright (c) 2016 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.

View File

@@ -1,17 +0,0 @@
# PSR Http Message Util
This repository holds utility classes and constants to facilitate common
operations of [PSR-7](https://www.php-fig.org/psr/psr-7/); the primary purpose is
to provide constants for referring to request methods, response status codes and
messages, and potentially common headers.
Implementation of PSR-7 interfaces is **not** within the scope of this package.
## Installation
Install by adding the package as a [Composer](https://getcomposer.org)
requirement:
```bash
$ composer require fig/http-message-util
```

View File

@@ -1,28 +0,0 @@
{
"name": "fig/http-message-util",
"description": "Utility classes and constants for use with PSR-7 (psr/http-message)",
"keywords": ["psr", "psr-7", "http", "http-message", "request", "response"],
"license": "MIT",
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"require": {
"php": "^5.3 || ^7.0 || ^8.0"
},
"suggest": {
"psr/http-message": "The package containing the PSR-7 interfaces"
},
"autoload": {
"psr-4": {
"Fig\\Http\\Message\\": "src/"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.1.x-dev"
}
}
}

View File

@@ -1,34 +0,0 @@
<?php
namespace Fig\Http\Message;
/**
* Defines constants for common HTTP request methods.
*
* Usage:
*
* <code>
* class RequestFactory implements RequestMethodInterface
* {
* public static function factory(
* $uri = '/',
* $method = self::METHOD_GET,
* $data = []
* ) {
* }
* }
* </code>
*/
interface RequestMethodInterface
{
const METHOD_HEAD = 'HEAD';
const METHOD_GET = 'GET';
const METHOD_POST = 'POST';
const METHOD_PUT = 'PUT';
const METHOD_PATCH = 'PATCH';
const METHOD_DELETE = 'DELETE';
const METHOD_PURGE = 'PURGE';
const METHOD_OPTIONS = 'OPTIONS';
const METHOD_TRACE = 'TRACE';
const METHOD_CONNECT = 'CONNECT';
}

View File

@@ -1,107 +0,0 @@
<?php
namespace Fig\Http\Message;
/**
* Defines constants for common HTTP status code.
*
* @see https://tools.ietf.org/html/rfc2295#section-8.1
* @see https://tools.ietf.org/html/rfc2324#section-2.3
* @see https://tools.ietf.org/html/rfc2518#section-9.7
* @see https://tools.ietf.org/html/rfc2774#section-7
* @see https://tools.ietf.org/html/rfc3229#section-10.4
* @see https://tools.ietf.org/html/rfc4918#section-11
* @see https://tools.ietf.org/html/rfc5842#section-7.1
* @see https://tools.ietf.org/html/rfc5842#section-7.2
* @see https://tools.ietf.org/html/rfc6585#section-3
* @see https://tools.ietf.org/html/rfc6585#section-4
* @see https://tools.ietf.org/html/rfc6585#section-5
* @see https://tools.ietf.org/html/rfc6585#section-6
* @see https://tools.ietf.org/html/rfc7231#section-6
* @see https://tools.ietf.org/html/rfc7238#section-3
* @see https://tools.ietf.org/html/rfc7725#section-3
* @see https://tools.ietf.org/html/rfc7540#section-9.1.2
* @see https://tools.ietf.org/html/rfc8297#section-2
* @see https://tools.ietf.org/html/rfc8470#section-7
* Usage:
*
* <code>
* class ResponseFactory implements StatusCodeInterface
* {
* public function createResponse($code = self::STATUS_OK)
* {
* }
* }
* </code>
*/
interface StatusCodeInterface
{
// Informational 1xx
const STATUS_CONTINUE = 100;
const STATUS_SWITCHING_PROTOCOLS = 101;
const STATUS_PROCESSING = 102;
const STATUS_EARLY_HINTS = 103;
// Successful 2xx
const STATUS_OK = 200;
const STATUS_CREATED = 201;
const STATUS_ACCEPTED = 202;
const STATUS_NON_AUTHORITATIVE_INFORMATION = 203;
const STATUS_NO_CONTENT = 204;
const STATUS_RESET_CONTENT = 205;
const STATUS_PARTIAL_CONTENT = 206;
const STATUS_MULTI_STATUS = 207;
const STATUS_ALREADY_REPORTED = 208;
const STATUS_IM_USED = 226;
// Redirection 3xx
const STATUS_MULTIPLE_CHOICES = 300;
const STATUS_MOVED_PERMANENTLY = 301;
const STATUS_FOUND = 302;
const STATUS_SEE_OTHER = 303;
const STATUS_NOT_MODIFIED = 304;
const STATUS_USE_PROXY = 305;
const STATUS_RESERVED = 306;
const STATUS_TEMPORARY_REDIRECT = 307;
const STATUS_PERMANENT_REDIRECT = 308;
// Client Errors 4xx
const STATUS_BAD_REQUEST = 400;
const STATUS_UNAUTHORIZED = 401;
const STATUS_PAYMENT_REQUIRED = 402;
const STATUS_FORBIDDEN = 403;
const STATUS_NOT_FOUND = 404;
const STATUS_METHOD_NOT_ALLOWED = 405;
const STATUS_NOT_ACCEPTABLE = 406;
const STATUS_PROXY_AUTHENTICATION_REQUIRED = 407;
const STATUS_REQUEST_TIMEOUT = 408;
const STATUS_CONFLICT = 409;
const STATUS_GONE = 410;
const STATUS_LENGTH_REQUIRED = 411;
const STATUS_PRECONDITION_FAILED = 412;
const STATUS_PAYLOAD_TOO_LARGE = 413;
const STATUS_URI_TOO_LONG = 414;
const STATUS_UNSUPPORTED_MEDIA_TYPE = 415;
const STATUS_RANGE_NOT_SATISFIABLE = 416;
const STATUS_EXPECTATION_FAILED = 417;
const STATUS_IM_A_TEAPOT = 418;
const STATUS_MISDIRECTED_REQUEST = 421;
const STATUS_UNPROCESSABLE_ENTITY = 422;
const STATUS_LOCKED = 423;
const STATUS_FAILED_DEPENDENCY = 424;
const STATUS_TOO_EARLY = 425;
const STATUS_UPGRADE_REQUIRED = 426;
const STATUS_PRECONDITION_REQUIRED = 428;
const STATUS_TOO_MANY_REQUESTS = 429;
const STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE = 431;
const STATUS_UNAVAILABLE_FOR_LEGAL_REASONS = 451;
// Server Errors 5xx
const STATUS_INTERNAL_SERVER_ERROR = 500;
const STATUS_NOT_IMPLEMENTED = 501;
const STATUS_BAD_GATEWAY = 502;
const STATUS_SERVICE_UNAVAILABLE = 503;
const STATUS_GATEWAY_TIMEOUT = 504;
const STATUS_VERSION_NOT_SUPPORTED = 505;
const STATUS_VARIANT_ALSO_NEGOTIATES = 506;
const STATUS_INSUFFICIENT_STORAGE = 507;
const STATUS_LOOP_DETECTED = 508;
const STATUS_NOT_EXTENDED = 510;
const STATUS_NETWORK_AUTHENTICATION_REQUIRED = 511;
}

View File

@@ -1,5 +0,0 @@
.idea/
demo/*.jpg
demo/*.pgm
demo/temp/
vendor/

View File

@@ -1,16 +0,0 @@
language: php
php:
- 5.3.3
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- 7.1
- 7.2
- hhvm
script:
- composer install
- phpunit

View File

@@ -1,19 +0,0 @@
Copyright (c) <2012-2017> Grégoire Passault
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.

View File

@@ -1,146 +0,0 @@
Captcha
=======
![Captchas examples](http://gregwar.com/captchas.png)
[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YUXRLWHQSWS6L)
Installation
============
With composer :
``` json
{
...
"require": {
"gregwar/captcha": "1.*"
}
}
```
Usage
=====
You can create a captcha with the `CaptchaBuilder` :
```php
<?php
use Gregwar\Captcha\CaptchaBuilder;
$builder = new CaptchaBuilder;
$builder->build();
```
You can then save it to a file :
```php
<?php
$builder->save('out.jpg');
```
Or output it directly :
```php
<?php
header('Content-type: image/jpeg');
$builder->output();
```
Or inline it directly in the HTML page:
```php
<img src="<?php echo $builder->inline(); ?>" />
```
You'll be able to get the code and compare it with a user input :
```php
<?php
// Example: storing the phrase in the session to test for the user
// input later
$_SESSION['phrase'] = $builder->getPhrase();
```
You can compare the phrase with user input:
```php
if($builder->testPhrase($userInput)) {
// instructions if user phrase is good
}
else {
// user phrase is wrong
}
```
API
===
You can use theses functions :
* **__construct($phrase = null)**, constructs the builder with the given phrase, if the phrase is null, a random one will be generated
* **getPhrase()**, allow you to get the phrase contents
* **setDistortion($distortion)**, enable or disable the distortion, call it before `build()`
* **isOCRReadable()**, returns `true` if the OCR can be read using the `ocrad` software, you'll need to have shell_exec enabled, imagemagick and ocrad installed
* **buildAgainstOCR($width = 150, $height = 40, $font = null)**, builds a code until it is not readable by `ocrad`
* **build($width = 150, $height = 40, $font = null)**, builds a code with the given $width, $height and $font. By default, a random font will be used from the library
* **save($filename, $quality = 80)**, saves the captcha into a jpeg in the $filename, with the given quality
* **get($quality = 80)**, returns the jpeg data
* **output($quality = 80)**, directly outputs the jpeg code to a browser
* **setBackgroundColor($r, $g, $b)**, sets the background color to force it (this will disable many effects and is not recommended)
* **setBackgroundImages(array($imagepath1, $imagePath2))**, Sets custom background images to be used as captcha background. It is recommended to disable image effects when passing custom images for background (ignore_all_effects). A random image is selected from the list passed, the full paths to the image files must be passed.
* **setInterpolation($interpolate)**, enable or disable the interpolation (enabled by default), disabling it will be quicker but the images will look uglier
* **setIgnoreAllEffects($ignoreAllEffects)**, disable all effects on the captcha image. Recommended to use when passing custom background images for the captcha.
* **testPhrase($phrase)**, returns true if the given phrase is good
* **setMaxBehindLines($lines)**, sets the maximum number of lines behind the code
* **setMaxFrontLines($lines)**, sets the maximum number of lines on the front of the code
If you want to change the number of character, you can call the phrase builder directly using
extra parameters:
```php
use Gregwar\Captcha\CaptchaBuilder;
use Gregwar\Captcha\PhraseBuilder;
// Will build phrases of 3 characters
$phraseBuilder = new PhraseBuilder(4);
// Will build phrases of 5 characters, only digits
$phraseBuilder = new PhraseBuilder(5, '0123456789');
// Pass it as first argument of CaptchaBuilder, passing it the phrase
// builder
$captcha = new CaptchaBuilder(null, $phraseBuilder);
```
You can also pass directly the wanted phrase to the builder:
```php
// Building a Captcha with the "hello" phrase
$captcha = new CaptchaBuilder('hello');
```
Complete example
================
If you want to see an example you can have a look at the ``demo/form.php``, which uses ``demo/session.php`` to
render a captcha and check it after the submission
Symfony Bundle
================
You can have a look at the following repository to enjoy the Symfony 2 bundle packaging this captcha generator :
https://github.com/Gregwar/CaptchaBundle
Yii2 Extension
===============
You can use the following extension for integrating with Yii2 Framework :
https://github.com/juliardi/yii2-captcha
License
=======
This library is under MIT license, have a look to the `LICENSE` file

View File

@@ -1,33 +0,0 @@
{
"name": "gregwar/captcha",
"type": "library",
"description": "Captcha generator",
"keywords": ["captcha", "spam", "bot"],
"homepage": "https://github.com/Gregwar/Captcha",
"license": "MIT",
"authors": [
{
"name": "Grégoire Passault",
"email": "g.passault@gmail.com",
"homepage": "http://www.gregwar.com/"
},
{
"name": "Jeremy Livingston",
"email": "jeremy.j.livingston@gmail.com"
}
],
"require": {
"php": ">=5.3.0",
"ext-gd": "*",
"ext-mbstring": "*",
"symfony/finder": "*"
},
"autoload": {
"psr-4": {
"Gregwar\\": "src/Gregwar"
}
},
"require-dev": {
"phpunit/phpunit": "^6.4"
}
}

View File

@@ -1,11 +0,0 @@
<?php
require_once __DIR__.'/../vendor/autoload.php';
use Gregwar\Captcha\CaptchaBuilder;
$captcha = new CaptchaBuilder;
$captcha
->build()
->save('out.jpg')
;

View File

@@ -1,12 +0,0 @@
<?php
require_once __DIR__.'/../vendor/autoload.php';
use Gregwar\Captcha\CaptchaBuilder;
echo count(CaptchaBuilder::create()
->build()
->getFingerprint()
);
echo "\n";

View File

@@ -1,32 +0,0 @@
<?php
require_once __DIR__.'/../vendor/autoload.php';
use Gregwar\Captcha\PhraseBuilder;
// We need the session to check the phrase after submitting
session_start();
?>
<html>
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// Checking that the posted phrase match the phrase stored in the session
if (isset($_SESSION['phrase']) && PhraseBuilder::comparePhrases($_SESSION['phrase'], $_POST['phrase'])) {
echo "<h1>Captcha is valid !</h1>";
} else {
echo "<h1>Captcha is not valid!</h1>";
}
// The phrase can't be used twice
unset($_SESSION['phrase']);
}
?>
<form method="post">
Copy the CAPTCHA:
<?php
// See session.php, where the captcha is actually rendered and the session phrase
// is set accordingly to the image displayed
?>
<img src="session.php" />
<input type="text" name="phrase" />
<input type="submit" />
</form>
</html>

View File

@@ -1,15 +0,0 @@
<!DOCTYPE html>
<body>
<html>
<meta charset="utf-8" />
</html>
<body>
<h1>Captchas gallery</h1>
<?php for ($x=0; $x<8; $x++) { ?>
<?php for ($y=0; $y<5; $y++) { ?>
<img src="output.php?n=<?php echo 5*$x+$y; ?>" />
<?php } ?>
<br />
<?php } ?>
</body>
</body>

View File

@@ -1,22 +0,0 @@
<?php
require_once __DIR__.'/../vendor/autoload.php';
use Gregwar\Captcha\CaptchaBuilder;
$captcha = new CaptchaBuilder();
$captcha->build();
?>
<!DOCTYPE html>
<body>
<html>
<meta charset="utf-8" />
</html>
<body>
<h1>Inline Captcha</h1>
<img src="<?php echo $captcha->inline(); ?>"/><br/>
Phrase: <?php echo $captcha->getPhrase(); ?>
</body>
</body>

View File

@@ -1,39 +0,0 @@
<?php
require_once __DIR__.'/../vendor/autoload.php';
use Gregwar\Captcha\CaptchaBuilder;
/**
* Generates 1000 captchas and try to read their code with the
* ocrad OCR
*/
$tests = 10000;
$passed = 0;
shell_exec('rm passed*.jpg');
for ($i=0; $i<$tests; $i++) {
echo "Captcha $i/$tests... ";
$captcha = new CaptchaBuilder;
$captcha
->setDistortion(false)
->build()
;
if ($captcha->isOCRReadable()) {
$passed++;
$captcha->save("passed$passed.jpg");
echo "passed at ocr... ";
} else {
echo "failed... ";
}
echo "pass rate: ".round(100*$passed/($i+1),2)."%\n";
}
echo "\n";
echo "Over, $passed/$tests readed with OCR\n";

View File

@@ -1,12 +0,0 @@
<?php
require_once __DIR__.'/../vendor/autoload.php';
use Gregwar\Captcha\CaptchaBuilder;
header('Content-type: image/jpeg');
CaptchaBuilder::create()
->build()
->output()
;

View File

@@ -1,22 +0,0 @@
<?php
// We need the session to store the correct phrase for later check
session_start();
// Including the autoload (you need to composer install in the main directory)
require_once __DIR__.'/../vendor/autoload.php';
use Gregwar\Captcha\CaptchaBuilder;
// Creating the captcha instance and setting the phrase in the session to store
// it for check when the form is submitted
$captcha = new CaptchaBuilder;
$_SESSION['phrase'] = $captcha->getPhrase();
// Setting the header to image jpeg because we here render an image
header('Content-Type: image/jpeg');
// Running the actual rendering of the captcha image
$captcha
->build()
->output()
;

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true" bootstrap="vendor/autoload.php">
<testsuites>
<testsuite name="KnpMenu Test Suite">
<directory suffix="Test.php">./tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src</directory>
</whitelist>
</filter>
</phpunit>

View File

@@ -1,737 +0,0 @@
<?php
namespace Gregwar\Captcha;
use \Exception;
/**
* Builds a new captcha image
* Uses the fingerprint parameter, if one is passed, to generate the same image
*
* @author Gregwar <g.passault@gmail.com>
* @author Jeremy Livingston <jeremy.j.livingston@gmail.com>
*/
class CaptchaBuilder implements CaptchaBuilderInterface
{
/**
* @var array
*/
protected $fingerprint = array();
/**
* @var bool
*/
protected $useFingerprint = false;
/**
* @var array
*/
protected $textColor = array();
/**
* @var array
*/
protected $lineColor = null;
/**
* @var array
*/
protected $backgroundColor = null;
/**
* @var array
*/
protected $backgroundImages = array();
/**
* @var resource
*/
protected $contents = null;
/**
* @var string
*/
protected $phrase = null;
/**
* @var PhraseBuilderInterface
*/
protected $builder;
/**
* @var bool
*/
protected $distortion = true;
/**
* The maximum number of lines to draw in front of
* the image. null - use default algorithm
*/
protected $maxFrontLines = null;
/**
* The maximum number of lines to draw behind
* the image. null - use default algorithm
*/
protected $maxBehindLines = null;
/**
* The maximum angle of char
*/
protected $maxAngle = 8;
/**
* The maximum offset of char
*/
protected $maxOffset = 5;
/**
* Is the interpolation enabled ?
*
* @var bool
*/
protected $interpolation = true;
/**
* Ignore all effects
*
* @var bool
*/
protected $ignoreAllEffects = false;
/**
* Allowed image types for the background images
*
* @var array
*/
protected $allowedBackgroundImageTypes = array('image/png', 'image/jpeg', 'image/gif');
/**
* The image contents
*/
public function getContents()
{
return $this->contents;
}
/**
* Enable/Disables the interpolation
*
* @param $interpolate bool True to enable, false to disable
*
* @return CaptchaBuilder
*/
public function setInterpolation($interpolate = true)
{
$this->interpolation = $interpolate;
return $this;
}
/**
* Temporary dir, for OCR check
*/
public $tempDir = 'temp/';
public function __construct($phrase = null, PhraseBuilderInterface $builder = null)
{
if ($builder === null) {
$this->builder = new PhraseBuilder;
} else {
$this->builder = $builder;
}
$this->phrase = is_string($phrase) ? $phrase : $this->builder->build($phrase);
}
/**
* Setting the phrase
*/
public function setPhrase($phrase)
{
$this->phrase = (string) $phrase;
}
/**
* Enables/disable distortion
*/
public function setDistortion($distortion)
{
$this->distortion = (bool) $distortion;
return $this;
}
public function setMaxBehindLines($maxBehindLines)
{
$this->maxBehindLines = $maxBehindLines;
return $this;
}
public function setMaxFrontLines($maxFrontLines)
{
$this->maxFrontLines = $maxFrontLines;
return $this;
}
public function setMaxAngle($maxAngle)
{
$this->maxAngle = $maxAngle;
return $this;
}
public function setMaxOffset($maxOffset)
{
$this->maxOffset = $maxOffset;
return $this;
}
/**
* Gets the captcha phrase
*/
public function getPhrase()
{
return $this->phrase;
}
/**
* Returns true if the given phrase is good
*/
public function testPhrase($phrase)
{
return ($this->builder->niceize($phrase) == $this->builder->niceize($this->getPhrase()));
}
/**
* Instantiation
*/
public static function create($phrase = null)
{
return new self($phrase);
}
/**
* Sets the text color to use
*/
public function setTextColor($r, $g, $b)
{
$this->textColor = array($r, $g, $b);
return $this;
}
/**
* Sets the background color to use
*/
public function setBackgroundColor($r, $g, $b)
{
$this->backgroundColor = array($r, $g, $b);
return $this;
}
public function setLineColor($r, $g, $b)
{
$this->lineColor = array($r, $g, $b);
return $this;
}
/**
* Sets the ignoreAllEffects value
*
* @param bool $ignoreAllEffects
* @return CaptchaBuilder
*/
public function setIgnoreAllEffects($ignoreAllEffects)
{
$this->ignoreAllEffects = $ignoreAllEffects;
return $this;
}
/**
* Sets the list of background images to use (one image is randomly selected)
*/
public function setBackgroundImages(array $backgroundImages)
{
$this->backgroundImages = $backgroundImages;
return $this;
}
/**
* Draw lines over the image
*/
protected function drawLine($image, $width, $height, $tcol = null)
{
if ($this->lineColor === null) {
$red = $this->rand(100, 255);
$green = $this->rand(100, 255);
$blue = $this->rand(100, 255);
} else {
$red = $this->lineColor[0];
$green = $this->lineColor[1];
$blue = $this->lineColor[2];
}
if ($tcol === null) {
$tcol = imagecolorallocate($image, $red, $green, $blue);
}
if ($this->rand(0, 1)) { // Horizontal
$Xa = $this->rand(0, $width/2);
$Ya = $this->rand(0, $height);
$Xb = $this->rand($width/2, $width);
$Yb = $this->rand(0, $height);
} else { // Vertical
$Xa = $this->rand(0, $width);
$Ya = $this->rand(0, $height/2);
$Xb = $this->rand(0, $width);
$Yb = $this->rand($height/2, $height);
}
imagesetthickness($image, $this->rand(1, 3));
imageline($image, $Xa, $Ya, $Xb, $Yb, $tcol);
}
/**
* Apply some post effects
*/
protected function postEffect($image)
{
if (!function_exists('imagefilter')) {
return;
}
if ($this->backgroundColor != null || $this->textColor != null) {
return;
}
// Negate ?
if ($this->rand(0, 1) == 0) {
imagefilter($image, IMG_FILTER_NEGATE);
}
// Edge ?
if ($this->rand(0, 10) == 0) {
imagefilter($image, IMG_FILTER_EDGEDETECT);
}
// Contrast
imagefilter($image, IMG_FILTER_CONTRAST, $this->rand(-50, 10));
// Colorize
if ($this->rand(0, 5) == 0) {
imagefilter($image, IMG_FILTER_COLORIZE, $this->rand(-80, 50), $this->rand(-80, 50), $this->rand(-80, 50));
}
}
/**
* Writes the phrase on the image
*/
protected function writePhrase($image, $phrase, $font, $width, $height)
{
$length = mb_strlen($phrase);
if ($length === 0) {
return \imagecolorallocate($image, 0, 0, 0);
}
// Gets the text size and start position
$size = (int) round($width / $length) - $this->rand(0, 3) - 1;
$box = \imagettfbbox($size, 0, $font, $phrase);
$textWidth = $box[2] - $box[0];
$textHeight = $box[1] - $box[7];
$x = (int) round(($width - $textWidth) / 2);
$y = (int) round(($height - $textHeight) / 2) + $size;
if (!$this->textColor) {
$textColor = array($this->rand(0, 150), $this->rand(0, 150), $this->rand(0, 150));
} else {
$textColor = $this->textColor;
}
$col = \imagecolorallocate($image, $textColor[0], $textColor[1], $textColor[2]);
// Write the letters one by one, with random angle
for ($i=0; $i<$length; $i++) {
$symbol = mb_substr($phrase, $i, 1);
$box = \imagettfbbox($size, 0, $font, $symbol);
$w = $box[2] - $box[0];
$angle = $this->rand(-$this->maxAngle, $this->maxAngle);
$offset = $this->rand(-$this->maxOffset, $this->maxOffset);
\imagettftext($image, $size, $angle, $x, $y + $offset, $col, $font, $symbol);
$x += $w;
}
return $col;
}
/**
* Try to read the code against an OCR
*/
public function isOCRReadable()
{
if (!is_dir($this->tempDir)) {
@mkdir($this->tempDir, 0755, true);
}
$tempj = $this->tempDir . uniqid('captcha', true) . '.jpg';
$tempp = $this->tempDir . uniqid('captcha', true) . '.pgm';
$this->save($tempj);
shell_exec("convert $tempj $tempp");
$value = trim(strtolower(shell_exec("ocrad $tempp")));
@unlink($tempj);
@unlink($tempp);
return $this->testPhrase($value);
}
/**
* Builds while the code is readable against an OCR
*/
public function buildAgainstOCR($width = 150, $height = 40, $font = null, $fingerprint = null)
{
do {
$this->build($width, $height, $font, $fingerprint);
} while ($this->isOCRReadable());
}
/**
* Generate the image
*/
public function build($width = 150, $height = 40, $font = null, $fingerprint = null)
{
if (null !== $fingerprint) {
$this->fingerprint = $fingerprint;
$this->useFingerprint = true;
} else {
$this->fingerprint = array();
$this->useFingerprint = false;
}
if ($font === null) {
$font = __DIR__ . '/Font/captcha'.$this->rand(0, 5).'.ttf';
}
if (empty($this->backgroundImages)) {
// if background images list is not set, use a color fill as a background
$image = imagecreatetruecolor($width, $height);
if ($this->backgroundColor == null) {
$bg = imagecolorallocate($image, $this->rand(200, 255), $this->rand(200, 255), $this->rand(200, 255));
} else {
$color = $this->backgroundColor;
$bg = imagecolorallocate($image, $color[0], $color[1], $color[2]);
}
imagefill($image, 0, 0, $bg);
} else {
// use a random background image
$randomBackgroundImage = $this->backgroundImages[rand(0, count($this->backgroundImages)-1)];
$imageType = $this->validateBackgroundImage($randomBackgroundImage);
$image = $this->createBackgroundImageFromType($randomBackgroundImage, $imageType);
}
// Apply effects
if (!$this->ignoreAllEffects) {
$square = $width * $height;
$effects = $this->rand($square/3000, $square/2000);
// set the maximum number of lines to draw in front of the text
if ($this->maxBehindLines != null && $this->maxBehindLines > 0) {
$effects = min($this->maxBehindLines, $effects);
}
if ($this->maxBehindLines !== 0) {
for ($e = 0; $e < $effects; $e++) {
$this->drawLine($image, $width, $height);
}
}
}
// Write CAPTCHA text
$color = $this->writePhrase($image, $this->phrase, $font, $width, $height);
// Apply effects
if (!$this->ignoreAllEffects) {
$square = $width * $height;
$effects = $this->rand($square/3000, $square/2000);
// set the maximum number of lines to draw in front of the text
if ($this->maxFrontLines != null && $this->maxFrontLines > 0) {
$effects = min($this->maxFrontLines, $effects);
}
if ($this->maxFrontLines !== 0) {
for ($e = 0; $e < $effects; $e++) {
$this->drawLine($image, $width, $height, $color);
}
}
}
// Distort the image
if ($this->distortion && !$this->ignoreAllEffects) {
$image = $this->distort($image, $width, $height, $bg);
}
// Post effects
if (!$this->ignoreAllEffects) {
$this->postEffect($image);
}
$this->contents = $image;
return $this;
}
/**
* Distorts the image
*/
public function distort($image, $width, $height, $bg)
{
$contents = imagecreatetruecolor($width, $height);
$X = $this->rand(0, $width);
$Y = $this->rand(0, $height);
$phase = $this->rand(0, 10);
$scale = 1.1 + $this->rand(0, 10000) / 30000;
for ($x = 0; $x < $width; $x++) {
for ($y = 0; $y < $height; $y++) {
$Vx = $x - $X;
$Vy = $y - $Y;
$Vn = sqrt($Vx * $Vx + $Vy * $Vy);
if ($Vn != 0) {
$Vn2 = $Vn + 4 * sin($Vn / 30);
$nX = $X + ($Vx * $Vn2 / $Vn);
$nY = $Y + ($Vy * $Vn2 / $Vn);
} else {
$nX = $X;
$nY = $Y;
}
$nY = $nY + $scale * sin($phase + $nX * 0.2);
if ($this->interpolation) {
$p = $this->interpolate(
$nX - floor($nX),
$nY - floor($nY),
$this->getCol($image, floor($nX), floor($nY), $bg),
$this->getCol($image, ceil($nX), floor($nY), $bg),
$this->getCol($image, floor($nX), ceil($nY), $bg),
$this->getCol($image, ceil($nX), ceil($nY), $bg)
);
} else {
$p = $this->getCol($image, round($nX), round($nY), $bg);
}
if ($p == 0) {
$p = $bg;
}
imagesetpixel($contents, $x, $y, $p);
}
}
return $contents;
}
/**
* Saves the Captcha to a jpeg file
*/
public function save($filename, $quality = 90)
{
imagejpeg($this->contents, $filename, $quality);
}
/**
* Gets the image GD
*/
public function getGd()
{
return $this->contents;
}
/**
* Gets the image contents
*/
public function get($quality = 90)
{
ob_start();
$this->output($quality);
return ob_get_clean();
}
/**
* Gets the HTML inline base64
*/
public function inline($quality = 90)
{
return 'data:image/jpeg;base64,' . base64_encode($this->get($quality));
}
/**
* Outputs the image
*/
public function output($quality = 90)
{
imagejpeg($this->contents, null, $quality);
}
/**
* @return array
*/
public function getFingerprint()
{
return $this->fingerprint;
}
/**
* Returns a random number or the next number in the
* fingerprint
*/
protected function rand($min, $max)
{
if (!is_array($this->fingerprint)) {
$this->fingerprint = array();
}
if ($this->useFingerprint) {
$value = current($this->fingerprint);
next($this->fingerprint);
} else {
$value = mt_rand((int)$min, (int)$max);
$this->fingerprint[] = $value;
}
return $value;
}
/**
* @param $x
* @param $y
* @param $nw
* @param $ne
* @param $sw
* @param $se
*
* @return int
*/
protected function interpolate($x, $y, $nw, $ne, $sw, $se)
{
list($r0, $g0, $b0) = $this->getRGB($nw);
list($r1, $g1, $b1) = $this->getRGB($ne);
list($r2, $g2, $b2) = $this->getRGB($sw);
list($r3, $g3, $b3) = $this->getRGB($se);
$cx = 1.0 - $x;
$cy = 1.0 - $y;
$m0 = $cx * $r0 + $x * $r1;
$m1 = $cx * $r2 + $x * $r3;
$r = (int) ($cy * $m0 + $y * $m1);
$m0 = $cx * $g0 + $x * $g1;
$m1 = $cx * $g2 + $x * $g3;
$g = (int) ($cy * $m0 + $y * $m1);
$m0 = $cx * $b0 + $x * $b1;
$m1 = $cx * $b2 + $x * $b3;
$b = (int) ($cy * $m0 + $y * $m1);
return ($r << 16) | ($g << 8) | $b;
}
/**
* @param $image
* @param $x
* @param $y
*
* @return int
*/
protected function getCol($image, $x, $y, $background)
{
$L = imagesx($image);
$H = imagesy($image);
if ($x < 0 || $x >= $L || $y < 0 || $y >= $H) {
return $background;
}
return imagecolorat($image, $x, $y);
}
/**
* @param $col
*
* @return array
*/
protected function getRGB($col)
{
return array(
(int) ($col >> 16) & 0xff,
(int) ($col >> 8) & 0xff,
(int) ($col) & 0xff,
);
}
/**
* Validate the background image path. Return the image type if valid
*
* @param string $backgroundImage
* @return string
* @throws Exception
*/
protected function validateBackgroundImage($backgroundImage)
{
// check if file exists
if (!file_exists($backgroundImage)) {
$backgroundImageExploded = explode('/', $backgroundImage);
$imageFileName = count($backgroundImageExploded) > 1? $backgroundImageExploded[count($backgroundImageExploded)-1] : $backgroundImage;
throw new Exception('Invalid background image: ' . $imageFileName);
}
// check image type
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
$imageType = finfo_file($finfo, $backgroundImage);
finfo_close($finfo);
if (!in_array($imageType, $this->allowedBackgroundImageTypes)) {
throw new Exception('Invalid background image type! Allowed types are: ' . join(', ', $this->allowedBackgroundImageTypes));
}
return $imageType;
}
/**
* Create background image from type
*
* @param string $backgroundImage
* @param string $imageType
* @return resource
* @throws Exception
*/
protected function createBackgroundImageFromType($backgroundImage, $imageType)
{
switch ($imageType) {
case 'image/jpeg':
$image = imagecreatefromjpeg($backgroundImage);
break;
case 'image/png':
$image = imagecreatefrompng($backgroundImage);
break;
case 'image/gif':
$image = imagecreatefromgif($backgroundImage);
break;
default:
throw new Exception('Not supported file type for background image!');
}
return $image;
}
}

View File

@@ -1,29 +0,0 @@
<?php
namespace Gregwar\Captcha;
/**
* A Captcha builder
*/
interface CaptchaBuilderInterface
{
/**
* Builds the code
*/
public function build($width, $height, $font, $fingerprint);
/**
* Saves the code to a file
*/
public function save($filename, $quality);
/**
* Gets the image contents
*/
public function get($quality);
/**
* Outputs the image
*/
public function output($quality);
}

View File

@@ -1,105 +0,0 @@
<?php
namespace Gregwar\Captcha;
use Symfony\Component\Finder\Finder;
/**
* Handles actions related to captcha image files including saving and garbage collection
*
* @author Gregwar <g.passault@gmail.com>
* @author Jeremy Livingston <jeremy@quizzle.com>
*/
class ImageFileHandler
{
/**
* Name of folder for captcha images
* @var string
*/
protected $imageFolder;
/**
* Absolute path to public web folder
* @var string
*/
protected $webPath;
/**
* Frequency of garbage collection in fractions of 1
* @var int
*/
protected $gcFreq;
/**
* Maximum age of images in minutes
* @var int
*/
protected $expiration;
/**
* @param $imageFolder
* @param $webPath
* @param $gcFreq
* @param $expiration
*/
public function __construct($imageFolder, $webPath, $gcFreq, $expiration)
{
$this->imageFolder = $imageFolder;
$this->webPath = $webPath;
$this->gcFreq = $gcFreq;
$this->expiration = $expiration;
}
/**
* Saves the provided image content as a file
*
* @param string $contents
*
* @return string
*/
public function saveAsFile($contents)
{
$this->createFolderIfMissing();
$filename = md5(uniqid()) . '.jpg';
$filePath = $this->webPath . '/' . $this->imageFolder . '/' . $filename;
imagejpeg($contents, $filePath, 15);
return '/' . $this->imageFolder . '/' . $filename;
}
/**
* Randomly runs garbage collection on the image directory
*
* @return bool
*/
public function collectGarbage()
{
if (!mt_rand(1, $this->gcFreq) == 1) {
return false;
}
$this->createFolderIfMissing();
$finder = new Finder();
$criteria = sprintf('<= now - %s minutes', $this->expiration);
$finder->in($this->webPath . '/' . $this->imageFolder)
->date($criteria);
foreach ($finder->files() as $file) {
unlink($file->getPathname());
}
return true;
}
/**
* Creates the folder if it doesn't exist
*/
protected function createFolderIfMissing()
{
if (!file_exists($this->webPath . '/' . $this->imageFolder)) {
mkdir($this->webPath . '/' . $this->imageFolder, 0755);
}
}
}

View File

@@ -1,75 +0,0 @@
<?php
namespace Gregwar\Captcha;
/**
* Generates random phrase
*
* @author Gregwar <g.passault@gmail.com>
*/
class PhraseBuilder implements PhraseBuilderInterface
{
/**
* @var int
*/
public $length;
/**
* @var string
*/
public $charset;
/**
* Constructs a PhraseBuilder with given parameters
*/
public function __construct($length = 5, $charset = 'abcdefghijklmnpqrstuvwxyz123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ')
{
$this->length = $length;
$this->charset = $charset;
}
/**
* Generates random phrase of given length with given charset
*/
public function build($length = null, $charset = null)
{
if ($length !== null) {
$this->length = $length;
}
if ($charset !== null) {
$this->charset = $charset;
}
$phrase = '';
$chars = str_split($this->charset);
for ($i = 0; $i < $this->length; $i++) {
$phrase .= $chars[array_rand($chars)];
}
return $phrase;
}
/**
* "Niceize" a code
*/
public function niceize($str)
{
return self::doNiceize($str);
}
/**
* A static helper to niceize
*/
public static function doNiceize($str)
{
return strtr(strtolower($str), '01', 'ol');
}
/**
* A static helper to compare
*/
public static function comparePhrases($str1, $str2)
{
return self::doNiceize($str1) === self::doNiceize($str2);
}
}

View File

@@ -1,21 +0,0 @@
<?php
namespace Gregwar\Captcha;
/**
* Interface for the PhraseBuilder
*
* @author Gregwar <g.passault@gmail.com>
*/
interface PhraseBuilderInterface
{
/**
* Generates random phrase of given length with given charset
*/
public function build();
/**
* "Niceize" a code
*/
public function niceize($str);
}

View File

@@ -1,30 +0,0 @@
<?php
namespace Test;
use Gregwar\Captcha\CaptchaBuilder;
use PHPUnit\Framework\TestCase;
class CaptchaBuilderTest extends TestCase
{
public function testDemo()
{
$captcha = new CaptchaBuilder();
$captcha
->build()
->save('out.jpg')
;
$this->assertTrue(file_exists(__DIR__.'/../out.jpg'));
}
public function testFingerPrint()
{
$int = count(CaptchaBuilder::create()
->build()
->getFingerprint()
);
$this->assertTrue(is_int($int));
}
}

View File

@@ -1,4 +0,0 @@
vendor
composer.phar
composer.lock
.idea

View File

@@ -1,16 +0,0 @@
language: php
php:
- 5.4
- 5.5
- 5.6
- 7.0
- 7.1
- 7.2
- 7.3
before_script:
- composer install --no-interaction --prefer-source
script:
- vendor/bin/phpunit --coverage-text --verbose

View File

@@ -1,13 +0,0 @@
To install URLify, you can add it as a dependency by downloading Composer, the PHP package manager.
`$ curl -s http://getcomposer.org/installer | php`
Then run this command to install Composer:
`$ php composer.phar install`
For more details, see https://getcomposer.org/
Then run this command to install the URLify library:
`$ composer require jbroadway/urlify`

View File

@@ -1,27 +0,0 @@
Copyright (c) Django Software Foundation and individual contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of Django 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.

View File

@@ -1,90 +0,0 @@
# URLify for PHP [![Build Status](https://travis-ci.org/jbroadway/urlify.png)](https://travis-ci.org/jbroadway/urlify)
A PHP port of [URLify.js](https://github.com/django/django/blob/master/django/contrib/admin/static/admin/js/urlify.js)
from the Django project. Handles symbols from Latin languages as well as Arabic, Azerbaijani, Czech, German, Greek, Kazakh,
Latvian, Lithuanian, Persian, Polish, Romanian, Bulgarian, Russian, Serbian, Turkish, Ukrainian, Vietnamese and Slovak. Symbols it cannot
transliterate it will simply omit.
## Installation
Install the latest version with:
```bash
$ composer require jbroadway/urlify
```
## Usage
To generate slugs for URLs:
```php
<?php
echo URLify::filter (' J\'étudie le français ');
// "jetudie-le-francais"
echo URLify::filter ('Lo siento, no hablo español.');
// "lo-siento-no-hablo-espanol"
```
To generate slugs for file names:
```php
<?php
echo URLify::filter ('фото.jpg', 60, "", true);
// "foto.jpg"
```
To simply transliterate characters:
```php
<?php
echo URLify::downcode ('J\'étudie le français');
// "J'etudie le francais"
echo URLify::downcode ('Lo siento, no hablo español.');
// "Lo siento, no hablo espanol."
/* Or use transliterate() alias: */
echo URLify::transliterate ('Lo siento, no hablo español.');
// "Lo siento, no hablo espanol."
```
To extend the character list:
```php
<?php
URLify::add_chars ([
'¿' => '?', '®' => '(r)', '¼' => '1/4',
'½' => '1/2', '¾' => '3/4', '¶' => 'P'
]);
echo URLify::downcode ('¿ ® ¼ ¼ ¾ ¶');
// "? (r) 1/2 1/2 3/4 P"
```
To extend the list of words to remove:
```php
<?php
URLify::remove_words (['remove', 'these', 'too']);
```
To prioritize a certain language map:
```php
<?php
echo URLify::filter ('Ägypten und Österreich besitzen wie üblich ein Übermaß an ähnlich öligen Attachés', 60, 'de');
// "aegypten-und-oesterreich-besitzen-wie-ueblich-ein-uebermass-aehnlich-oeligen-attaches"
echo URLify::filter ('Cağaloğlu, çalıştığı, müjde, lazım, mahkûm', 60, 'tr');
// "cagaloglu-calistigi-mujde-lazim-mahkum"
```
Please note that the "ü" is transliterated to "ue" in the first case, whereas it results in a simple "u" in the latter.

View File

@@ -1,300 +0,0 @@
<?php
/**
* A PHP port of URLify.js from the Django project
* (https://github.com/django/django/blob/master/django/contrib/admin/static/admin/js/urlify.js).
* Handles symbols from Latin languages, Greek, Turkish, Bulgarian, Russian,
* Ukrainian, Czech, Polish, Romanian, Latvian, Lithuanian, Vietnamese, Arabic,
* Serbian, Azerbaijani, Kazakh and Slovak. Symbols it cannot transliterate
* it will simply omit.
*
* Usage:
*
* echo URLify::filter (' J\'étudie le français ');
* // "jetudie-le-francais"
*
* echo URLify::filter ('Lo siento, no hablo español.');
* // "lo-siento-no-hablo-espanol"
*/
class URLify
{
public static $maps = array (
'de' => array ( /* German */
'Ä' => 'Ae', 'Ö' => 'Oe', 'Ü' => 'Ue', 'ä' => 'ae', 'ö' => 'oe', 'ü' => 'ue', 'ß' => 'ss',
'ẞ' => 'SS'
),
'latin' => array (
'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Å' => 'A','Ă' => 'A', 'Æ' => 'AE', 'Ç' =>
'C', 'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I',
'Ï' => 'I', 'Ð' => 'D', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ö' =>
'O', 'Ő' => 'O', 'Ø' => 'O', 'Œ' => 'OE' ,'Ș' => 'S','Ț' => 'T', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U', 'Ű' => 'U',
'Ý' => 'Y', 'Þ' => 'TH', 'ß' => 'ss', 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' =>
'a', 'å' => 'a', 'ă' => 'a', 'æ' => 'ae', 'ç' => 'c', 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e',
'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', 'ð' => 'd', 'ñ' => 'n', 'ò' => 'o', 'ó' =>
'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ő' => 'o', 'ø' => 'o', 'œ' => 'oe', 'ș' => 's', 'ț' => 't', 'ù' => 'u', 'ú' => 'u',
'û' => 'u', 'ü' => 'u', 'ű' => 'u', 'ý' => 'y', 'þ' => 'th', 'ÿ' => 'y'
),
'latin_symbols' => array (
'©' => '(c)'
),
'el' => array ( /* Greek */
'α' => 'a', 'β' => 'b', 'γ' => 'g', 'δ' => 'd', 'ε' => 'e', 'ζ' => 'z', 'η' => 'h', 'θ' => '8',
'ι' => 'i', 'κ' => 'k', 'λ' => 'l', 'μ' => 'm', 'ν' => 'n', 'ξ' => '3', 'ο' => 'o', 'π' => 'p',
'ρ' => 'r', 'σ' => 's', 'τ' => 't', 'υ' => 'y', 'φ' => 'f', 'χ' => 'x', 'ψ' => 'ps', 'ω' => 'w',
'ά' => 'a', 'έ' => 'e', 'ί' => 'i', 'ό' => 'o', 'ύ' => 'y', 'ή' => 'h', 'ώ' => 'w', 'ς' => 's',
'ϊ' => 'i', 'ΰ' => 'y', 'ϋ' => 'y', 'ΐ' => 'i',
'Α' => 'A', 'Β' => 'B', 'Γ' => 'G', 'Δ' => 'D', 'Ε' => 'E', 'Ζ' => 'Z', 'Η' => 'H', 'Θ' => '8',
'Ι' => 'I', 'Κ' => 'K', 'Λ' => 'L', 'Μ' => 'M', 'Ν' => 'N', 'Ξ' => '3', 'Ο' => 'O', 'Π' => 'P',
'Ρ' => 'R', 'Σ' => 'S', 'Τ' => 'T', 'Υ' => 'Y', 'Φ' => 'F', 'Χ' => 'X', 'Ψ' => 'PS', 'Ω' => 'W',
'Ά' => 'A', 'Έ' => 'E', 'Ί' => 'I', 'Ό' => 'O', 'Ύ' => 'Y', 'Ή' => 'H', 'Ώ' => 'W', 'Ϊ' => 'I',
'Ϋ' => 'Y'
),
'tr' => array ( /* Turkish */
'ş' => 's', 'Ş' => 'S', 'ı' => 'i', 'İ' => 'I', 'ç' => 'c', 'Ç' => 'C', 'ü' => 'u', 'Ü' => 'U',
'ö' => 'o', 'Ö' => 'O', 'ğ' => 'g', 'Ğ' => 'G'
),
'bg' => array( /* Bulgarian */
'Щ' => 'Sht', 'Ш' => 'Sh', 'Ч' => 'Ch', 'Ц' => 'C', 'Ю' => 'Yu', 'Я' => 'Ya',
'Ж' => 'J', 'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D',
'Е' => 'E', 'З' => 'Z', 'И' => 'I', 'Й' => 'Y', 'К' => 'K', 'Л' => 'L',
'М' => 'M', 'Н' => 'N', 'О' => 'O', 'П' => 'P', 'Р' => 'R', 'С' => 'S',
'Т' => 'T', 'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ь' => '', 'Ъ' => 'A',
'щ' => 'sht', 'ш' => 'sh', 'ч' => 'ch', 'ц' => 'c', 'ю' => 'yu', 'я' => 'ya',
'ж' => 'j', 'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd',
'е' => 'e', 'з' => 'z', 'и' => 'i', 'й' => 'y', 'к' => 'k', 'л' => 'l',
'м' => 'm', 'н' => 'n', 'о' => 'o', 'п' => 'p', 'р' => 'r', 'с' => 's',
'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ь' => '', 'ъ' => 'a'
),
'ru' => array ( /* Russian */
'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e', 'ё' => 'yo', 'ж' => 'zh',
'з' => 'z', 'и' => 'i', 'й' => 'i', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o',
'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c',
'ч' => 'ch', 'ш' => 'sh', 'щ' => 'sh', 'ъ' => '', 'ы' => 'y', 'ь' => '', 'э' => 'e', 'ю' => 'yu',
'я' => 'ya',
'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D', 'Е' => 'E', 'Ё' => 'Yo', 'Ж' => 'Zh',
'З' => 'Z', 'И' => 'I', 'Й' => 'I', 'К' => 'K', 'Л' => 'L', 'М' => 'M', 'Н' => 'N', 'О' => 'O',
'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Т' => 'T', 'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'C',
'Ч' => 'Ch', 'Ш' => 'Sh', 'Щ' => 'Sh', 'Ъ' => '', 'Ы' => 'Y', 'Ь' => '', 'Э' => 'E', 'Ю' => 'Yu',
'Я' => 'Ya',
'№' => ''
),
'uk' => array ( /* Ukrainian */
'Є' => 'Ye', 'І' => 'I', 'Ї' => 'Yi', 'Ґ' => 'G', 'є' => 'ye', 'і' => 'i', 'ї' => 'yi', 'ґ' => 'g'
),
'kk' => array ( /* Kazakh */
'Ә' => 'A', 'Ғ' => 'G', 'Қ' => 'Q', 'Ң' => 'N', 'Ө' => 'O', 'Ұ' => 'U', 'Ү' => 'U', 'Һ' => 'H',
'ә' => 'a', 'ғ' => 'g', 'қ' => 'q', 'ң' => 'n', 'ө' => 'o', 'ұ' => 'u', 'ү' => 'u', 'һ' => 'h',
),
'cs' => array ( /* Czech */
'č' => 'c', 'ď' => 'd', 'ě' => 'e', 'ň' => 'n', 'ř' => 'r', 'š' => 's', 'ť' => 't', 'ů' => 'u',
'ž' => 'z', 'Č' => 'C', 'Ď' => 'D', 'Ě' => 'E', 'Ň' => 'N', 'Ř' => 'R', 'Š' => 'S', 'Ť' => 'T',
'Ů' => 'U', 'Ž' => 'Z'
),
'pl' => array ( /* Polish */
'ą' => 'a', 'ć' => 'c', 'ę' => 'e', 'ł' => 'l', 'ń' => 'n', 'ó' => 'o', 'ś' => 's', 'ź' => 'z',
'ż' => 'z', 'Ą' => 'A', 'Ć' => 'C', 'Ę' => 'e', 'Ł' => 'L', 'Ń' => 'N', 'Ó' => 'O', 'Ś' => 'S',
'Ź' => 'Z', 'Ż' => 'Z'
),
'ro' => array ( /* Romanian */
'ă' => 'a', 'â' => 'a', 'î' => 'i', 'ș' => 's', 'ț' => 't', 'Ţ' => 'T', 'ţ' => 't'
),
'lv' => array ( /* Latvian */
'ā' => 'a', 'č' => 'c', 'ē' => 'e', 'ģ' => 'g', 'ī' => 'i', 'ķ' => 'k', 'ļ' => 'l', 'ņ' => 'n',
'š' => 's', 'ū' => 'u', 'ž' => 'z', 'Ā' => 'A', 'Č' => 'C', 'Ē' => 'E', 'Ģ' => 'G', 'Ī' => 'i',
'Ķ' => 'k', 'Ļ' => 'L', 'Ņ' => 'N', 'Š' => 'S', 'Ū' => 'u', 'Ž' => 'Z'
),
'lt' => array ( /* Lithuanian */
'ą' => 'a', 'č' => 'c', 'ę' => 'e', 'ė' => 'e', 'į' => 'i', 'š' => 's', 'ų' => 'u', 'ū' => 'u', 'ž' => 'z',
'Ą' => 'A', 'Č' => 'C', 'Ę' => 'E', 'Ė' => 'E', 'Į' => 'I', 'Š' => 'S', 'Ų' => 'U', 'Ū' => 'U', 'Ž' => 'Z'
),
'vi' => array ( /* Vietnamese */
'Á' => 'A', 'À' => 'A', 'Ả' => 'A', 'Ã' => 'A', 'Ạ' => 'A', 'Ă' => 'A', 'Ắ' => 'A', 'Ằ' => 'A', 'Ẳ' => 'A', 'Ẵ' => 'A', 'Ặ' => 'A', 'Â' => 'A', 'Ấ' => 'A', 'Ầ' => 'A', 'Ẩ' => 'A', 'Ẫ' => 'A', 'Ậ' => 'A',
'á' => 'a', 'à' => 'a', 'ả' => 'a', 'ã' => 'a', 'ạ' => 'a', 'ă' => 'a', 'ắ' => 'a', 'ằ' => 'a', 'ẳ' => 'a', 'ẵ' => 'a', 'ặ' => 'a', 'â' => 'a', 'ấ' => 'a', 'ầ' => 'a', 'ẩ' => 'a', 'ẫ' => 'a', 'ậ' => 'a',
'É' => 'E', 'È' => 'E', 'Ẻ' => 'E', 'Ẽ' => 'E', 'Ẹ' => 'E', 'Ê' => 'E', 'Ế' => 'E', 'Ề' => 'E', 'Ể' => 'E', 'Ễ' => 'E', 'Ệ' => 'E',
'é' => 'e', 'è' => 'e', 'ẻ' => 'e', 'ẽ' => 'e', 'ẹ' => 'e', 'ê' => 'e', 'ế' => 'e', 'ề' => 'e', 'ể' => 'e', 'ễ' => 'e', 'ệ' => 'e',
'Í' => 'I', 'Ì' => 'I', 'Ỉ' => 'I', 'Ĩ' => 'I', 'Ị' => 'I', 'í' => 'i', 'ì' => 'i', 'ỉ' => 'i', 'ĩ' => 'i', 'ị' => 'i',
'Ó' => 'O', 'Ò' => 'O', 'Ỏ' => 'O', 'Õ' => 'O', 'Ọ' => 'O', 'Ô' => 'O', 'Ố' => 'O', 'Ồ' => 'O', 'Ổ' => 'O', 'Ỗ' => 'O', 'Ộ' => 'O', 'Ơ' => 'O', 'Ớ' => 'O', 'Ờ' => 'O', 'Ở' => 'O', 'Ỡ' => 'O', 'Ợ' => 'O',
'ó' => 'o', 'ò' => 'o', 'ỏ' => 'o', 'õ' => 'o', 'ọ' => 'o', 'ô' => 'o', 'ố' => 'o', 'ồ' => 'o', 'ổ' => 'o', 'ỗ' => 'o', 'ộ' => 'o', 'ơ' => 'o', 'ớ' => 'o', 'ờ' => 'o', 'ở' => 'o', 'ỡ' => 'o', 'ợ' => 'o',
'Ú' => 'U', 'Ù' => 'U', 'Ủ' => 'U', 'Ũ' => 'U', 'Ụ' => 'U', 'Ư' => 'U', 'Ứ' => 'U', 'Ừ' => 'U', 'Ử' => 'U', 'Ữ' => 'U', 'Ự' => 'U',
'ú' => 'u', 'ù' => 'u', 'ủ' => 'u', 'ũ' => 'u', 'ụ' => 'u', 'ư' => 'u', 'ứ' => 'u', 'ừ' => 'u', 'ử' => 'u', 'ữ' => 'u', 'ự' => 'u',
'Ý' => 'Y', 'Ỳ' => 'Y', 'Ỷ' => 'Y', 'Ỹ' => 'Y', 'Ỵ' => 'Y', 'ý' => 'y', 'ỳ' => 'y', 'ỷ' => 'y', 'ỹ' => 'y', 'ỵ' => 'y',
'Đ' => 'D', 'đ' => 'd'
),
'ar' => array ( /* Arabic */
'أ' => 'a', 'ب' => 'b', 'ت' => 't', 'ث' => 'th', 'ج' => 'g', 'ح' => 'h', 'خ' => 'kh', 'د' => 'd',
'ذ' => 'th', 'ر' => 'r', 'ز' => 'z', 'س' => 's', 'ش' => 'sh', 'ص' => 's', 'ض' => 'd', 'ط' => 't',
'ظ' => 'th', 'ع' => 'aa', 'غ' => 'gh', 'ف' => 'f', 'ق' => 'k', 'ك' => 'k', 'ل' => 'l', 'م' => 'm',
'ن' => 'n', 'ه' => 'h', 'و' => 'o', 'ي' => 'y',
'ا' => 'a', 'إ' => 'a', 'آ' => 'a', 'ؤ' => 'o', 'ئ' => 'y', 'ء' => 'aa',
'٠' => '0', '١' => '1', '٢' => '2', '٣' => '3', '٤' => '4', '٥' => '5', '٦' => '6', '٧' => '7', '٨' => '8', '٩' => '9',
),
'fa' => array ( /* Persian */
'گ' => 'g', 'ژ' => 'j', 'پ' => 'p', 'چ' => 'ch', 'ی' => 'y', 'ک' => 'k',
'۰' => '0', '۱' => '1', '۲' => '2', '۳' => '3', '۴' => '4', '۵' => '5', '۶' => '6', '۷' => '7', '۸' => '8', '۹' => '9',
),
'sr' => array ( /* Serbian */
'ђ' => 'dj', 'ј' => 'j', 'љ' => 'lj', 'њ' => 'nj', 'ћ' => 'c', 'џ' => 'dz', 'đ' => 'dj',
'Ђ' => 'Dj', 'Ј' => 'j', 'Љ' => 'Lj', 'Њ' => 'Nj', 'Ћ' => 'C', 'Џ' => 'Dz', 'Đ' => 'Dj'
),
'az' => array ( /* Azerbaijani */
'ç' => 'c', 'ə' => 'e', 'ğ' => 'g', 'ı' => 'i', 'ö' => 'o', 'ş' => 's', 'ü' => 'u',
'Ç' => 'C', 'Ə' => 'E', 'Ğ' => 'G', 'İ' => 'I', 'Ö' => 'O', 'Ş' => 'S', 'Ü' => 'U'
),
'sk' => array ( /* Slovak */
'ĺ' => 'l', 'ľ' => 'l', 'ŕ' => 'r'
)
);
/**
* List of words to remove from URLs.
*/
public static $remove_list = array (
'a', 'an', 'as', 'at', 'before', 'but', 'by', 'for', 'from',
'is', 'in', 'into', 'like', 'of', 'off', 'on', 'onto', 'per',
'since', 'than', 'the', 'this', 'that', 'to', 'up', 'via',
'with'
);
/**
* The character map.
*/
private static $map = array ();
/**
* The character list as a string.
*/
private static $chars = '';
/**
* The character list as a regular expression.
*/
private static $regex = '';
/**
* The current language
*/
private static $language = '';
/**
* Initializes the character map.
* @param string $language
*/
private static function init ($language = "")
{
if (count (self::$map) > 0 && (($language == "") || ($language == self::$language))) {
return;
}
/* Is a specific map associated with $language ? */
if (isset(self::$maps[$language]) && is_array(self::$maps[$language])) {
/* Move this map to end. This means it will have priority over others */
$m = self::$maps[$language];
unset(self::$maps[$language]);
self::$maps[$language] = $m;
}
/* Reset static vars */
self::$language = $language;
self::$map = array();
self::$chars = '';
foreach (self::$maps as $map) {
foreach ($map as $orig => $conv) {
self::$map[$orig] = $conv;
self::$chars .= $orig;
}
}
self::$regex = '/[' . preg_quote(self::$chars, '/') . ']/u';
}
/**
* Add new characters to the list. `$map` should be a hash.
* @param array $map
*/
public static function add_chars ($map)
{
if (! is_array ($map)) {
throw new LogicException ('$map must be an associative array.');
}
self::$maps[] = $map;
self::$map = array ();
self::$chars = '';
}
/**
* Append words to the remove list. Accepts either single words
* or an array of words.
* @param mixed $words
*/
public static function remove_words ($words)
{
$words = is_array ($words) ? $words : array ($words);
self::$remove_list = array_unique (array_merge (self::$remove_list, $words));
}
/**
* Transliterates characters to their ASCII equivalents.
* $language specifies a priority for a specific language.
* The latter is useful if languages have different rules for the same character.
* @param string $text
* @param string $language
* @return string
*/
public static function downcode ($text, $language = "")
{
self::init ($language);
if (preg_match_all (self::$regex, $text, $matches)) {
for ($i = 0; $i < count ($matches[0]); $i++) {
$char = $matches[0][$i];
if (isset (self::$map[$char])) {
$text = str_replace ($char, self::$map[$char], $text);
}
}
}
return $text;
}
/**
* Filters a string, e.g., "Petty theft" to "petty-theft"
* @param string $text The text to return filtered
* @param int $length The length (after filtering) of the string to be returned
* @param string $language The transliteration language, passed down to downcode()
* @param bool $file_name Whether there should be and additional filter considering this is a filename
* @param bool $use_remove_list Whether you want to remove specific elements previously set in self::$remove_list
* @param bool $lower_case Whether you want the filter to maintain casing or lowercase everything (default)
* @param bool $treat_underscore_as_space Treat underscore as space, so it will replaced with "-"
* @return string
*/
public static function filter ($text, $length = 60, $language = "", $file_name = false, $use_remove_list = true, $lower_case = true, $treat_underscore_as_space = true)
{
$text = self::downcode ($text,$language);
if ($use_remove_list) {
// remove all these words from the string before urlifying
$text = preg_replace ('/\b(' . join ('|', self::$remove_list) . ')\b/i', '', $text);
}
// if downcode doesn't hit, the char will be stripped here
$remove_pattern = ($file_name) ? '/[^_\-.\-a-zA-Z0-9\s]/u' : '/[^\s_\-a-zA-Z0-9]/u';
$text = preg_replace ($remove_pattern, '', $text); // remove unneeded chars
if ($treat_underscore_as_space) {
$text = str_replace ('_', ' ', $text); // treat underscores as spaces
}
$text = preg_replace ('/^\s+|\s+$/u', '', $text); // trim leading/trailing spaces
$text = preg_replace ('/[-\s]+/u', '-', $text); // convert spaces to hyphens
if ($lower_case) {
$text = strtolower ($text); // convert to lowercase
}
return trim (substr ($text, 0, $length), '-'); // trim to first $length chars
}
/**
* Alias of `URLify::downcode()`.
*/
public static function transliterate ($text)
{
return self::downcode ($text);
}
}

View File

@@ -1,29 +0,0 @@
{
"name": "jbroadway/urlify",
"type": "library",
"description": "PHP port of URLify.js from the Django project. Transliterates non-ascii characters for use in URLs.",
"keywords": ["urlify","transliterate","translit","transliteration","url","encode","slug","link","iconv"],
"homepage": "https://github.com/jbroadway/urlify",
"license": "BSD-3-Clause-Clear",
"authors": [
{
"name": "Johnny Broadway",
"email": "johnny@johnnybroadway.com",
"homepage": "http://www.johnnybroadway.com/"
}
],
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5"
},
"autoload": {
"psr-0": { "URLify": "" }
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
}
}

View File

@@ -1,8 +0,0 @@
<phpunit bootstrap="tests/bootstrap.php">
<testsuite name="URLify Test Suite">
<directory>tests</directory>
</testsuite>
<logging>
<log type="coverage-text" target="php://stdout" showUncoveredFiles="false"/>
</logging>
</phpunit>

View File

@@ -1,20 +0,0 @@
<?php
//Downcode the provided argument or stdin if the argument was not present
require_once dirname (__DIR__) . '/URLify.php';
//Print usage and exit if arguments are invalid
if($argc < 1 || $argc > 2) {
die ("Usage (argument): php " . basename(__FILE__) . " \"<text to downcode>\"\nUsage (pipe): <Arbitrary command> | php " . basename(__FILE__) . "\n");
}
//Process the provided argument
if($argc === 2) {
$s = $argv[1];
//Or read from stdin if the argument wasn't present
} else {
$piped = true;
$s = file_get_contents("php://stdin");
}
echo URLify::downcode ($s) . ($piped ? "\n" : "");

View File

@@ -1,20 +0,0 @@
<?php
//Filter the provided argument or stdin if the argument was not present
require_once dirname (__DIR__) . '/URLify.php';
//Print usage and exit if arguments are invalid
if($argc < 1 || $argc > 2) {
die ("Usage (argument): php " . basename(__FILE__) . " \"<text to filter>\"\nUsage (pipe): <Arbitrary command> | php " . basename(__FILE__) . "\n");
}
//Process the provided argument
if($argc === 2) {
$s = $argv[1];
//Or read from stdin if the argument wasn't present
} else {
$piped = true;
$s = file_get_contents("php://stdin");
}
echo URLify::filter ($s) . ($piped ? "\n" : "");

View File

@@ -1,20 +0,0 @@
<?php
//Transliterate the provided argument or stdin if the argument was not present
require_once dirname (__DIR__) . '/URLify.php';
//Print usage and exit if arguments are invalid
if($argc < 1 || $argc > 2) {
die ("Usage (argument): php " . basename(__FILE__) . " \"<text to transliterate>\"\nUsage (pipe): <Arbitrary command> | php " . basename(__FILE__) . "\n");
}
//Process the provided argument
if($argc === 2) {
$s = $argv[1];
//Or read from stdin if the argument wasn't present
} else {
$piped = true;
$s = file_get_contents("php://stdin");
}
echo URLify::transliterate($s) . ($piped ? "\n" : "");

View File

@@ -1,60 +0,0 @@
<?php
use PHPUnit\Framework\TestCase;
class URLifyTest extends TestCase {
function test_downcode () {
$this->assertEquals (' J\'etudie le francais ', URLify::downcode (' J\'étudie le français '));
$this->assertEquals ('Lo siento, no hablo espanol.', URLify::downcode ('Lo siento, no hablo español.'));
$this->assertEquals ('F3PWS', URLify::downcode ('ΦΞΠΏΣ'));
$this->assertEquals ('foo-bar', URLify::filter ('_foo_bar_'));
}
function test_filter () {
$this->assertEquals ('jetudie-le-francais', URLify::filter (' J\'étudie le français '));
$this->assertEquals ('lo-siento-no-hablo-espanol', URLify::filter ('Lo siento, no hablo español.'));
$this->assertEquals ('f3pws', URLify::filter ('ΦΞΠΏΣ'));
$this->assertEquals ('', URLify::filter('大般若經'));
$this->assertEquals ('test-.txt', URLify::filter('test-大般若經.txt', 60, "", $file_name = true));
$this->assertEquals ('yakrhy-ltoytr', URLify::filter('ياكرهي لتويتر'));
$this->assertEquals ('saaat-25', URLify::filter('ساعت ۲۵'));
$this->assertEquals ('foto.jpg', URLify::filter ('фото.jpg', 60, "", $file_name = true));
// priorization of language-specific maps
$this->assertEquals ('aouaou', URLify::filter ('ÄÖÜäöü',60,"tr"));
$this->assertEquals ('aeoeueaeoeue', URLify::filter ('ÄÖÜäöü',60,"de"));
$this->assertEquals ('bobby-mcferrin-dont-worry-be-happy', URLify::filter ("Bobby McFerrin — Don't worry be happy",600,"en"));
// test stripping and conversion of UTF-8 spaces
$this->assertEquals ('test-mahito-mukai', URLify::filter('向井 真人test (Mahito Mukai)'));
// Treat underscore as space
$this->assertEquals ('text_with_underscore', URLify::filter('text_with_underscore', 60, "en", true, true, true, false));
}
function test_add_chars () {
$this->assertEquals ('¿ ® ¼ ¼ ¾ ¶', URLify::downcode ('¿ ® ¼ ¼ ¾ ¶'));
URLify::add_chars (array (
'¿' => '?', '®' => '(r)', '¼' => '1/4',
'¼' => '1/2', '¾' => '3/4', '¶' => 'P'
));
$this->assertEquals ('? (r) 1/2 1/2 3/4 P', URLify::downcode ('¿ ® ¼ ¼ ¾ ¶'));
}
function test_remove_words () {
$this->assertEquals ('foo-bar', URLify::filter ('foo bar'));
URLify::remove_words (array ('foo', 'bar'));
$this->assertEquals ('', URLify::filter ('foo bar'));
}
function test_many_rounds_with_unknown_language_code () {
for ($i = 0; $i < 1000; $i++) {
URLify::downcode ('Lo siento, no hablo español.',-1);
}
}
function test_remove_words_disable () {
URLify::remove_words (array ('foo', 'bar'));
$this->assertEquals ('foo-bar', URLify::filter ('foo bar', 60, '', false, false));
}
}
?>

View File

@@ -1,9 +0,0 @@
<?php
set_error_handler(function () {
echo file_get_contents(dirname(__DIR__).'/INSTALL');
exit(1);
}, E_ALL);
require_once dirname(__DIR__) . '/vendor/autoload.php';
restore_error_handler();

Submodule system/vendor/laminas/laminas-permissions-acl deleted from 86cecb540c

View File

@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) Taylor Otwell
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.

View File

@@ -1,73 +0,0 @@
# Serializable Closure
<a href="https://github.com/laravel/serializable-closure/actions">
<img src="https://github.com/laravel/serializable-closure/workflows/tests/badge.svg" alt="Build Status">
</a>
<a href="https://packagist.org/packages/laravel/serializable-closure">
<img src="https://img.shields.io/packagist/dt/laravel/serializable-closure" alt="Total Downloads">
</a>
<a href="https://packagist.org/packages/laravel/serializable-closure">
<img src="https://img.shields.io/packagist/v/laravel/serializable-closure" alt="Latest Stable Version">
</a>
<a href="https://packagist.org/packages/laravel/serializable-closure">
<img src="https://img.shields.io/packagist/l/laravel/serializable-closure" alt="License">
</a>
## Introduction
> This project is a fork of the excellent [opis/closure: 3.x](https://github.com/opis/closure) package. At Laravel, we decided to fork this package as the upcoming version [4.x](https://github.com/opis/closure) is a complete rewrite on top of the [FFI extension](https://www.php.net/manual/en/book.ffi.php). As Laravel is a web framework, and FFI is not enabled by default in web requests, this fork allows us to keep using the `3.x` series while adding support for new PHP versions.
Laravel Serializable Closure provides an easy and secure way to **serialize closures in PHP**.
## Official Documentation
### Installation
> **Requires [PHP 7.4+](https://php.net/releases/)**
First, install Laravel Serializable Closure via the [Composer](https://getcomposer.org/) package manager:
```bash
composer require laravel/serializable-closure
```
### Usage
You may serialize a closure this way:
```php
use Laravel\SerializableClosure\SerializableClosure;
$closure = fn () => 'james';
// Recommended
SerializableClosure::setSecretKey('secret');
$serialized = serialize(new SerializableClosure($closure));
$closure = unserialize($serialized)->getClosure();
echo $closure(); // james;
```
### Caveats
* Anonymous classes cannot be created within closures.
* Attributes cannot be used within closures.
* Serializing closures on REPL environments like Laravel Tinker is not supported.
* Serializing closures that reference objects with readonly properties is not supported.
## Contributing
Thank you for considering contributing to Serializable Closure! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
## Code of Conduct
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
## Security Vulnerabilities
Please review [our security policy](https://github.com/laravel/serializable-closure/security/policy) on how to report security vulnerabilities.
## License
Serializable Closure is open-sourced software licensed under the [MIT license](LICENSE.md).

View File

@@ -1,52 +0,0 @@
{
"name": "laravel/serializable-closure",
"description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.",
"keywords": ["laravel", "Serializable", "closure"],
"license": "MIT",
"support": {
"issues": "https://github.com/laravel/serializable-closure/issues",
"source": "https://github.com/laravel/serializable-closure"
},
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
},
{
"name": "Nuno Maduro",
"email": "nuno@laravel.com"
}
],
"require": {
"php": "^7.3|^8.0"
},
"require-dev": {
"nesbot/carbon": "^2.61",
"pestphp/pest": "^1.21.3",
"phpstan/phpstan": "^1.8.2",
"symfony/var-dumper": "^5.4.11"
},
"autoload": {
"psr-4": {
"Laravel\\SerializableClosure\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"config": {
"sort-packages": true,
"allow-plugins": {
"pestphp/pest-plugin": true
}
},
"minimum-stability": "dev",
"prefer-stable": true
}

View File

@@ -1,20 +0,0 @@
<?php
namespace Laravel\SerializableClosure\Contracts;
interface Serializable
{
/**
* Resolve the closure with the given arguments.
*
* @return mixed
*/
public function __invoke();
/**
* Gets the closure that got serialized/unserialized.
*
* @return \Closure
*/
public function getClosure();
}

View File

@@ -1,22 +0,0 @@
<?php
namespace Laravel\SerializableClosure\Contracts;
interface Signer
{
/**
* Sign the given serializable.
*
* @param string $serializable
* @return array
*/
public function sign($serializable);
/**
* Verify the given signature.
*
* @param array $signature
* @return bool
*/
public function verify($signature);
}

View File

@@ -1,19 +0,0 @@
<?php
namespace Laravel\SerializableClosure\Exceptions;
use Exception;
class InvalidSignatureException extends Exception
{
/**
* Create a new exception instance.
*
* @param string $message
* @return void
*/
public function __construct($message = 'Your serialized closure might have been modified or it\'s unsafe to be unserialized.')
{
parent::__construct($message);
}
}

View File

@@ -1,19 +0,0 @@
<?php
namespace Laravel\SerializableClosure\Exceptions;
use Exception;
class MissingSecretKeyException extends Exception
{
/**
* Create a new exception instance.
*
* @param string $message
* @return void
*/
public function __construct($message = 'No serializable closure secret key has been specified.')
{
parent::__construct($message);
}
}

View File

@@ -1,19 +0,0 @@
<?php
namespace Laravel\SerializableClosure\Exceptions;
use Exception;
class PhpVersionNotSupportedException extends Exception
{
/**
* Create a new exception instance.
*
* @param string $message
* @return void
*/
public function __construct($message = 'PHP 7.3 is not supported.')
{
parent::__construct($message);
}
}

View File

@@ -1,139 +0,0 @@
<?php
namespace Laravel\SerializableClosure;
use Closure;
use Laravel\SerializableClosure\Exceptions\InvalidSignatureException;
use Laravel\SerializableClosure\Exceptions\PhpVersionNotSupportedException;
use Laravel\SerializableClosure\Serializers\Signed;
use Laravel\SerializableClosure\Signers\Hmac;
class SerializableClosure
{
/**
* The closure's serializable.
*
* @var \Laravel\SerializableClosure\Contracts\Serializable
*/
protected $serializable;
/**
* Creates a new serializable closure instance.
*
* @param \Closure $closure
* @return void
*/
public function __construct(Closure $closure)
{
if (\PHP_VERSION_ID < 70400) {
throw new PhpVersionNotSupportedException();
}
$this->serializable = Serializers\Signed::$signer
? new Serializers\Signed($closure)
: new Serializers\Native($closure);
}
/**
* Resolve the closure with the given arguments.
*
* @return mixed
*/
public function __invoke()
{
if (\PHP_VERSION_ID < 70400) {
throw new PhpVersionNotSupportedException();
}
return call_user_func_array($this->serializable, func_get_args());
}
/**
* Gets the closure.
*
* @return \Closure
*/
public function getClosure()
{
if (\PHP_VERSION_ID < 70400) {
throw new PhpVersionNotSupportedException();
}
return $this->serializable->getClosure();
}
/**
* Create a new unsigned serializable closure instance.
*
* @param Closure $closure
* @return \Laravel\SerializableClosure\UnsignedSerializableClosure
*/
public static function unsigned(Closure $closure)
{
return new UnsignedSerializableClosure($closure);
}
/**
* Sets the serializable closure secret key.
*
* @param string|null $secret
* @return void
*/
public static function setSecretKey($secret)
{
Serializers\Signed::$signer = $secret
? new Hmac($secret)
: null;
}
/**
* Sets the serializable closure secret key.
*
* @param \Closure|null $transformer
* @return void
*/
public static function transformUseVariablesUsing($transformer)
{
Serializers\Native::$transformUseVariables = $transformer;
}
/**
* Sets the serializable closure secret key.
*
* @param \Closure|null $resolver
* @return void
*/
public static function resolveUseVariablesUsing($resolver)
{
Serializers\Native::$resolveUseVariables = $resolver;
}
/**
* Get the serializable representation of the closure.
*
* @return array
*/
public function __serialize()
{
return [
'serializable' => $this->serializable,
];
}
/**
* Restore the closure after serialization.
*
* @param array $data
* @return void
*
* @throws \Laravel\SerializableClosure\Exceptions\InvalidSignatureException
*/
public function __unserialize($data)
{
if (Signed::$signer && ! $data['serializable'] instanceof Signed) {
throw new InvalidSignatureException();
}
$this->serializable = $data['serializable'];
}
}

View File

@@ -1,514 +0,0 @@
<?php
namespace Laravel\SerializableClosure\Serializers;
use Closure;
use DateTimeInterface;
use Laravel\SerializableClosure\Contracts\Serializable;
use Laravel\SerializableClosure\SerializableClosure;
use Laravel\SerializableClosure\Support\ClosureScope;
use Laravel\SerializableClosure\Support\ClosureStream;
use Laravel\SerializableClosure\Support\ReflectionClosure;
use Laravel\SerializableClosure\Support\SelfReference;
use Laravel\SerializableClosure\UnsignedSerializableClosure;
use ReflectionObject;
use UnitEnum;
class Native implements Serializable
{
/**
* Transform the use variables before serialization.
*
* @var \Closure|null
*/
public static $transformUseVariables;
/**
* Resolve the use variables after unserialization.
*
* @var \Closure|null
*/
public static $resolveUseVariables;
/**
* The closure to be serialized/unserialized.
*
* @var \Closure
*/
protected $closure;
/**
* The closure's reflection.
*
* @var \Laravel\SerializableClosure\Support\ReflectionClosure|null
*/
protected $reflector;
/**
* The closure's code.
*
* @var array|null
*/
protected $code;
/**
* The closure's reference.
*
* @var string
*/
protected $reference;
/**
* The closure's scope.
*
* @var \Laravel\SerializableClosure\Support\ClosureScope|null
*/
protected $scope;
/**
* The "key" that marks an array as recursive.
*/
const ARRAY_RECURSIVE_KEY = 'LARAVEL_SERIALIZABLE_RECURSIVE_KEY';
/**
* Creates a new serializable closure instance.
*
* @param \Closure $closure
* @return void
*/
public function __construct(Closure $closure)
{
$this->closure = $closure;
}
/**
* Resolve the closure with the given arguments.
*
* @return mixed
*/
public function __invoke()
{
return call_user_func_array($this->closure, func_get_args());
}
/**
* Gets the closure.
*
* @return \Closure
*/
public function getClosure()
{
return $this->closure;
}
/**
* Get the serializable representation of the closure.
*
* @return array
*/
public function __serialize()
{
if ($this->scope === null) {
$this->scope = new ClosureScope();
$this->scope->toSerialize++;
}
$this->scope->serializations++;
$scope = $object = null;
$reflector = $this->getReflector();
if ($reflector->isBindingRequired()) {
$object = $reflector->getClosureThis();
static::wrapClosures($object, $this->scope);
}
if ($scope = $reflector->getClosureScopeClass()) {
$scope = $scope->name;
}
$this->reference = spl_object_hash($this->closure);
$this->scope[$this->closure] = $this;
$use = $reflector->getUseVariables();
if (static::$transformUseVariables) {
$use = call_user_func(static::$transformUseVariables, $reflector->getUseVariables());
}
$code = $reflector->getCode();
$this->mapByReference($use);
$data = [
'use' => $use,
'function' => $code,
'scope' => $scope,
'this' => $object,
'self' => $this->reference,
];
if (! --$this->scope->serializations && ! --$this->scope->toSerialize) {
$this->scope = null;
}
return $data;
}
/**
* Restore the closure after serialization.
*
* @param array $data
* @return void
*/
public function __unserialize($data)
{
ClosureStream::register();
$this->code = $data;
unset($data);
$this->code['objects'] = [];
if ($this->code['use']) {
$this->scope = new ClosureScope();
if (static::$resolveUseVariables) {
$this->code['use'] = call_user_func(static::$resolveUseVariables, $this->code['use']);
}
$this->mapPointers($this->code['use']);
extract($this->code['use'], EXTR_OVERWRITE | EXTR_REFS);
$this->scope = null;
}
$this->closure = include ClosureStream::STREAM_PROTO.'://'.$this->code['function'];
if ($this->code['this'] === $this) {
$this->code['this'] = null;
}
$this->closure = $this->closure->bindTo($this->code['this'], $this->code['scope']);
if (! empty($this->code['objects'])) {
foreach ($this->code['objects'] as $item) {
$item['property']->setValue($item['instance'], $item['object']->getClosure());
}
}
$this->code = $this->code['function'];
}
/**
* Ensures the given closures are serializable.
*
* @param mixed $data
* @param \Laravel\SerializableClosure\Support\ClosureScope $storage
* @return void
*/
public static function wrapClosures(&$data, $storage)
{
if ($data instanceof Closure) {
$data = new static($data);
} elseif (is_array($data)) {
if (isset($data[self::ARRAY_RECURSIVE_KEY])) {
return;
}
$data[self::ARRAY_RECURSIVE_KEY] = true;
foreach ($data as $key => &$value) {
if ($key === self::ARRAY_RECURSIVE_KEY) {
continue;
}
static::wrapClosures($value, $storage);
}
unset($value);
unset($data[self::ARRAY_RECURSIVE_KEY]);
} elseif ($data instanceof \stdClass) {
if (isset($storage[$data])) {
$data = $storage[$data];
return;
}
$data = $storage[$data] = clone $data;
foreach ($data as &$value) {
static::wrapClosures($value, $storage);
}
unset($value);
} elseif (is_object($data) && ! $data instanceof static && ! $data instanceof UnitEnum) {
if (isset($storage[$data])) {
$data = $storage[$data];
return;
}
$instance = $data;
$reflection = new ReflectionObject($instance);
if (! $reflection->isUserDefined()) {
$storage[$instance] = $data;
return;
}
$storage[$instance] = $data = $reflection->newInstanceWithoutConstructor();
do {
if (! $reflection->isUserDefined()) {
break;
}
foreach ($reflection->getProperties() as $property) {
if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined()) {
continue;
}
$property->setAccessible(true);
if (PHP_VERSION >= 7.4 && ! $property->isInitialized($instance)) {
continue;
}
$value = $property->getValue($instance);
if (is_array($value) || is_object($value)) {
static::wrapClosures($value, $storage);
}
$property->setValue($data, $value);
}
} while ($reflection = $reflection->getParentClass());
}
}
/**
* Gets the closure's reflector.
*
* @return \Laravel\SerializableClosure\Support\ReflectionClosure
*/
public function getReflector()
{
if ($this->reflector === null) {
$this->code = null;
$this->reflector = new ReflectionClosure($this->closure);
}
return $this->reflector;
}
/**
* Internal method used to map closure pointers.
*
* @param mixed $data
* @return void
*/
protected function mapPointers(&$data)
{
$scope = $this->scope;
if ($data instanceof static) {
$data = &$data->closure;
} elseif (is_array($data)) {
if (isset($data[self::ARRAY_RECURSIVE_KEY])) {
return;
}
$data[self::ARRAY_RECURSIVE_KEY] = true;
foreach ($data as $key => &$value) {
if ($key === self::ARRAY_RECURSIVE_KEY) {
continue;
} elseif ($value instanceof static) {
$data[$key] = &$value->closure;
} elseif ($value instanceof SelfReference && $value->hash === $this->code['self']) {
$data[$key] = &$this->closure;
} else {
$this->mapPointers($value);
}
}
unset($value);
unset($data[self::ARRAY_RECURSIVE_KEY]);
} elseif ($data instanceof \stdClass) {
if (isset($scope[$data])) {
return;
}
$scope[$data] = true;
foreach ($data as $key => &$value) {
if ($value instanceof SelfReference && $value->hash === $this->code['self']) {
$data->{$key} = &$this->closure;
} elseif (is_array($value) || is_object($value)) {
$this->mapPointers($value);
}
}
unset($value);
} elseif (is_object($data) && ! ($data instanceof Closure)) {
if (isset($scope[$data])) {
return;
}
$scope[$data] = true;
$reflection = new ReflectionObject($data);
do {
if (! $reflection->isUserDefined()) {
break;
}
foreach ($reflection->getProperties() as $property) {
if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined()) {
continue;
}
$property->setAccessible(true);
if (PHP_VERSION >= 7.4 && ! $property->isInitialized($data)) {
continue;
}
$item = $property->getValue($data);
if ($item instanceof SerializableClosure || $item instanceof UnsignedSerializableClosure || ($item instanceof SelfReference && $item->hash === $this->code['self'])) {
$this->code['objects'][] = [
'instance' => $data,
'property' => $property,
'object' => $item instanceof SelfReference ? $this : $item,
];
} elseif (is_array($item) || is_object($item)) {
$this->mapPointers($item);
$property->setValue($data, $item);
}
}
} while ($reflection = $reflection->getParentClass());
}
}
/**
* Internal method used to map closures by reference.
*
* @param mixed $data
* @return void
*/
protected function mapByReference(&$data)
{
if ($data instanceof Closure) {
if ($data === $this->closure) {
$data = new SelfReference($this->reference);
return;
}
if (isset($this->scope[$data])) {
$data = $this->scope[$data];
return;
}
$instance = new static($data);
$instance->scope = $this->scope;
$data = $this->scope[$data] = $instance;
} elseif (is_array($data)) {
if (isset($data[self::ARRAY_RECURSIVE_KEY])) {
return;
}
$data[self::ARRAY_RECURSIVE_KEY] = true;
foreach ($data as $key => &$value) {
if ($key === self::ARRAY_RECURSIVE_KEY) {
continue;
}
$this->mapByReference($value);
}
unset($value);
unset($data[self::ARRAY_RECURSIVE_KEY]);
} elseif ($data instanceof \stdClass) {
if (isset($this->scope[$data])) {
$data = $this->scope[$data];
return;
}
$instance = $data;
$this->scope[$instance] = $data = clone $data;
foreach ($data as &$value) {
$this->mapByReference($value);
}
unset($value);
} elseif (is_object($data) && ! $data instanceof SerializableClosure && ! $data instanceof UnsignedSerializableClosure) {
if (isset($this->scope[$data])) {
$data = $this->scope[$data];
return;
}
$instance = $data;
if ($data instanceof DateTimeInterface) {
$this->scope[$instance] = $data;
return;
}
if ($data instanceof UnitEnum) {
$this->scope[$instance] = $data;
return;
}
$reflection = new ReflectionObject($data);
if (! $reflection->isUserDefined()) {
$this->scope[$instance] = $data;
return;
}
$this->scope[$instance] = $data = $reflection->newInstanceWithoutConstructor();
do {
if (! $reflection->isUserDefined()) {
break;
}
foreach ($reflection->getProperties() as $property) {
if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined()) {
continue;
}
$property->setAccessible(true);
if (PHP_VERSION >= 7.4 && ! $property->isInitialized($instance)) {
continue;
}
$value = $property->getValue($instance);
if (is_array($value) || is_object($value)) {
$this->mapByReference($value);
}
$property->setValue($data, $value);
}
} while ($reflection = $reflection->getParentClass());
}
}
}

View File

@@ -1,91 +0,0 @@
<?php
namespace Laravel\SerializableClosure\Serializers;
use Laravel\SerializableClosure\Contracts\Serializable;
use Laravel\SerializableClosure\Exceptions\InvalidSignatureException;
use Laravel\SerializableClosure\Exceptions\MissingSecretKeyException;
class Signed implements Serializable
{
/**
* The signer that will sign and verify the closure's signature.
*
* @var \Laravel\SerializableClosure\Contracts\Signer|null
*/
public static $signer;
/**
* The closure to be serialized/unserialized.
*
* @var \Closure
*/
protected $closure;
/**
* Creates a new serializable closure instance.
*
* @param \Closure $closure
* @return void
*/
public function __construct($closure)
{
$this->closure = $closure;
}
/**
* Resolve the closure with the given arguments.
*
* @return mixed
*/
public function __invoke()
{
return call_user_func_array($this->closure, func_get_args());
}
/**
* Gets the closure.
*
* @return \Closure
*/
public function getClosure()
{
return $this->closure;
}
/**
* Get the serializable representation of the closure.
*
* @return array
*/
public function __serialize()
{
if (! static::$signer) {
throw new MissingSecretKeyException();
}
return static::$signer->sign(
serialize(new Native($this->closure))
);
}
/**
* Restore the closure after serialization.
*
* @param array $signature
* @return void
*
* @throws \Laravel\SerializableClosure\Exceptions\InvalidSignatureException
*/
public function __unserialize($signature)
{
if (static::$signer && ! static::$signer->verify($signature)) {
throw new InvalidSignatureException();
}
/** @var \Laravel\SerializableClosure\Contracts\Serializable $serializable */
$serializable = unserialize($signature['serializable']);
$this->closure = $serializable->getClosure();
}
}

View File

@@ -1,53 +0,0 @@
<?php
namespace Laravel\SerializableClosure\Signers;
use Laravel\SerializableClosure\Contracts\Signer;
class Hmac implements Signer
{
/**
* The secret key.
*
* @var string
*/
protected $secret;
/**
* Creates a new signer instance.
*
* @param string $secret
* @return void
*/
public function __construct($secret)
{
$this->secret = $secret;
}
/**
* Sign the given serializable.
*
* @param string $serialized
* @return array
*/
public function sign($serialized)
{
return [
'serializable' => $serialized,
'hash' => base64_encode(hash_hmac('sha256', $serialized, $this->secret, true)),
];
}
/**
* Verify the given signature.
*
* @param array $signature
* @return bool
*/
public function verify($signature)
{
return hash_equals(base64_encode(
hash_hmac('sha256', $signature['serializable'], $this->secret, true)
), $signature['hash']);
}
}

View File

@@ -1,22 +0,0 @@
<?php
namespace Laravel\SerializableClosure\Support;
use SplObjectStorage;
class ClosureScope extends SplObjectStorage
{
/**
* The number of serializations in current scope.
*
* @var int
*/
public $serializations = 0;
/**
* The number of closures that have to be serialized.
*
* @var int
*/
public $toSerialize = 0;
}

View File

@@ -1,179 +0,0 @@
<?php
namespace Laravel\SerializableClosure\Support;
#[\AllowDynamicProperties]
class ClosureStream
{
/**
* The stream protocol.
*/
const STREAM_PROTO = 'laravel-serializable-closure';
/**
* Checks if this stream is registered.
*
* @var bool
*/
protected static $isRegistered = false;
/**
* The stream content.
*
* @var string
*/
protected $content;
/**
* The stream content.
*
* @var int
*/
protected $length;
/**
* The stream pointer.
*
* @var int
*/
protected $pointer = 0;
/**
* Opens file or URL.
*
* @param string $path
* @param string $mode
* @param string $options
* @param string|null $opened_path
* @return bool
*/
public function stream_open($path, $mode, $options, &$opened_path)
{
$this->content = "<?php\nreturn ".substr($path, strlen(static::STREAM_PROTO.'://')).';';
$this->length = strlen($this->content);
return true;
}
/**
* Read from stream.
*
* @param int $count
* @return string
*/
public function stream_read($count)
{
$value = substr($this->content, $this->pointer, $count);
$this->pointer += $count;
return $value;
}
/**
* Tests for end-of-file on a file pointer.
*
* @return bool
*/
public function stream_eof()
{
return $this->pointer >= $this->length;
}
/**
* Change stream options.
*
* @param int $option
* @param int $arg1
* @param int $arg2
* @return bool
*/
public function stream_set_option($option, $arg1, $arg2)
{
return false;
}
/**
* Retrieve information about a file resource.
*
* @return array|bool
*/
public function stream_stat()
{
$stat = stat(__FILE__);
// @phpstan-ignore-next-line
$stat[7] = $stat['size'] = $this->length;
return $stat;
}
/**
* Retrieve information about a file.
*
* @param string $path
* @param int $flags
* @return array|bool
*/
public function url_stat($path, $flags)
{
$stat = stat(__FILE__);
// @phpstan-ignore-next-line
$stat[7] = $stat['size'] = $this->length;
return $stat;
}
/**
* Seeks to specific location in a stream.
*
* @param int $offset
* @param int $whence
* @return bool
*/
public function stream_seek($offset, $whence = SEEK_SET)
{
$crt = $this->pointer;
switch ($whence) {
case SEEK_SET:
$this->pointer = $offset;
break;
case SEEK_CUR:
$this->pointer += $offset;
break;
case SEEK_END:
$this->pointer = $this->length + $offset;
break;
}
if ($this->pointer < 0 || $this->pointer >= $this->length) {
$this->pointer = $crt;
return false;
}
return true;
}
/**
* Retrieve the current position of a stream.
*
* @return int
*/
public function stream_tell()
{
return $this->pointer;
}
/**
* Registers the stream.
*
* @return void
*/
public static function register()
{
if (! static::$isRegistered) {
static::$isRegistered = stream_wrapper_register(static::STREAM_PROTO, __CLASS__);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +0,0 @@
<?php
namespace Laravel\SerializableClosure\Support;
class SelfReference
{
/**
* The unique hash representing the object.
*
* @var string
*/
public $hash;
/**
* Creates a new self reference instance.
*
* @param string $hash
* @return void
*/
public function __construct($hash)
{
$this->hash = $hash;
}
}

View File

@@ -1,82 +0,0 @@
<?php
namespace Laravel\SerializableClosure;
use Closure;
use Laravel\SerializableClosure\Exceptions\PhpVersionNotSupportedException;
class UnsignedSerializableClosure
{
/**
* The closure's serializable.
*
* @var \Laravel\SerializableClosure\Contracts\Serializable
*/
protected $serializable;
/**
* Creates a new serializable closure instance.
*
* @param \Closure $closure
* @return void
*/
public function __construct(Closure $closure)
{
if (\PHP_VERSION_ID < 70400) {
throw new PhpVersionNotSupportedException();
}
$this->serializable = new Serializers\Native($closure);
}
/**
* Resolve the closure with the given arguments.
*
* @return mixed
*/
public function __invoke()
{
if (\PHP_VERSION_ID < 70400) {
throw new PhpVersionNotSupportedException();
}
return call_user_func_array($this->serializable, func_get_args());
}
/**
* Gets the closure.
*
* @return \Closure
*/
public function getClosure()
{
if (\PHP_VERSION_ID < 70400) {
throw new PhpVersionNotSupportedException();
}
return $this->serializable->getClosure();
}
/**
* Get the serializable representation of the closure.
*
* @return array
*/
public function __serialize()
{
return [
'serializable' => $this->serializable,
];
}
/**
* Restore the closure after serialization.
*
* @param array $data
* @return void
*/
public function __unserialize($data)
{
$this->serializable = $data['serializable'];
}
}

View File

@@ -1,5 +0,0 @@
/vendor/
.idea/
# ignore lock file since we have no extra dependencies
composer.lock

View File

@@ -1 +0,0 @@
assume_php=false

View File

@@ -1,20 +0,0 @@
sudo: false
language: php
php:
- 5.4
- 5.5
- 5.6
- 7.0
- 7.1
- 7.2
- hhvm
script:
- ./vendor/bin/phpunit
before_install:
- travis_retry composer self-update
install:
- composer install

View File

@@ -1,126 +0,0 @@
<?hh // decl
namespace FastRoute {
class BadRouteException extends \LogicException {
}
interface RouteParser {
public function parse(string $route): array<array>;
}
class RouteCollector {
public function __construct(RouteParser $routeParser, DataGenerator $dataGenerator);
public function addRoute(mixed $httpMethod, string $route, mixed $handler): void;
public function getData(): array;
}
class Route {
public function __construct(string $httpMethod, mixed $handler, string $regex, array $variables);
public function matches(string $str): bool;
}
interface DataGenerator {
public function addRoute(string $httpMethod, array $routeData, mixed $handler);
public function getData(): array;
}
interface Dispatcher {
const int NOT_FOUND = 0;
const int FOUND = 1;
const int METHOD_NOT_ALLOWED = 2;
public function dispatch(string $httpMethod, string $uri): array;
}
function simpleDispatcher(
(function(RouteCollector): void) $routeDefinitionCallback,
shape(
?'routeParser' => classname<RouteParser>,
?'dataGenerator' => classname<DataGenerator>,
?'dispatcher' => classname<Dispatcher>,
?'routeCollector' => classname<RouteCollector>,
) $options = shape()): Dispatcher;
function cachedDispatcher(
(function(RouteCollector): void) $routeDefinitionCallback,
shape(
?'routeParser' => classname<RouteParser>,
?'dataGenerator' => classname<DataGenerator>,
?'dispatcher' => classname<Dispatcher>,
?'routeCollector' => classname<RouteCollector>,
?'cacheDisabled' => bool,
?'cacheFile' => string,
) $options = shape()): Dispatcher;
}
namespace FastRoute\DataGenerator {
abstract class RegexBasedAbstract implements \FastRoute\DataGenerator {
protected abstract function getApproxChunkSize();
protected abstract function processChunk($regexToRoutesMap);
public function addRoute(string $httpMethod, array $routeData, mixed $handler): void;
public function getData(): array;
}
class CharCountBased extends RegexBasedAbstract {
protected function getApproxChunkSize(): int;
protected function processChunk(array<string, string> $regexToRoutesMap): array<string, mixed>;
}
class GroupCountBased extends RegexBasedAbstract {
protected function getApproxChunkSize(): int;
protected function processChunk(array<string, string> $regexToRoutesMap): array<string, mixed>;
}
class GroupPosBased extends RegexBasedAbstract {
protected function getApproxChunkSize(): int;
protected function processChunk(array<string, string> $regexToRoutesMap): array<string, mixed>;
}
class MarkBased extends RegexBasedAbstract {
protected function getApproxChunkSize(): int;
protected function processChunk(array<string, string> $regexToRoutesMap): array<string, mixed>;
}
}
namespace FastRoute\Dispatcher {
abstract class RegexBasedAbstract implements \FastRoute\Dispatcher {
protected abstract function dispatchVariableRoute(array<array> $routeData, string $uri): array;
public function dispatch(string $httpMethod, string $uri): array;
}
class GroupPosBased extends RegexBasedAbstract {
public function __construct(array $data);
protected function dispatchVariableRoute(array<array> $routeData, string $uri): array;
}
class GroupCountBased extends RegexBasedAbstract {
public function __construct(array $data);
protected function dispatchVariableRoute(array<array> $routeData, string $uri): array;
}
class CharCountBased extends RegexBasedAbstract {
public function __construct(array $data);
protected function dispatchVariableRoute(array<array> $routeData, string $uri): array;
}
class MarkBased extends RegexBasedAbstract {
public function __construct(array $data);
protected function dispatchVariableRoute(array<array> $routeData, string $uri): array;
}
}
namespace FastRoute\RouteParser {
class Std implements \FastRoute\RouteParser {
const string VARIABLE_REGEX = <<<'REGEX'
\{
\s* ([a-zA-Z][a-zA-Z0-9_]*) \s*
(?:
: \s* ([^{}]*(?:\{(?-1)\}[^{}]*)*)
)?
\}
REGEX;
const string DEFAULT_DISPATCH_REGEX = '[^/]+';
public function parse(string $route): array<array>;
}
}

View File

@@ -1,31 +0,0 @@
Copyright (c) 2013 by Nikita Popov.
Some 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.
* The names of the contributors may not 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.

View File

@@ -1,313 +0,0 @@
FastRoute - Fast request router for PHP
=======================================
This library provides a fast implementation of a regular expression based router. [Blog post explaining how the
implementation works and why it is fast.][blog_post]
Install
-------
To install with composer:
```sh
composer require nikic/fast-route
```
Requires PHP 5.4 or newer.
Usage
-----
Here's a basic usage example:
```php
<?php
require '/path/to/vendor/autoload.php';
$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
$r->addRoute('GET', '/users', 'get_all_users_handler');
// {id} must be a number (\d+)
$r->addRoute('GET', '/user/{id:\d+}', 'get_user_handler');
// The /{title} suffix is optional
$r->addRoute('GET', '/articles/{id:\d+}[/{title}]', 'get_article_handler');
});
// Fetch method and URI from somewhere
$httpMethod = $_SERVER['REQUEST_METHOD'];
$uri = $_SERVER['REQUEST_URI'];
// Strip query string (?foo=bar) and decode URI
if (false !== $pos = strpos($uri, '?')) {
$uri = substr($uri, 0, $pos);
}
$uri = rawurldecode($uri);
$routeInfo = $dispatcher->dispatch($httpMethod, $uri);
switch ($routeInfo[0]) {
case FastRoute\Dispatcher::NOT_FOUND:
// ... 404 Not Found
break;
case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
$allowedMethods = $routeInfo[1];
// ... 405 Method Not Allowed
break;
case FastRoute\Dispatcher::FOUND:
$handler = $routeInfo[1];
$vars = $routeInfo[2];
// ... call $handler with $vars
break;
}
```
### Defining routes
The routes are defined by calling the `FastRoute\simpleDispatcher()` function, which accepts
a callable taking a `FastRoute\RouteCollector` instance. The routes are added by calling
`addRoute()` on the collector instance:
```php
$r->addRoute($method, $routePattern, $handler);
```
The `$method` is an uppercase HTTP method string for which a certain route should match. It
is possible to specify multiple valid methods using an array:
```php
// These two calls
$r->addRoute('GET', '/test', 'handler');
$r->addRoute('POST', '/test', 'handler');
// Are equivalent to this one call
$r->addRoute(['GET', 'POST'], '/test', 'handler');
```
By default the `$routePattern` uses a syntax where `{foo}` specifies a placeholder with name `foo`
and matching the regex `[^/]+`. To adjust the pattern the placeholder matches, you can specify
a custom pattern by writing `{bar:[0-9]+}`. Some examples:
```php
// Matches /user/42, but not /user/xyz
$r->addRoute('GET', '/user/{id:\d+}', 'handler');
// Matches /user/foobar, but not /user/foo/bar
$r->addRoute('GET', '/user/{name}', 'handler');
// Matches /user/foo/bar as well
$r->addRoute('GET', '/user/{name:.+}', 'handler');
```
Custom patterns for route placeholders cannot use capturing groups. For example `{lang:(en|de)}`
is not a valid placeholder, because `()` is a capturing group. Instead you can use either
`{lang:en|de}` or `{lang:(?:en|de)}`.
Furthermore parts of the route enclosed in `[...]` are considered optional, so that `/foo[bar]`
will match both `/foo` and `/foobar`. Optional parts are only supported in a trailing position,
not in the middle of a route.
```php
// This route
$r->addRoute('GET', '/user/{id:\d+}[/{name}]', 'handler');
// Is equivalent to these two routes
$r->addRoute('GET', '/user/{id:\d+}', 'handler');
$r->addRoute('GET', '/user/{id:\d+}/{name}', 'handler');
// Multiple nested optional parts are possible as well
$r->addRoute('GET', '/user[/{id:\d+}[/{name}]]', 'handler');
// This route is NOT valid, because optional parts can only occur at the end
$r->addRoute('GET', '/user[/{id:\d+}]/{name}', 'handler');
```
The `$handler` parameter does not necessarily have to be a callback, it could also be a controller
class name or any other kind of data you wish to associate with the route. FastRoute only tells you
which handler corresponds to your URI, how you interpret it is up to you.
#### Shorcut methods for common request methods
For the `GET`, `POST`, `PUT`, `PATCH`, `DELETE` and `HEAD` request methods shortcut methods are available. For example:
```php
$r->get('/get-route', 'get_handler');
$r->post('/post-route', 'post_handler');
```
Is equivalent to:
```php
$r->addRoute('GET', '/get-route', 'get_handler');
$r->addRoute('POST', '/post-route', 'post_handler');
```
#### Route Groups
Additionally, you can specify routes inside of a group. All routes defined inside a group will have a common prefix.
For example, defining your routes as:
```php
$r->addGroup('/admin', function (RouteCollector $r) {
$r->addRoute('GET', '/do-something', 'handler');
$r->addRoute('GET', '/do-another-thing', 'handler');
$r->addRoute('GET', '/do-something-else', 'handler');
});
```
Will have the same result as:
```php
$r->addRoute('GET', '/admin/do-something', 'handler');
$r->addRoute('GET', '/admin/do-another-thing', 'handler');
$r->addRoute('GET', '/admin/do-something-else', 'handler');
```
Nested groups are also supported, in which case the prefixes of all the nested groups are combined.
### Caching
The reason `simpleDispatcher` accepts a callback for defining the routes is to allow seamless
caching. By using `cachedDispatcher` instead of `simpleDispatcher` you can cache the generated
routing data and construct the dispatcher from the cached information:
```php
<?php
$dispatcher = FastRoute\cachedDispatcher(function(FastRoute\RouteCollector $r) {
$r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0');
$r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1');
$r->addRoute('GET', '/user/{name}', 'handler2');
}, [
'cacheFile' => __DIR__ . '/route.cache', /* required */
'cacheDisabled' => IS_DEBUG_ENABLED, /* optional, enabled by default */
]);
```
The second parameter to the function is an options array, which can be used to specify the cache
file location, among other things.
### Dispatching a URI
A URI is dispatched by calling the `dispatch()` method of the created dispatcher. This method
accepts the HTTP method and a URI. Getting those two bits of information (and normalizing them
appropriately) is your job - this library is not bound to the PHP web SAPIs.
The `dispatch()` method returns an array whose first element contains a status code. It is one
of `Dispatcher::NOT_FOUND`, `Dispatcher::METHOD_NOT_ALLOWED` and `Dispatcher::FOUND`. For the
method not allowed status the second array element contains a list of HTTP methods allowed for
the supplied URI. For example:
[FastRoute\Dispatcher::METHOD_NOT_ALLOWED, ['GET', 'POST']]
> **NOTE:** The HTTP specification requires that a `405 Method Not Allowed` response include the
`Allow:` header to detail available methods for the requested resource. Applications using FastRoute
should use the second array element to add this header when relaying a 405 response.
For the found status the second array element is the handler that was associated with the route
and the third array element is a dictionary of placeholder names to their values. For example:
/* Routing against GET /user/nikic/42 */
[FastRoute\Dispatcher::FOUND, 'handler0', ['name' => 'nikic', 'id' => '42']]
### Overriding the route parser and dispatcher
The routing process makes use of three components: A route parser, a data generator and a
dispatcher. The three components adhere to the following interfaces:
```php
<?php
namespace FastRoute;
interface RouteParser {
public function parse($route);
}
interface DataGenerator {
public function addRoute($httpMethod, $routeData, $handler);
public function getData();
}
interface Dispatcher {
const NOT_FOUND = 0, FOUND = 1, METHOD_NOT_ALLOWED = 2;
public function dispatch($httpMethod, $uri);
}
```
The route parser takes a route pattern string and converts it into an array of route infos, where
each route info is again an array of it's parts. The structure is best understood using an example:
/* The route /user/{id:\d+}[/{name}] converts to the following array: */
[
[
'/user/',
['id', '\d+'],
],
[
'/user/',
['id', '\d+'],
'/',
['name', '[^/]+'],
],
]
This array can then be passed to the `addRoute()` method of a data generator. After all routes have
been added the `getData()` of the generator is invoked, which returns all the routing data required
by the dispatcher. The format of this data is not further specified - it is tightly coupled to
the corresponding dispatcher.
The dispatcher accepts the routing data via a constructor and provides a `dispatch()` method, which
you're already familiar with.
The route parser can be overwritten individually (to make use of some different pattern syntax),
however the data generator and dispatcher should always be changed as a pair, as the output from
the former is tightly coupled to the input of the latter. The reason the generator and the
dispatcher are separate is that only the latter is needed when using caching (as the output of
the former is what is being cached.)
When using the `simpleDispatcher` / `cachedDispatcher` functions from above the override happens
through the options array:
```php
<?php
$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
/* ... */
}, [
'routeParser' => 'FastRoute\\RouteParser\\Std',
'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased',
'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased',
]);
```
The above options array corresponds to the defaults. By replacing `GroupCountBased` by
`GroupPosBased` you could switch to a different dispatching strategy.
### A Note on HEAD Requests
The HTTP spec requires servers to [support both GET and HEAD methods][2616-511]:
> The methods GET and HEAD MUST be supported by all general-purpose servers
To avoid forcing users to manually register HEAD routes for each resource we fallback to matching an
available GET route for a given resource. The PHP web SAPI transparently removes the entity body
from HEAD responses so this behavior has no effect on the vast majority of users.
However, implementers using FastRoute outside the web SAPI environment (e.g. a custom server) MUST
NOT send entity bodies generated in response to HEAD requests. If you are a non-SAPI user this is
*your responsibility*; FastRoute has no purview to prevent you from breaking HTTP in such cases.
Finally, note that applications MAY always specify their own HEAD method route for a given
resource to bypass this behavior entirely.
### Credits
This library is based on a router that [Levi Morrison][levi] implemented for the Aerys server.
A large number of tests, as well as HTTP compliance considerations, were provided by [Daniel Lowrey][rdlowrey].
[2616-511]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.1 "RFC 2616 Section 5.1.1"
[blog_post]: http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html
[levi]: https://github.com/morrisonlevi
[rdlowrey]: https://github.com/rdlowrey

Some files were not shown because too many files have changed in this diff Show More