[CORE][COMPOSER] Add hoa/consistency

Renamed curry to callable_left_curry
This commit is contained in:
Diogo Cordeiro 2019-06-25 10:35:31 +01:00
parent 411e8ed79d
commit ec32db2dd6
84 changed files with 12419 additions and 191 deletions

View File

@ -19,6 +19,7 @@
"apereo/phpcas": "^1.3", "apereo/phpcas": "^1.3",
"diogocomposer/xmpphp": "^3.0", "diogocomposer/xmpphp": "^3.0",
"ezyang/htmlpurifier": "^4.10", "ezyang/htmlpurifier": "^4.10",
"hoa/consistency": "^1.17.05.02",
"masterminds/html5": "^2.6", "masterminds/html5": "^2.6",
"mf2/mf2": "^0.4.6", "mf2/mf2": "^0.4.6",
"michelf/php-markdown": "^1.8.0", "michelf/php-markdown": "^1.8.0",

348
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "ac49a57ede587e949b9bad4b3c080a1d", "content-hash": "1f145be7e041fab248e0ffa15684f12f",
"packages": [ "packages": [
{ {
"name": "apereo/phpcas", "name": "apereo/phpcas",
@ -179,6 +179,179 @@
], ],
"time": "2018-02-23T01:58:20+00:00" "time": "2018-02-23T01:58:20+00:00"
}, },
{
"name": "hoa/consistency",
"version": "1.17.05.02",
"source": {
"type": "git",
"url": "https://github.com/hoaproject/Consistency.git",
"reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/hoaproject/Consistency/zipball/fd7d0adc82410507f332516faf655b6ed22e4c2f",
"reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f",
"shasum": ""
},
"require": {
"hoa/exception": "~1.0",
"php": ">=5.5.0"
},
"require-dev": {
"hoa/stream": "~1.0",
"hoa/test": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Hoa\\Consistency\\": "."
},
"files": [
"Prelude.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Ivan Enderlin",
"email": "ivan.enderlin@hoa-project.net"
},
{
"name": "Hoa community",
"homepage": "https://hoa-project.net/"
}
],
"description": "The Hoa\\Consistency library.",
"homepage": "https://hoa-project.net/",
"keywords": [
"autoloader",
"callable",
"consistency",
"entity",
"flex",
"keyword",
"library"
],
"time": "2017-05-02T12:18:12+00:00"
},
{
"name": "hoa/event",
"version": "1.17.01.13",
"source": {
"type": "git",
"url": "https://github.com/hoaproject/Event.git",
"reference": "6c0060dced212ffa3af0e34bb46624f990b29c54"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/hoaproject/Event/zipball/6c0060dced212ffa3af0e34bb46624f990b29c54",
"reference": "6c0060dced212ffa3af0e34bb46624f990b29c54",
"shasum": ""
},
"require": {
"hoa/consistency": "~1.0",
"hoa/exception": "~1.0"
},
"require-dev": {
"hoa/test": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Hoa\\Event\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Ivan Enderlin",
"email": "ivan.enderlin@hoa-project.net"
},
{
"name": "Hoa community",
"homepage": "https://hoa-project.net/"
}
],
"description": "The Hoa\\Event library.",
"homepage": "https://hoa-project.net/",
"keywords": [
"event",
"library",
"listener",
"observer"
],
"time": "2017-01-13T15:30:50+00:00"
},
{
"name": "hoa/exception",
"version": "1.17.01.16",
"source": {
"type": "git",
"url": "https://github.com/hoaproject/Exception.git",
"reference": "091727d46420a3d7468ef0595651488bfc3a458f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/hoaproject/Exception/zipball/091727d46420a3d7468ef0595651488bfc3a458f",
"reference": "091727d46420a3d7468ef0595651488bfc3a458f",
"shasum": ""
},
"require": {
"hoa/consistency": "~1.0",
"hoa/event": "~1.0"
},
"require-dev": {
"hoa/test": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Hoa\\Exception\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Ivan Enderlin",
"email": "ivan.enderlin@hoa-project.net"
},
{
"name": "Hoa community",
"homepage": "https://hoa-project.net/"
}
],
"description": "The Hoa\\Exception library.",
"homepage": "https://hoa-project.net/",
"keywords": [
"exception",
"library"
],
"time": "2017-01-16T07:53:27+00:00"
},
{ {
"name": "masterminds/html5", "name": "masterminds/html5",
"version": "2.6.0", "version": "2.6.0",
@ -1277,179 +1450,6 @@
], ],
"time": "2017-08-08T07:44:07+00:00" "time": "2017-08-08T07:44:07+00:00"
}, },
{
"name": "hoa/consistency",
"version": "1.17.05.02",
"source": {
"type": "git",
"url": "https://github.com/hoaproject/Consistency.git",
"reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/hoaproject/Consistency/zipball/fd7d0adc82410507f332516faf655b6ed22e4c2f",
"reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f",
"shasum": ""
},
"require": {
"hoa/exception": "~1.0",
"php": ">=5.5.0"
},
"require-dev": {
"hoa/stream": "~1.0",
"hoa/test": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Hoa\\Consistency\\": "."
},
"files": [
"Prelude.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Ivan Enderlin",
"email": "ivan.enderlin@hoa-project.net"
},
{
"name": "Hoa community",
"homepage": "https://hoa-project.net/"
}
],
"description": "The Hoa\\Consistency library.",
"homepage": "https://hoa-project.net/",
"keywords": [
"autoloader",
"callable",
"consistency",
"entity",
"flex",
"keyword",
"library"
],
"time": "2017-05-02T12:18:12+00:00"
},
{
"name": "hoa/event",
"version": "1.17.01.13",
"source": {
"type": "git",
"url": "https://github.com/hoaproject/Event.git",
"reference": "6c0060dced212ffa3af0e34bb46624f990b29c54"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/hoaproject/Event/zipball/6c0060dced212ffa3af0e34bb46624f990b29c54",
"reference": "6c0060dced212ffa3af0e34bb46624f990b29c54",
"shasum": ""
},
"require": {
"hoa/consistency": "~1.0",
"hoa/exception": "~1.0"
},
"require-dev": {
"hoa/test": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Hoa\\Event\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Ivan Enderlin",
"email": "ivan.enderlin@hoa-project.net"
},
{
"name": "Hoa community",
"homepage": "https://hoa-project.net/"
}
],
"description": "The Hoa\\Event library.",
"homepage": "https://hoa-project.net/",
"keywords": [
"event",
"library",
"listener",
"observer"
],
"time": "2017-01-13T15:30:50+00:00"
},
{
"name": "hoa/exception",
"version": "1.17.01.16",
"source": {
"type": "git",
"url": "https://github.com/hoaproject/Exception.git",
"reference": "091727d46420a3d7468ef0595651488bfc3a458f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/hoaproject/Exception/zipball/091727d46420a3d7468ef0595651488bfc3a458f",
"reference": "091727d46420a3d7468ef0595651488bfc3a458f",
"shasum": ""
},
"require": {
"hoa/consistency": "~1.0",
"hoa/event": "~1.0"
},
"require-dev": {
"hoa/test": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Hoa\\Exception\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Ivan Enderlin",
"email": "ivan.enderlin@hoa-project.net"
},
{
"name": "Hoa community",
"homepage": "https://hoa-project.net/"
}
],
"description": "The Hoa\\Exception library.",
"homepage": "https://hoa-project.net/",
"keywords": [
"exception",
"library"
],
"time": "2017-01-16T07:53:27+00:00"
},
{ {
"name": "hoa/file", "name": "hoa/file",
"version": "1.17.07.11", "version": "1.17.07.11",

View File

@ -25,7 +25,7 @@
* @param ... any remaining arguments will be appended to call-time params * @param ... any remaining arguments will be appended to call-time params
* @return callback * @return callback
*/ */
function curry($fn) { function callable_left_curry($fn) {
$extra_args = func_get_args(); $extra_args = func_get_args();
array_shift($extra_args); array_shift($extra_args);
return function() use ($fn, $extra_args) { return function() use ($fn, $extra_args) {

View File

@ -927,7 +927,7 @@ define('_URL_SCHEME_SINGLE_COLON', 2);
define('_URL_SCHEME_NO_DOMAIN', 4); define('_URL_SCHEME_NO_DOMAIN', 4);
define('_URL_SCHEME_COLON_COORDINATES', 8); define('_URL_SCHEME_COLON_COORDINATES', 8);
function common_url_schemes($filter=null) function common_url_schemes($filter = null)
{ {
// TODO: move these to $config // TODO: move these to $config
$schemes = ['http' => _URL_SCHEME_COLON_DOUBLE_SLASH, $schemes = ['http' => _URL_SCHEME_COLON_DOUBLE_SLASH,
@ -1040,7 +1040,7 @@ function common_replace_urls_callback($text, $callback, $arg = null)
'#ixu'; '#ixu';
//preg_match_all($regex,$text,$matches); //preg_match_all($regex,$text,$matches);
//print_r($matches); //print_r($matches);
return preg_replace_callback($regex, curry('callback_helper', $callback, $arg), $text); return preg_replace_callback($regex, callable_left_curry('callback_helper', $callback, $arg), $text);
} }
/** /**
@ -1054,11 +1054,11 @@ function common_replace_urls_callback($text, $callback, $arg = null)
* *
* @access private * @access private
*/ */
function callback_helper($matches, $callback, $arg=null) function callback_helper($matches, $callback, $arg = null)
{ {
$url=$matches[1]; $url = $matches[1];
$left = strpos($matches[0], $url); $left = strpos($matches[0], $url);
$right = $left+strlen($url); $right = $left + strlen($url);
$groupSymbolSets=[ $groupSymbolSets=[
[ [
@ -1078,31 +1078,31 @@ function callback_helper($matches, $callback, $arg=null)
'right'=>'>' 'right'=>'>'
] ]
]; ];
$cannotEndWith=['.','?',',','#'];
$original_url=$url; $cannotEndWith = ['.','?',',','#'];
do { do {
$original_url=$url; $original_url = $url;
foreach ($groupSymbolSets as $groupSymbolSet) { foreach ($groupSymbolSets as $groupSymbolSet) {
if (substr($url, -1)==$groupSymbolSet['right']) { if (substr($url, -1) == $groupSymbolSet['right']) {
$group_left_count = substr_count($url, $groupSymbolSet['left']); $group_left_count = substr_count($url, $groupSymbolSet['left']);
$group_right_count = substr_count($url, $groupSymbolSet['right']); $group_right_count = substr_count($url, $groupSymbolSet['right']);
if ($group_left_count<$group_right_count) { if ($group_left_count < $group_right_count) {
$right-=1; $right -= 1;
$url=substr($url, 0, -1); $url = substr($url, 0, -1);
} }
} }
} }
if (in_array(substr($url, -1), $cannotEndWith)) { if (in_array(substr($url, -1), $cannotEndWith)) {
$right-=1; $right -= 1;
$url=substr($url, 0, -1); $url=substr($url, 0, -1);
} }
} while ($original_url!=$url); } while ($original_url != $url);
$result = call_user_func_array($callback, [$url, $arg]); $result = call_user_func_array($callback, [$url, $arg]);
return substr($matches[0], 0, $left) . $result . substr($matches[0], $right); return substr($matches[0], 0, $left) . $result . substr($matches[0], $right);
} }
require_once INSTALLDIR . "/lib/curry.php"; require_once INSTALLDIR . "/lib/callable_left_curry.php";
function common_linkify($url) function common_linkify($url)
{ {

View File

@ -20,7 +20,7 @@ class CurryTest extends PHPUnit_Framework_TestCase
public function testProduction($callback, $curry_params, $call_params, $expected) public function testProduction($callback, $curry_params, $call_params, $expected)
{ {
$params = array_merge(array($callback), $curry_params); $params = array_merge(array($callback), $curry_params);
$curried = call_user_func_array('curry', $params); $curried = call_user_func_array('callable_left_curry', $params);
$result = call_user_func_array($curried, $call_params); $result = call_user_func_array($curried, $call_params);
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);
} }

View File

@ -379,6 +379,37 @@ return array(
'HTMLPurifier_VarParser_Flexible' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Flexible.php', 'HTMLPurifier_VarParser_Flexible' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Flexible.php',
'HTMLPurifier_VarParser_Native' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Native.php', 'HTMLPurifier_VarParser_Native' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Native.php',
'HTMLPurifier_Zipper' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Zipper.php', 'HTMLPurifier_Zipper' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Zipper.php',
'Hoa\\Consistency\\Autoloader' => $vendorDir . '/hoa/consistency/Autoloader.php',
'Hoa\\Consistency\\Consistency' => $vendorDir . '/hoa/consistency/Consistency.php',
'Hoa\\Consistency\\Exception' => $vendorDir . '/hoa/consistency/Exception.php',
'Hoa\\Consistency\\Test\\Unit\\Autoloader' => $vendorDir . '/hoa/consistency/Test/Unit/Autoloader.php',
'Hoa\\Consistency\\Test\\Unit\\Consistency' => $vendorDir . '/hoa/consistency/Test/Unit/Consistency.php',
'Hoa\\Consistency\\Test\\Unit\\Exception' => $vendorDir . '/hoa/consistency/Test/Unit/Exception.php',
'Hoa\\Consistency\\Test\\Unit\\Xcallable' => $vendorDir . '/hoa/consistency/Test/Unit/Xcallable.php',
'Hoa\\Consistency\\Xcallable' => $vendorDir . '/hoa/consistency/Xcallable.php',
'Hoa\\Event\\Bucket' => $vendorDir . '/hoa/event/Bucket.php',
'Hoa\\Event\\Event' => $vendorDir . '/hoa/event/Event.php',
'Hoa\\Event\\Exception' => $vendorDir . '/hoa/event/Exception.php',
'Hoa\\Event\\Listenable' => $vendorDir . '/hoa/event/Listenable.php',
'Hoa\\Event\\Listener' => $vendorDir . '/hoa/event/Listener.php',
'Hoa\\Event\\Listens' => $vendorDir . '/hoa/event/Listens.php',
'Hoa\\Event\\Source' => $vendorDir . '/hoa/event/Source.php',
'Hoa\\Event\\Test\\Unit\\Bucket' => $vendorDir . '/hoa/event/Test/Unit/Bucket.php',
'Hoa\\Event\\Test\\Unit\\Event' => $vendorDir . '/hoa/event/Test/Unit/Event.php',
'Hoa\\Event\\Test\\Unit\\Exception' => $vendorDir . '/hoa/event/Test/Unit/Exception.php',
'Hoa\\Event\\Test\\Unit\\Listenable' => $vendorDir . '/hoa/event/Test/Unit/Listenable.php',
'Hoa\\Event\\Test\\Unit\\Listener' => $vendorDir . '/hoa/event/Test/Unit/Listener.php',
'Hoa\\Event\\Test\\Unit\\Listens' => $vendorDir . '/hoa/event/Test/Unit/Listens.php',
'Hoa\\Event\\Test\\Unit\\Source' => $vendorDir . '/hoa/event/Test/Unit/Source.php',
'Hoa\\Event\\Test\\Unit\\_Listenable' => $vendorDir . '/hoa/event/Test/Unit/Listens.php',
'Hoa\\Exception\\Error' => $vendorDir . '/hoa/exception/Error.php',
'Hoa\\Exception\\Exception' => $vendorDir . '/hoa/exception/Exception.php',
'Hoa\\Exception\\Group' => $vendorDir . '/hoa/exception/Group.php',
'Hoa\\Exception\\Idle' => $vendorDir . '/hoa/exception/Idle.php',
'Hoa\\Exception\\Test\\Unit\\Error' => $vendorDir . '/hoa/exception/Test/Unit/Error.php',
'Hoa\\Exception\\Test\\Unit\\Exception' => $vendorDir . '/hoa/exception/Test/Unit/Exception.php',
'Hoa\\Exception\\Test\\Unit\\Group' => $vendorDir . '/hoa/exception/Test/Unit/Group.php',
'Hoa\\Exception\\Test\\Unit\\Idle' => $vendorDir . '/hoa/exception/Test/Unit/Idle.php',
'Masterminds\\HTML5' => $vendorDir . '/masterminds/html5/src/HTML5.php', 'Masterminds\\HTML5' => $vendorDir . '/masterminds/html5/src/HTML5.php',
'Masterminds\\HTML5\\Elements' => $vendorDir . '/masterminds/html5/src/HTML5/Elements.php', 'Masterminds\\HTML5\\Elements' => $vendorDir . '/masterminds/html5/src/HTML5/Elements.php',
'Masterminds\\HTML5\\Entities' => $vendorDir . '/masterminds/html5/src/HTML5/Entities.php', 'Masterminds\\HTML5\\Entities' => $vendorDir . '/masterminds/html5/src/HTML5/Entities.php',

View File

@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir); $baseDir = dirname($vendorDir);
return array( return array(
'e88992873b7765f9b5710cab95ba5dd7' => $vendorDir . '/hoa/consistency/Prelude.php',
'5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php', '5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
'2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php', '2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
'757772e28a0943a9afe83def8db95bdf' => $vendorDir . '/mf2/mf2/Mf2/Parser.php', '757772e28a0943a9afe83def8db95bdf' => $vendorDir . '/mf2/mf2/Mf2/Parser.php',

View File

@ -12,4 +12,7 @@ return array(
'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'), 'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'),
'Michelf\\' => array($vendorDir . '/michelf/php-markdown/Michelf'), 'Michelf\\' => array($vendorDir . '/michelf/php-markdown/Michelf'),
'Masterminds\\' => array($vendorDir . '/masterminds/html5/src'), 'Masterminds\\' => array($vendorDir . '/masterminds/html5/src'),
'Hoa\\Exception\\' => array($vendorDir . '/hoa/exception'),
'Hoa\\Event\\' => array($vendorDir . '/hoa/event'),
'Hoa\\Consistency\\' => array($vendorDir . '/hoa/consistency'),
); );

View File

@ -7,6 +7,7 @@ namespace Composer\Autoload;
class ComposerStaticInit444c3f31864f68a3f466e2c19837e185 class ComposerStaticInit444c3f31864f68a3f466e2c19837e185
{ {
public static $files = array ( public static $files = array (
'e88992873b7765f9b5710cab95ba5dd7' => __DIR__ . '/..' . '/hoa/consistency/Prelude.php',
'5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php', '5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php',
'2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php', '2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
'757772e28a0943a9afe83def8db95bdf' => __DIR__ . '/..' . '/mf2/mf2/Mf2/Parser.php', '757772e28a0943a9afe83def8db95bdf' => __DIR__ . '/..' . '/mf2/mf2/Mf2/Parser.php',
@ -35,6 +36,12 @@ class ComposerStaticInit444c3f31864f68a3f466e2c19837e185
'Michelf\\' => 8, 'Michelf\\' => 8,
'Masterminds\\' => 12, 'Masterminds\\' => 12,
), ),
'H' =>
array (
'Hoa\\Exception\\' => 14,
'Hoa\\Event\\' => 10,
'Hoa\\Consistency\\' => 16,
),
); );
public static $prefixDirsPsr4 = array ( public static $prefixDirsPsr4 = array (
@ -62,6 +69,18 @@ class ComposerStaticInit444c3f31864f68a3f466e2c19837e185
array ( array (
0 => __DIR__ . '/..' . '/masterminds/html5/src', 0 => __DIR__ . '/..' . '/masterminds/html5/src',
), ),
'Hoa\\Exception\\' =>
array (
0 => __DIR__ . '/..' . '/hoa/exception',
),
'Hoa\\Event\\' =>
array (
0 => __DIR__ . '/..' . '/hoa/event',
),
'Hoa\\Consistency\\' =>
array (
0 => __DIR__ . '/..' . '/hoa/consistency',
),
); );
public static $prefixesPsr0 = array ( public static $prefixesPsr0 = array (
@ -448,6 +467,37 @@ class ComposerStaticInit444c3f31864f68a3f466e2c19837e185
'HTMLPurifier_VarParser_Flexible' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Flexible.php', 'HTMLPurifier_VarParser_Flexible' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Flexible.php',
'HTMLPurifier_VarParser_Native' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Native.php', 'HTMLPurifier_VarParser_Native' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Native.php',
'HTMLPurifier_Zipper' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Zipper.php', 'HTMLPurifier_Zipper' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Zipper.php',
'Hoa\\Consistency\\Autoloader' => __DIR__ . '/..' . '/hoa/consistency/Autoloader.php',
'Hoa\\Consistency\\Consistency' => __DIR__ . '/..' . '/hoa/consistency/Consistency.php',
'Hoa\\Consistency\\Exception' => __DIR__ . '/..' . '/hoa/consistency/Exception.php',
'Hoa\\Consistency\\Test\\Unit\\Autoloader' => __DIR__ . '/..' . '/hoa/consistency/Test/Unit/Autoloader.php',
'Hoa\\Consistency\\Test\\Unit\\Consistency' => __DIR__ . '/..' . '/hoa/consistency/Test/Unit/Consistency.php',
'Hoa\\Consistency\\Test\\Unit\\Exception' => __DIR__ . '/..' . '/hoa/consistency/Test/Unit/Exception.php',
'Hoa\\Consistency\\Test\\Unit\\Xcallable' => __DIR__ . '/..' . '/hoa/consistency/Test/Unit/Xcallable.php',
'Hoa\\Consistency\\Xcallable' => __DIR__ . '/..' . '/hoa/consistency/Xcallable.php',
'Hoa\\Event\\Bucket' => __DIR__ . '/..' . '/hoa/event/Bucket.php',
'Hoa\\Event\\Event' => __DIR__ . '/..' . '/hoa/event/Event.php',
'Hoa\\Event\\Exception' => __DIR__ . '/..' . '/hoa/event/Exception.php',
'Hoa\\Event\\Listenable' => __DIR__ . '/..' . '/hoa/event/Listenable.php',
'Hoa\\Event\\Listener' => __DIR__ . '/..' . '/hoa/event/Listener.php',
'Hoa\\Event\\Listens' => __DIR__ . '/..' . '/hoa/event/Listens.php',
'Hoa\\Event\\Source' => __DIR__ . '/..' . '/hoa/event/Source.php',
'Hoa\\Event\\Test\\Unit\\Bucket' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Bucket.php',
'Hoa\\Event\\Test\\Unit\\Event' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Event.php',
'Hoa\\Event\\Test\\Unit\\Exception' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Exception.php',
'Hoa\\Event\\Test\\Unit\\Listenable' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Listenable.php',
'Hoa\\Event\\Test\\Unit\\Listener' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Listener.php',
'Hoa\\Event\\Test\\Unit\\Listens' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Listens.php',
'Hoa\\Event\\Test\\Unit\\Source' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Source.php',
'Hoa\\Event\\Test\\Unit\\_Listenable' => __DIR__ . '/..' . '/hoa/event/Test/Unit/Listens.php',
'Hoa\\Exception\\Error' => __DIR__ . '/..' . '/hoa/exception/Error.php',
'Hoa\\Exception\\Exception' => __DIR__ . '/..' . '/hoa/exception/Exception.php',
'Hoa\\Exception\\Group' => __DIR__ . '/..' . '/hoa/exception/Group.php',
'Hoa\\Exception\\Idle' => __DIR__ . '/..' . '/hoa/exception/Idle.php',
'Hoa\\Exception\\Test\\Unit\\Error' => __DIR__ . '/..' . '/hoa/exception/Test/Unit/Error.php',
'Hoa\\Exception\\Test\\Unit\\Exception' => __DIR__ . '/..' . '/hoa/exception/Test/Unit/Exception.php',
'Hoa\\Exception\\Test\\Unit\\Group' => __DIR__ . '/..' . '/hoa/exception/Test/Unit/Group.php',
'Hoa\\Exception\\Test\\Unit\\Idle' => __DIR__ . '/..' . '/hoa/exception/Test/Unit/Idle.php',
'Masterminds\\HTML5' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5.php', 'Masterminds\\HTML5' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5.php',
'Masterminds\\HTML5\\Elements' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5/Elements.php', 'Masterminds\\HTML5\\Elements' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5/Elements.php',
'Masterminds\\HTML5\\Entities' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5/Entities.php', 'Masterminds\\HTML5\\Entities' => __DIR__ . '/..' . '/masterminds/html5/src/HTML5/Entities.php',

View File

@ -178,6 +178,185 @@
"html" "html"
] ]
}, },
{
"name": "hoa/consistency",
"version": "1.17.05.02",
"version_normalized": "1.17.05.02",
"source": {
"type": "git",
"url": "https://github.com/hoaproject/Consistency.git",
"reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/hoaproject/Consistency/zipball/fd7d0adc82410507f332516faf655b6ed22e4c2f",
"reference": "fd7d0adc82410507f332516faf655b6ed22e4c2f",
"shasum": ""
},
"require": {
"hoa/exception": "~1.0",
"php": ">=5.5.0"
},
"require-dev": {
"hoa/stream": "~1.0",
"hoa/test": "~2.0"
},
"time": "2017-05-02T12:18:12+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Hoa\\Consistency\\": "."
},
"files": [
"Prelude.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Ivan Enderlin",
"email": "ivan.enderlin@hoa-project.net"
},
{
"name": "Hoa community",
"homepage": "https://hoa-project.net/"
}
],
"description": "The Hoa\\Consistency library.",
"homepage": "https://hoa-project.net/",
"keywords": [
"autoloader",
"callable",
"consistency",
"entity",
"flex",
"keyword",
"library"
]
},
{
"name": "hoa/event",
"version": "1.17.01.13",
"version_normalized": "1.17.01.13",
"source": {
"type": "git",
"url": "https://github.com/hoaproject/Event.git",
"reference": "6c0060dced212ffa3af0e34bb46624f990b29c54"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/hoaproject/Event/zipball/6c0060dced212ffa3af0e34bb46624f990b29c54",
"reference": "6c0060dced212ffa3af0e34bb46624f990b29c54",
"shasum": ""
},
"require": {
"hoa/consistency": "~1.0",
"hoa/exception": "~1.0"
},
"require-dev": {
"hoa/test": "~2.0"
},
"time": "2017-01-13T15:30:50+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Hoa\\Event\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Ivan Enderlin",
"email": "ivan.enderlin@hoa-project.net"
},
{
"name": "Hoa community",
"homepage": "https://hoa-project.net/"
}
],
"description": "The Hoa\\Event library.",
"homepage": "https://hoa-project.net/",
"keywords": [
"event",
"library",
"listener",
"observer"
]
},
{
"name": "hoa/exception",
"version": "1.17.01.16",
"version_normalized": "1.17.01.16",
"source": {
"type": "git",
"url": "https://github.com/hoaproject/Exception.git",
"reference": "091727d46420a3d7468ef0595651488bfc3a458f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/hoaproject/Exception/zipball/091727d46420a3d7468ef0595651488bfc3a458f",
"reference": "091727d46420a3d7468ef0595651488bfc3a458f",
"shasum": ""
},
"require": {
"hoa/consistency": "~1.0",
"hoa/event": "~1.0"
},
"require-dev": {
"hoa/test": "~2.0"
},
"time": "2017-01-16T07:53:27+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Hoa\\Exception\\": "."
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Ivan Enderlin",
"email": "ivan.enderlin@hoa-project.net"
},
{
"name": "Hoa community",
"homepage": "https://hoa-project.net/"
}
],
"description": "The Hoa\\Exception library.",
"homepage": "https://hoa-project.net/",
"keywords": [
"exception",
"library"
]
},
{ {
"name": "masterminds/html5", "name": "masterminds/html5",
"version": "2.6.0", "version": "2.6.0",

1
vendor/hoa/consistency/.State vendored Normal file
View File

@ -0,0 +1 @@
finalized

2
vendor/hoa/consistency/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/vendor/
/composer.lock

57
vendor/hoa/consistency/.travis.yml vendored Normal file
View File

@ -0,0 +1,57 @@
language: php
matrix:
include:
- php: 5.5
- php: 5.6
- php: 7.0
- php: 7.1
env:
- ENABLE_XDEBUG=true
- php: 7.1
env:
- ENABLE_DEVTOOLS=true
- php: nightly
- php: hhvm-3.12
sudo: required
dist: trusty
group: edge
- php: hhvm
sudo: required
dist: trusty
group: edge
allow_failures:
- php: nightly
- php: hhvm-3.12
- php: hhvm
fast_finish: true
os:
- linux
notifications:
irc: "chat.freenode.net#hoaproject"
sudo: false
env:
global:
- secure: "AAAAB3NzaC1yc2EAAAADAQABAAACAQDIf0Rf76Hhkflz5b9UzWjOjk4UlMU5ySk0VY3B4WdHDLWMMK7fBp1Aj9qXWEDwkuX/NbQP1gB8jQNo7i5uZEOfu7Mn2svPkBBtnmKmaJhk90xypM4lcpcdPi4e8kXUgkriNQLQ2bRe1qZIeF115FkuIvActq7iWKY1TVSZbO54cDKMifDZfH09cf4vpwrZJqwZG6PUnUcCYijgDy99HtfRvzf9xalO4yWm55ZEbJ/VNTHlq1EhK73QLdHC7MO+OQFcd5wEyMbNxBj/bDn/udgb0HsrDijComTg/oTdQJMspYDQYV3ZYvpGozTTCVQrVTYYTP9RCNstgJLHDv9fZZW6yRlw4yNsT7jIQRLs/7awTxOAvRlxqaxk0//ECVNhDgawVtlbEIKrqnM1N7QTm0gjE0HkWEzxE0QbgoZqlLFD6qCp6WVvIT3uGY/i4TkVy78wf3/fzCKbrf72kYSbxIOCxVtptOmrgAblNEpiA/uZ9IofR2p2iwiVY1xF/mzxV2M4zCw6WASrlDhkaL0IncEdRtBuV2WTpixmtjmNkE9h/90kzb5cKExU786gZmvyflYvqlNlcMo3dNsDnROjQCAUXGBw5+risdqTT295BGmlEdZUtcf0c6/zEGhR8B7CktWYLSgOL5mpGMVNEBzyzEwnIiWCvI3pGgoV3Z9UzSJWKQ=="
cache:
directories:
- vendor/
before_script:
- export PATH="$PATH:$HOME/.composer/vendor/bin"
- if [[ ! $ENABLE_XDEBUG ]]; then
phpenv config-rm xdebug.ini || echo "ext-xdebug is not available, cannot remove it.";
fi
script:
- composer install
- vendor/bin/hoa test:run
- if [[ $ENABLE_DEVTOOLS ]]; then
composer global require friendsofphp/php-cs-fixer;
vendor/bin/hoa devtools:cs --diff --dry-run .;
fi

260
vendor/hoa/consistency/Autoloader.php vendored Normal file
View File

@ -0,0 +1,260 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Consistency;
/**
* Class Hoa\Consistency\Autoloader.
*
* This class is a PSR-4 compliant autoloader.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Autoloader
{
/**
* Namespace prefixes to base directories.
*
* @var array
*/
protected $_namespacePrefixesToBaseDirectories = [];
/**
* Add a base directory for a namespace prefix.
*
* @param string $prefix Namespace prefix.
* @param string $baseDirectory Base directory for this prefix.
* @param bool $prepend Whether the prefix is prepended or
* appended to the prefix' stack.
* @return void
*/
public function addNamespace($prefix, $baseDirectory, $prepend = false)
{
$prefix = trim($prefix, '\\') . '\\';
$baseDirectory = rtrim($baseDirectory, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
if (false === isset($this->_namespacePrefixesToBaseDirectories[$prefix])) {
$this->_namespacePrefixesToBaseDirectories[$prefix] = [];
}
if (true === $prepend) {
array_unshift(
$this->_namespacePrefixesToBaseDirectories[$prefix],
$baseDirectory
);
} else {
array_push(
$this->_namespacePrefixesToBaseDirectories[$prefix],
$baseDirectory
);
}
return;
}
/**
* Try to load the entity file for a given entity name.
*
* @param string $entity Entity name to load.
* @return bool
*/
public function load($entity)
{
$entityPrefix = $entity;
$hasBaseDirectory = false;
while (false !== $pos = strrpos($entityPrefix, '\\')) {
$currentEntityPrefix = substr($entity, 0, $pos + 1);
$entityPrefix = rtrim($currentEntityPrefix, '\\');
$entitySuffix = substr($entity, $pos + 1);
$entitySuffixAsPath = str_replace('\\', '/', $entitySuffix);
if (false === $this->hasBaseDirectory($currentEntityPrefix)) {
continue;
}
$hasBaseDirectory = true;
foreach ($this->getBaseDirectories($currentEntityPrefix) as $baseDirectory) {
$file = $baseDirectory . $entitySuffixAsPath . '.php';
if (false !== $this->requireFile($file)) {
return $file;
}
}
}
if (true === $hasBaseDirectory &&
$entity === Consistency::getEntityShortestName($entity) &&
false !== $pos = strrpos($entity, '\\')) {
return $this->runAutoloaderStack(
$entity . '\\' . substr($entity, $pos + 1)
);
}
return null;
}
/**
* Require a file if exists.
*
* @param string $filename File name.
* @return bool
*/
public function requireFile($filename)
{
if (false === file_exists($filename)) {
return false;
}
require $filename;
return true;
}
/**
* Check whether at least one base directory exists for a namespace prefix.
*
* @param string $namespacePrefix Namespace prefix.
* @return bool
*/
public function hasBaseDirectory($namespacePrefix)
{
return isset($this->_namespacePrefixesToBaseDirectories[$namespacePrefix]);
}
/**
* Get declared base directories for a namespace prefix.
*
* @param string $namespacePrefix Namespace prefix.
* @return array
*/
public function getBaseDirectories($namespacePrefix)
{
if (false === $this->hasBaseDirectory($namespacePrefix)) {
return [];
}
return $this->_namespacePrefixesToBaseDirectories[$namespacePrefix];
}
/**
* Get loaded classes.
*
* @return array
*/
public static function getLoadedClasses()
{
return get_declared_classes();
}
/**
* Run the entire autoloader stack with a specific entity.
*
* @param string $entity Entity name to load.
* @return void
*/
public function runAutoloaderStack($entity)
{
return spl_autoload_call($entity);
}
/**
* Register the autoloader.
*
* @param bool $prepend Prepend this autoloader to the stack or not.
* @return bool
*/
public function register($prepend = false)
{
return spl_autoload_register([$this, 'load'], true, $prepend);
}
/**
* Unregister the autoloader.
*
* @return bool
*/
public function unregister()
{
return spl_autoload_unregister([$this, 'load']);
}
/**
* Get all registered autoloaders (not only from this library).
*
* @return array
*/
public function getRegisteredAutoloaders()
{
return spl_autoload_functions();
}
/**
* Dynamic new, a simple factory.
* It loads and constructs a class, with provided arguments.
*
* @param bool $classname Classname.
* @param array $arguments Arguments for the constructor.
* @return object
*/
public static function dnew($classname, array $arguments = [])
{
$classname = ltrim($classname, '\\');
if (false === Consistency::entityExists($classname, false)) {
spl_autoload_call($classname);
}
$class = new \ReflectionClass($classname);
if (empty($arguments) || false === $class->hasMethod('__construct')) {
return $class->newInstance();
}
return $class->newInstanceArgs($arguments);
}
}
/**
* Autoloader.
*/
$autoloader = new Autoloader();
$autoloader->addNamespace('Hoa', dirname(__DIR__));
$autoloader->register();

51
vendor/hoa/consistency/CHANGELOG.md vendored Normal file
View File

@ -0,0 +1,51 @@
# 1.17.05.02
* CI: Set up Travis. (Ivan Enderlin, 2017-03-08T09:52:17+01:00)
* Prelude: Remove the `(unset)` cast. (Ivan Enderlin, 2017-03-07T16:55:13+01:00)
# 1.17.01.10
* Quality: Happy new year! (Alexis von Glasow, 2017-01-09T21:38:10+01:00)
* Documentation: New `README.md` file. (Ivan Enderlin, 2016-10-19T16:27:31+02:00)
* Documentation: Fix `docs` and `source` links. (Ivan Enderlin, 2016-10-05T20:26:20+02:00)
* Documentation: Update `support` properties. (Ivan Enderlin, 2016-10-05T15:56:01+02:00)
* Consistency: `void` is a reserved keyword now. (Ivan Enderlin, 2016-09-02T11:06:18+02:00)
* Consistency: Remove `trait_exists` polyfill. (Ivan Enderlin, 2016-08-23T17:26:07+02:00)
# 1.16.03.03
* Add `STREAM_CRYPTO_METHOD_*` constants on PHP 5.5. (Metalaka, 2016-02-29T21:10:14+01:00)
* Composer: Fix `hoa/stream` dependency. (Ivan Enderlin, 2016-03-03T10:13:50+01:00)
# 1.16.01.14
* Test: Write cases for flex entity in autoloader. (Ivan Enderlin, 2016-01-14T10:45:08+01:00)
* Autoloader: Restrict loads to mapped entities. (Ivan Enderlin, 2016-01-14T10:38:21+01:00)
# 1.16.01.11
* Quality: Drop PHP5.4. (Ivan Enderlin, 2016-01-11T09:15:26+01:00)
* Quality: Run devtools:cs. (Ivan Enderlin, 2016-01-09T08:58:31+01:00)
* Core: Remove `Hoa\Core`. (Ivan Enderlin, 2016-01-09T08:03:33+01:00)
# 0.16.01.06
* Prelude: Introduce the prelude/preamble! (Ivan Enderlin, 2015-12-09T08:34:16+01:00)
* Consistency: Import last methods from `Hoa\Core`. (Ivan Enderlin, 2015-12-09T08:24:02+01:00)
* Quality: Fix CS. (Ivan Enderlin, 2015-12-09T06:43:22+01:00)
* Add a `.gitignore` file. (Metalaka, 2015-12-03T13:21:11+01:00)
* Autoloader: Propagate unknown entity on the stack. (Ivan Enderlin, 2015-12-03T11:04:57+01:00)
* Autoloader: Auto-register to support flex entity. (Ivan Enderlin, 2015-12-03T10:01:23+01:00)
* Composer: Force some files to load. (Ivan Enderlin, 2015-12-03T08:15:55+01:00)
* Test: Simplify `case_register`. (Ivan Enderlin, 2015-12-03T08:15:19+01:00)
* Consistency: Use a strict equality check on trait. (Ivan Enderlin, 2015-12-02T17:11:50+01:00)
* README: First draft. (Ivan Enderlin, 2015-12-02T08:40:34+01:00)
* Documentation: Update API documentation. (Ivan Enderlin, 2015-12-02T08:37:58+01:00)
* Autoloader: Support flex entities. (Ivan Enderlin, 2015-12-02T08:18:39+01:00)
* Test: Write test suite of `…nsistency\Autoloader`. (Ivan Enderlin, 2015-12-01T08:42:30+01:00)
* Test: Write test suite of `…sistency\Consistency`. (Ivan Enderlin, 2015-11-25T22:10:30+01:00)
* Test: Write test suite of `…onsistency\Xcallable`. (Ivan Enderlin, 2015-11-25T08:45:59+01:00)
* Test: Write test suite of `…onsistency\Exception`. (Ivan Enderlin, 2015-11-24T16:59:18+01:00)
* Split from `Hoa\Core`. (Ivan Enderlin, 2015-11-23T23:08:19+01:00)
(first snapshot)

363
vendor/hoa/consistency/Consistency.php vendored Normal file
View File

@ -0,0 +1,363 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Consistency
{
/**
* Class Hoa\Consistency\Consistency.
*
* This class is a collection of tools to ensure foreward and backward
* compatibility.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Consistency
{
/**
* Check if an entity exists (class, interface, trait).
*
* @param string $entityName Entity name.
* @param bool $autoloader Run autoloader if necessary.
* @return bool
*/
public static function entityExists($entityName, $autoloader = false)
{
return
class_exists($entityName, $autoloader) ||
interface_exists($entityName, false) ||
trait_exists($entityName, false);
}
/**
* Get the shortest name for an entity.
*
* @param string $entityName Entity name.
* @return string
*/
public static function getEntityShortestName($entityName)
{
$parts = explode('\\', $entityName);
$count = count($parts);
if (1 >= $count) {
return $entityName;
}
if ($parts[$count - 2] === $parts[$count - 1]) {
return implode('\\', array_slice($parts, 0, -1));
}
return $entityName;
}
/**
* Declare a flex entity (for nested library).
*
* @param string $entityName Entity name.
* @return bool
*/
public static function flexEntity($entityName)
{
return class_alias(
$entityName,
static::getEntityShortestName($entityName),
false
);
}
/**
* Whether a word is reserved or not.
*
* @param string $word Word.
* @return bool
*/
public static function isKeyword($word)
{
static $_list = [
// PHP keywords.
'__halt_compiler',
'abstract',
'and',
'array',
'as',
'bool',
'break',
'callable',
'case',
'catch',
'class',
'clone',
'const',
'continue',
'declare',
'default',
'die',
'do',
'echo',
'else',
'elseif',
'empty',
'enddeclare',
'endfor',
'endforeach',
'endif',
'endswitch',
'endwhile',
'eval',
'exit',
'extends',
'false',
'final',
'float',
'for',
'foreach',
'function',
'global',
'goto',
'if',
'implements',
'include',
'include_once',
'instanceof',
'insteadof',
'int',
'interface',
'isset',
'list',
'mixed',
'namespace',
'new',
'null',
'numeric',
'object',
'or',
'print',
'private',
'protected',
'public',
'require',
'require_once',
'resource',
'return',
'static',
'string',
'switch',
'throw',
'trait',
'true',
'try',
'unset',
'use',
'var',
'void',
'while',
'xor',
'yield',
// Compile-time constants.
'__class__',
'__dir__',
'__file__',
'__function__',
'__line__',
'__method__',
'__namespace__',
'__trait__'
];
return in_array(strtolower($word), $_list);
}
/**
* Whether an ID is a valid PHP identifier.
*
* @param string $id ID.
* @return bool
*/
public static function isIdentifier($id)
{
return 0 !== preg_match(
'#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x80-\xff]*$#',
$id
);
}
/**
* Register a register shutdown function.
* It may be analogous to a super static destructor.
*
* @param callable $callable Callable.
* @return bool
*/
public static function registerShutdownFunction($callable)
{
return register_shutdown_function($callable);
}
/**
* Get PHP executable.
*
* @return string
*/
public static function getPHPBinary()
{
if (defined('PHP_BINARY')) {
return PHP_BINARY;
}
if (isset($_SERVER['_'])) {
return $_SERVER['_'];
}
foreach (['', '.exe'] as $extension) {
if (file_exists($_ = PHP_BINDIR . DS . 'php' . $extension)) {
return realpath($_);
}
}
return null;
}
/**
* Generate an Universal Unique Identifier (UUID).
*
* @return string
*/
public static function uuid()
{
return sprintf(
'%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand(0, 0xffff),
mt_rand(0, 0xffff),
mt_rand(0, 0xffff),
mt_rand(0, 0x0fff) | 0x4000,
mt_rand(0, 0x3fff) | 0x8000,
mt_rand(0, 0xffff),
mt_rand(0, 0xffff),
mt_rand(0, 0xffff)
);
}
}
}
namespace
{
if (70000 > PHP_VERSION_ID && false === interface_exists('Throwable', false)) {
/**
* Implement a fake Throwable class, introduced in PHP7.0.
*/
interface Throwable
{
public function getMessage();
public function getCode();
public function getFile();
public function getLine();
public function getTrace();
public function getPrevious();
public function getTraceAsString();
public function __toString();
}
}
/**
* Define TLSv* constants, introduced in PHP 5.5.
*/
if (50600 > PHP_VERSION_ID) {
$define = function ($constantName, $constantValue, $case = false) {
if (!defined($constantName)) {
return define($constantName, $constantValue, $case);
}
return false;
};
$define('STREAM_CRYPTO_METHOD_TLSv1_0_SERVER', 8);
$define('STREAM_CRYPTO_METHOD_TLSv1_1_SERVER', 16);
$define('STREAM_CRYPTO_METHOD_TLSv1_2_SERVER', 32);
$define('STREAM_CRYPTO_METHOD_ANY_SERVER', 62);
$define('STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT', 9);
$define('STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT', 17);
$define('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT', 33);
$define('STREAM_CRYPTO_METHOD_ANY_CLIENT', 63);
}
if (!function_exists('curry')) {
/**
* Curry.
* Example:
* $c = curry('str_replace', , , 'foobar');
* var_dump($c('foo', 'baz')); // bazbar
* $c = curry('str_replace', 'foo', 'baz', );
* var_dump($c('foobarbaz')); // bazbarbaz
* Nested curries also work:
* $c1 = curry('str_replace', , , 'foobar');
* $c2 = curry($c1, 'foo', );
* var_dump($c2('baz')); // bazbar
* Obviously, as the first argument is a callable, we can combine this with
* \Hoa\Consistency\Xcallable ;-).
* The “…” character is the HORIZONTAL ELLIPSIS Unicode character (Unicode:
* 2026, UTF-8: E2 80 A6).
*
* @param mixed $callable Callable (two parts).
* @param ... ... Arguments.
* @return \Closure
*/
function curry($callable)
{
$arguments = func_get_args();
array_shift($arguments);
$ii = array_keys($arguments, , true);
return function () use ($callable, $arguments, $ii) {
return call_user_func_array(
$callable,
array_replace($arguments, array_combine($ii, func_get_args()))
);
};
}
}
/**
* Flex entity.
*/
Hoa\Consistency\Consistency::flexEntity('Hoa\Consistency\Consistency');
}

51
vendor/hoa/consistency/Exception.php vendored Normal file
View File

@ -0,0 +1,51 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Consistency;
use Hoa\Exception as HoaException;
/**
* Class \Hoa\Consistency\Exception.
*
* Extending the \Hoa\Exception\Exception class.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Exception extends HoaException
{
}

104
vendor/hoa/consistency/Prelude.php vendored Normal file
View File

@ -0,0 +1,104 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
if (false === defined('HOA')) {
define('HOA', true);
}
if (false === defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50400) {
throw new Exception(
'Hoa needs at least PHP5.4 to work; you have ' . phpversion() . '.'
);
}
require_once __DIR__ . DIRECTORY_SEPARATOR . 'Autoloader.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'Consistency.php';
$define = function ($constantName, $constantValue, $case = false) {
if (!defined($constantName)) {
return define($constantName, $constantValue, $case);
}
return false;
};
$define('SUCCEED', true);
$define('FAILED', false);
$define('…', '__hoa_core_fill');
$define('DS', DIRECTORY_SEPARATOR);
$define('PS', PATH_SEPARATOR);
$define('ROOT_SEPARATOR', ';');
$define('RS', ROOT_SEPARATOR);
$define('CRLF', "\r\n");
$define('OS_WIN', defined('PHP_WINDOWS_VERSION_PLATFORM'));
$define('S_64_BITS', PHP_INT_SIZE == 8);
$define('S_32_BITS', !S_64_BITS);
$define('PHP_INT_MIN', ~PHP_INT_MAX);
$define('PHP_FLOAT_MIN', (float) PHP_INT_MIN);
$define('PHP_FLOAT_MAX', (float) PHP_INT_MAX);
$define('π', M_PI);
$define('nil', null);
$define('_public', 1);
$define('_protected', 2);
$define('_private', 4);
$define('_static', 8);
$define('_abstract', 16);
$define('_pure', 32);
$define('_final', 64);
$define('_dynamic', ~_static);
$define('_concrete', ~_abstract);
$define('_overridable', ~_final);
$define('WITH_COMPOSER', class_exists('Composer\Autoload\ClassLoader', false) ||
('cli' === PHP_SAPI &&
file_exists(__DIR__ . DS . '..' . DS . '..' . DS . 'autoload.php')));
/**
* Alias of \Hoa\Consistency\Xcallable.
*
* @param mixed $call First callable part.
* @param mixed $able Second callable part (if needed).
* @return mixed
*/
if (!function_exists('xcallable')) {
function xcallable($call, $able = '')
{
if ($call instanceof Hoa\Consistency\Xcallable) {
return $call;
}
return new Hoa\Consistency\Xcallable($call, $able);
}
}

275
vendor/hoa/consistency/README.md vendored Normal file
View File

@ -0,0 +1,275 @@
<p align="center">
<img src="https://static.hoa-project.net/Image/Hoa.svg" alt="Hoa" width="250px" />
</p>
---
<p align="center">
<a href="https://travis-ci.org/hoaproject/Consistency"><img src="https://img.shields.io/travis/hoaproject/Consistency/master.svg" alt="Build status" /></a>
<a href="https://coveralls.io/github/hoaproject/Consistency?branch=master"><img src="https://img.shields.io/coveralls/hoaproject/Consistency/master.svg" alt="Code coverage" /></a>
<a href="https://packagist.org/packages/hoa/consistency"><img src="https://img.shields.io/packagist/dt/hoa/consistency.svg" alt="Packagist" /></a>
<a href="https://hoa-project.net/LICENSE"><img src="https://img.shields.io/packagist/l/hoa/consistency.svg" alt="License" /></a>
</p>
<p align="center">
Hoa is a <strong>modular</strong>, <strong>extensible</strong> and
<strong>structured</strong> set of PHP libraries.<br />
Moreover, Hoa aims at being a bridge between industrial and research worlds.
</p>
# Hoa\Consistency
[![Help on IRC](https://img.shields.io/badge/help-%23hoaproject-ff0066.svg)](https://webchat.freenode.net/?channels=#hoaproject)
[![Help on Gitter](https://img.shields.io/badge/help-gitter-ff0066.svg)](https://gitter.im/hoaproject/central)
[![Documentation](https://img.shields.io/badge/documentation-hack_book-ff0066.svg)](https://central.hoa-project.net/Documentation/Library/Consistency)
[![Board](https://img.shields.io/badge/organisation-board-ff0066.svg)](https://waffle.io/hoaproject/consistency)
This library provides a thin layer between PHP VMs and libraries to ensure
consistency accross VM versions and library versions.
[Learn more](https://central.hoa-project.net/Documentation/Library/Consistency).
## Installation
With [Composer](https://getcomposer.org/), to include this library into
your dependencies, you need to
require [`hoa/consistency`](https://packagist.org/packages/hoa/consistency):
```sh
$ composer require hoa/consistency '~1.0'
```
For more installation procedures, please read [the Source
page](https://hoa-project.net/Source.html).
## Testing
Before running the test suites, the development dependencies must be installed:
```sh
$ composer install
```
Then, to run all the test suites:
```sh
$ vendor/bin/hoa test:run
```
For more information, please read the [contributor
guide](https://hoa-project.net/Literature/Contributor/Guide.html).
## Quick usage
We propose a quick overview of how the consistency API ensures foreward and
backward compatibility, also an overview of the [PSR-4
autoloader](http://www.php-fig.org/psr/psr-4/) and the xcallable API.
### Foreward and backward compatibility
The `Hoa\Consistency\Consistency` class ensures foreward and backward
compatibility.
#### Example with keywords
The `Hoa\Consistency\Consistency::isKeyword` checks whether a specific word is
reserved by PHP or not. Let's say your current PHP version does not support the
`callable` keyword or type declarations such as `int`, `float`, `string` etc.,
the `isKeyword` method will tell you if they are reserved keywords: Not only
for your current PHP version, but maybe in an incoming version.
```php
$isKeyword = Hoa\Consistency\Consistency::isKeyword('yield');
```
It avoids to write algorithms that might break in the future or for your users
living on the edge.
#### Example with identifiers
PHP identifiers are defined by a regular expression. It might change in the
future. To prevent breaking your algorithms, you can use the
`Hoa\Consistency\Consistency::isIdentifier` method to check an identifier is
correct regarding current PHP version:
```php
$isValidIdentifier = Hoa\Consistency\Consistency::isIdentifier('foo');
```
#### Flexible entities
Flexible entities are very simple. If we declare `Foo\Bar\Bar` as a flexible
entity, we will be able to access it with the `Foo\Bar\Bar` name or `Foo\Bar`.
This is very useful if your architecture evolves but you want to keep the
backward compatibility. For instance, it often happens that you create a
`Foo\Bar\Exception` class in the `Foo/Bar/Exception.php` file. But after few
versions, you realise other exceptions need to be introduced, so you need an
`Exception` directory. In this case, `Foo\Bar\Exception` should move as
`Foo\Bar\Exception\Exception`. If this latter is declared as a flexible entity,
backward compatibility will be kept.
```php
Hoa\Consistency\Consistency::flexEntity('Foo\Bar\Exception\Exception');
```
Another example is the “entry-class” (informal naming).
`Hoa\Consistency\Consistency` is a good example. This is more convenient to
write `Hoa\Consistency` instead of `Hoa\Consistency\Consistency`. This is
possible because this is a flexible entity.
#### Throwable & co.
The `Throwable` interface has been introduced to represent a whole new exception
architecture in PHP. Thus, to be compatible with incoming PHP versions, you
might want to use this interface in some cases. Hopefully, the `Throwable`
interface will be created for you if it does not exists.
```php
try {
} catch (Throwable $e) {
}
```
### Autoloader
`Hoa\Consistency\Autoloader` is a [PSR-4
compatible](http://www.php-fig.org/psr/psr-4/) autoloader. It simply works as
follows:
* `addNamespace` is used to map a namespace prefix to a directory,
* `register` is used to register the autoloader.
The API also provides the `load` method to force the load of an entity,
`unregister` to unregister the autoloader, `getRegisteredAutoloaders` to get
a list of all registered autoloaders etc.
For instance, to map the `Foo\Bar` namespace to the `Source/` directory:
```php
$autoloader = new Hoa\Consistency\Autoloader();
$autoloader->addNamespace('Foo\Bar', 'Source');
$autoloader->register();
$baz = new Foo\Bar\Baz(); // automatically loaded!
```
### Xcallable
Xcallables are “extended callables”. It is a unified API to invoke callables of
any kinds, and also extends some Hoa's API (like
[`Hoa\Event`](https://central.hoa-project.net/Resource/Library/Event)
or
[`Hoa\Stream`](https://central.hoa-project.net/Resource/Library/Stream)). It
understands the following kinds:
* `'function'` as a string,
* `'class::method'` as a string,
* `'class', 'method'` as 2 string arguments,
* `$object, 'method'` as 2 arguments,
* `$object, ''` as 2 arguments, the “able” is unknown,
* `function (…) { … }` as a closure,
* `['class', 'method']` as an array of strings,
* `[$object, 'method']` as an array.
To use it, simply instanciate the `Hoa\Consistency\Xcallable` class and use it
as a function:
```php
$xcallable = new Hoa\Consistency\Xcallable('strtoupper');
var_dump($xcallable('foo'));
/**
* Will output:
* string(3) "FOO"
*/
```
The `Hoa\Consistency\Xcallable::distributeArguments` method invokes the callable
but the arguments are passed as an array:
```php
$xcallable->distributeArguments(['foo']);
```
This is also possible to get a unique hash of the callable:
```php
var_dump($xcallable->getHash());
/**
* Will output:
* string(19) "function#strtoupper"
*/
```
Finally, this is possible to get a reflection instance of the current callable
(can be of kind [`ReflectionFunction`](http://php.net/ReflectionFunction),
[`ReflectionClass`](http://php.net/ReflectionClass),
[`ReflectionMethod`](http://php.net/ReflectionMethod) or
[`ReflectionObject`](http://php.net/ReflectionObject)):
```php
var_dump($xcallable->getReflection());
/**
* Will output:
* object(ReflectionFunction)#42 (1) {
* ["name"]=>
* string(10) "strtoupper"
* }
*/
```
When the object is set but not the method, the latter will be deduced if
possible. If the object is of kind
[`Hoa\Stream`](http://central.hoa-project.net/Resource/Library/Stream), then
according to the type of the arguments given to the callable, the
`writeInteger`, `writeString`, `writeArray` etc. method will be used. If the
argument is of kind `Hoa\Event\Bucket`, then the method name will be deduced
based on the data contained inside the event bucket. This is very handy. For
instance, the following example will work seamlessly:
```php
Hoa\Event\Event::getEvent('hoa://Event/Exception')
->attach(new Hoa\File\Write('Exceptions.log'));
```
The `attach` method on `Hoa\Event\Event` transforms its argument as an
xcallable. In this particular case, the method to call is unknown, we only have
an object (of kind `Hoa\File\Write`). However, because this is a stream, the
method will be deduced according to the data contained in the event bucket fired
on the `hoa://Event/Exception` event channel.
## Documentation
The
[hack book of `Hoa\Consistency`](https://central.hoa-project.net/Documentation/Library/Consistency)
contains detailed information about how to use this library and how it works.
To generate the documentation locally, execute the following commands:
```sh
$ composer require --dev hoa/devtools
$ vendor/bin/hoa devtools:documentation --open
```
More documentation can be found on the project's website:
[hoa-project.net](https://hoa-project.net/).
## Getting help
There are mainly two ways to get help:
* On the [`#hoaproject`](https://webchat.freenode.net/?channels=#hoaproject)
IRC channel,
* On the forum at [users.hoa-project.net](https://users.hoa-project.net).
## Contribution
Do you want to contribute? Thanks! A detailed [contributor
guide](https://hoa-project.net/Literature/Contributor/Guide.html) explains
everything you need to know.
## License
Hoa is under the New BSD License (BSD-3-Clause). Please, see
[`LICENSE`](https://hoa-project.net/LICENSE) for details.

View File

@ -0,0 +1,342 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Consistency\Test\Unit;
use Hoa\Consistency\Autoloader as SUT;
use Hoa\Test;
/**
* Class \Hoa\Consistency\Test\Unit\Autoloader.
*
* Test suite of the autoloader.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Autoloader extends Test\Unit\Suite
{
public function case_add_namespace_prepend()
{
$this
->given(
$autoloader = new SUT(),
$prefix = 'Foo\Bar\\',
$baseDirectoryA = 'Source/Foo/Bar/',
$baseDirectoryB = 'Source/Foo/Bar/'
)
->when(
$autoloader->addNamespace($prefix, $baseDirectoryA),
$result = $autoloader->addNamespace($prefix, $baseDirectoryB)
)
->then
->boolean($autoloader->hasBaseDirectory($prefix))
->isTrue()
->array($autoloader->getBaseDirectories($prefix))
->isEqualTo([
$baseDirectoryB,
$baseDirectoryA
]);
}
public function case_add_namespace_append()
{
$this
->given(
$autoloader = new SUT(),
$prefix = 'Foo\Bar\\',
$baseDirectoryA = 'Source/Foo/Bar/',
$baseDirectoryB = 'Source/Foo/Bar/'
)
->when(
$autoloader->addNamespace($prefix, $baseDirectoryA),
$result = $autoloader->addNamespace($prefix, $baseDirectoryB)
)
->then
->boolean($autoloader->hasBaseDirectory($prefix))
->isTrue()
->array($autoloader->getBaseDirectories($prefix))
->isEqualTo([
$baseDirectoryA,
$baseDirectoryB
]);
}
public function case_add_namespace_with_invalid_prefix()
{
$this
->given(
$autoloader = new SUT(),
$prefix = '\\\\Foo\Bar',
$baseDirectory = 'Source/Foo/Bar/'
)
->when($result = $autoloader->addNamespace($prefix, $baseDirectory))
->then
->boolean($autoloader->hasBaseDirectory('Foo\Bar\\'))
->isTrue()
->array($autoloader->getBaseDirectories('Foo\Bar\\'))
->isEqualTo([$baseDirectory]);
}
public function case_add_namespace_with_invalid_base_directory()
{
$this
->given(
$autoloader = new SUT(),
$prefix = 'Foo\Bar\\',
$baseDirectory = 'Source/Foo/Bar'
)
->when($result = $autoloader->addNamespace($prefix, $baseDirectory))
->then
->boolean($autoloader->hasBaseDirectory('Foo\Bar\\'))
->isTrue()
->array($autoloader->getBaseDirectories('Foo\Bar\\'))
->isEqualTo(['Source/Foo/Bar/']);
}
public function case_add_namespace_with_crazy_invalid_base_directory()
{
$this
->given(
$autoloader = new SUT(),
$prefix = 'Foo\Bar\\',
$baseDirectory = 'Source/Foo/Bar/////'
)
->when($result = $autoloader->addNamespace($prefix, $baseDirectory))
->then
->boolean($autoloader->hasBaseDirectory('Foo\Bar\\'))
->isTrue()
->array($autoloader->getBaseDirectories('Foo\Bar\\'))
->isEqualTo(['Source/Foo/Bar/']);
}
public function case_load()
{
$this
->given(
$autoloader = new \Mock\Hoa\Consistency\Autoloader(),
$autoloader->addNamespace('Foo\Bar\\', 'Source/Foo/Bar/'),
$this->calling($autoloader)->requireFile = function ($file) {
return $file;
}
)
->when($result = $autoloader->load('Foo\Bar\Baz\Qux'))
->then
->string($result)
->isEqualTo('Source/Foo/Bar/Baz/Qux.php');
}
public function case_load_invalid_entity()
{
$this
->given($autoloader = new SUT())
->when($result = $autoloader->load('Foo'))
->then
->variable($result)
->isNull();
}
public function case_load_flex_entity()
{
$self = $this;
$this
->given(
$autoloader = new \Mock\Hoa\Consistency\Autoloader(),
$autoloader->addNamespace('Foo\Bar\\', 'Source/Foo/'),
$this->calling($autoloader)->runAutoloaderStack = function ($entity) use ($self, &$called) {
$called = true;
$self
->string($entity)
->isEqualTo('Foo\Bar\Baz\Baz');
return;
},
$autoloader->register()
)
->when($result = $autoloader->load('Foo\Bar\Baz'))
->then
->variable($result)
->isNull()
->boolean($called)
->isTrue();
}
public function case_load_unmapped_flex_entity()
{
$self = $this;
$this
->given(
$autoloader = new \Mock\Hoa\Consistency\Autoloader(),
$this->calling($autoloader)->runAutoloaderStack = function ($entity) use ($self, &$called) {
$called = true;
return;
},
$autoloader->register()
)
->when($result = $autoloader->load('Foo\Bar\Baz'))
->then
->variable($result)
->isNull()
->variable($called)
->isNull();
}
public function case_require_existing_file()
{
$this
->given(
$autoloader = new SUT(),
$this->function->file_exists = true,
$constantName = 'HOA_TEST_' . uniqid(),
$filename = 'hoa://Test/Vfs/Foo?type=file',
file_put_contents($filename, '<?php define("' . $constantName . '", "BAR");')
)
->when($result = $autoloader->requireFile($filename))
->then
->boolean($result)
->isTrue()
->string(constant($constantName))
->isEqualTo('BAR');
}
public function case_require_not_existing_file()
{
$this
->given(
$autoloader = new SUT(),
$this->function->file_exists = false
)
->when($result = $autoloader->requireFile('/hoa/flatland'))
->then
->boolean($result)
->isFalse();
}
public function case_has_not_base_directory()
{
$this
->given($autoloader = new SUT())
->when($result = $autoloader->hasBaseDirectory('foo'))
->then
->boolean($result)
->isFalse();
}
public function case_get_base_undeclared_namespace_prefix()
{
$this
->given($autoloader = new SUT())
->when($result = $autoloader->getBaseDirectories('foo'))
->then
->array($result)
->isEmpty();
}
public function case_dnew()
{
$this
->given($classname = 'Hoa\Consistency\Autoloader')
->when($result = SUT::dnew($classname))
->then
->object($result)
->isInstanceOf($classname);
}
public function case_dnew_unknown_class()
{
$this
->given($this->function->spl_autoload_call = null)
->exception(function () {
SUT::dnew('Foo');
})
->isInstanceOf('ReflectionException');
}
public function case_get_loaded_classes()
{
$this
->given(
$declaredClasses = get_declared_classes(),
$this->function->get_declared_classes = $declaredClasses
)
->when($result = SUT::getLoadedClasses())
->then
->array($result)
->isEqualTo($declaredClasses);
}
public function case_register()
{
$self = $this;
$this
->given($autoloader = new SUT())
->when($result = $autoloader->register())
->then
->boolean($result)
->isTrue()
->array($autoloader->getRegisteredAutoloaders())
->isEqualTo(spl_autoload_functions());
}
public function case_unregister()
{
$this
->given(
$autoloader = new SUT(),
$oldRegisteredAutoloaders = $autoloader->getRegisteredAutoloaders()
)
->when($result = $autoloader->register())
->then
->boolean($result)
->isTrue()
->integer(count($autoloader->getRegisteredAutoloaders()))
->isEqualTo(count($oldRegisteredAutoloaders) + 1)
->when($result = $autoloader->unregister())
->then
->boolean($result)
->isTrue()
->array($autoloader->getRegisteredAutoloaders())
->isEqualTo($oldRegisteredAutoloaders);
}
}

View File

@ -0,0 +1,325 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Consistency\Test\Unit;
use Hoa\Consistency\Consistency as SUT;
use Hoa\Test;
/**
* Class \Hoa\Consistency\Test\Unit\Consistency.
*
* Test suite of the consistency class.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Consistency extends Test\Unit\Suite
{
protected function _entity_exists_with_xxx($class, $interface, $trait)
{
$this
->given(
$this->function->class_exists = $class,
$this->function->interface_exists = $interface,
$this->function->trait_exists = $trait
)
->when($result = SUT::entityExists('foo'))
->then
->boolean($result)
->isTrue();
}
public function case_entity_exists_with_class()
{
return $this->_entity_exists_with_xxx(true, false, false);
}
public function case_entity_exists_with_interface()
{
return $this->_entity_exists_with_xxx(false, true, false);
}
public function case_entity_exists_with_trait()
{
return $this->_entity_exists_with_xxx(false, false, true);
}
public function case_entity_does_not_exists()
{
$this
->given(
$this->function->class_exists = false,
$this->function->interface_exists = false,
$this->function->trait_exists = false
)
->when($result = SUT::entityExists('foo'))
->then
->boolean($result)
->isFalse();
}
public function case_get_entity_shortest_name()
{
$this
->when($result = SUT::getEntityShortestName('Foo\Bar\Bar'))
->then
->string($result)
->isEqualTo('Foo\Bar');
}
public function case_get_entity_shortest_name_with_already_the_shortest()
{
$this
->when($result = SUT::getEntityShortestName('Foo\Bar'))
->then
->string($result)
->isEqualTo('Foo\Bar');
}
public function case_get_entity_shortest_name_with_no_namespace()
{
$this
->when($result = SUT::getEntityShortestName('Foo'))
->then
->string($result)
->isEqualTo('Foo');
}
public function case_is_keyword()
{
$this
->given(
$keywords = [
'__HALT_COMPILER',
'abstract',
'and',
'array',
'as',
'bool',
'break',
'callable',
'case',
'catch',
'class',
'clone',
'const',
'continue',
'declare',
'default',
'die',
'do',
'echo',
'else',
'elseif',
'empty',
'enddeclare',
'endfor',
'endforeach',
'endif',
'endswitch',
'endwhile',
'eval',
'exit',
'extends',
'false',
'final',
'float',
'for',
'foreach',
'function',
'global',
'goto',
'if',
'implements',
'include',
'include_once',
'instanceof',
'insteadof',
'int',
'interface',
'isset',
'list',
'mixed',
'namespace',
'new',
'null',
'numeric',
'object',
'or',
'print',
'private',
'protected',
'public',
'require',
'require_once',
'resource',
'return',
'static',
'string',
'switch',
'throw',
'trait',
'true',
'try',
'unset',
'use',
'var',
'void',
'while',
'xor',
'yield',
'__CLASS__',
'__DIR__',
'__FILE__',
'__FUNCTION__',
'__LINE__',
'__METHOD__',
'__NAMESPACE__',
'__TRAIT__'
]
)
->when(function () use ($keywords) {
foreach ($keywords as $keyword) {
$this
->boolean(SUT::isKeyword($keyword))
->isTrue();
}
});
}
public function case_is_identifier()
{
$this
->given($_identifier = $this->realdom->regex('#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x80-\xff]*$#'))
->when(function () use ($_identifier) {
foreach ($this->sampleMany($_identifier, 1000) as $identifier) {
$this
->boolean(SUT::isIdentifier($identifier))
->isTrue();
}
});
}
public function case_register_shutdown_function()
{
$self = $this;
$this
->given(
$callable = function () {
},
$this->function->register_shutdown_function = function ($_callable) use (&$called, $self, &$callable) {
$called = true;
$self
->variable($_callable)
->isEqualTo($callable);
return true;
}
)
->when($result = SUT::registerShutdownFunction($callable))
->then
->boolean($result)
->isTrue();
}
public function case_get_php_binary_with_constant()
{
$this
->given($this->constant->PHP_BINARY = '/foo/php')
->when($result = SUT::getPHPBinary())
->then
->string($result)
->isEqualTo('/foo/php');
}
public function case_get_php_binary_with_server()
{
$this
->given(
$this->function->defined = false,
$_SERVER['_'] = '/bar/php'
)
->when($result = SUT::getPHPBinary())
->then
->string($result)
->isEqualTo('/bar/php');
}
public function case_get_php_binary_with_bin_directory()
{
unset($_SERVER['_']);
$this
->given(
$this->function->defined = false,
$this->function->file_exists = true,
$this->function->realpath = '/baz/php'
)
->when($result = SUT::getPHPBinary())
->then
->string($result)
->isEqualTo('/baz/php');
}
public function case_uuid()
{
$this
->given($this->function->mt_rand = 42)
->when($result = SUT::uuid())
->then
->string($result)
->isEqualTo('002a002a-002a-402a-802a-002a002a002a');
}
public function case_uuid_all_differents()
{
$this
->when(function () {
$uuids = [];
for ($i = 0; $i < 10000; ++$i) {
$uuids[] = SUT::uuid();
}
$this
->integer(count($uuids))
->isEqualTo(count(array_unique($uuids)));
});
}
}

View File

@ -0,0 +1,60 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Consistency\Test\Unit;
use Hoa\Consistency\Exception as SUT;
use Hoa\Test;
/**
* Class \Hoa\Consistency\Test\Unit\Exception.
*
* Test suite of the exception.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Exception extends Test\Unit\Suite
{
public function case_hoa_exception()
{
$this
->when($result = new SUT('foo', 0))
->then
->object($result)
->isInstanceOf('Hoa\Exception\Exception');
}
}

View File

@ -0,0 +1,341 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Consistency\Test\Unit;
use Hoa\Consistency\Xcallable as SUT;
use Hoa\Test;
/**
* Class \Hoa\Consistency\Test\Unit\Xcallable.
*
* Test suite of the xcallable class.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Xcallable extends Test\Unit\Suite
{
public function case_form_function()
{
$this
->when($result = new SUT('strtoupper'))
->then
->string($result('foo'))
->isEqualTo('FOO')
->string($result->getValidCallback())
->isEqualTo('strtoupper')
->string($result->getHash())
->isEqualTo('function#strtoupper')
->isEqualTo($result . '')
->object($reflection = $result->getReflection())
->isInstanceOf('ReflectionFunction')
->string($reflection->getName())
->isEqualTo('strtoupper');
}
public function case_form_class___method()
{
$this
->when($result = new SUT(__CLASS__ . '::strtoupper'))
->then
->string($result('foo'))
->isEqualTo('FOO')
->array($result->getValidCallback())
->isEqualTo([__CLASS__, 'strtoupper'])
->string($result->getHash())
->isEqualTo('class#' . __CLASS__ . '::strtoupper')
->isEqualTo($result . '')
->object($reflection = $result->getReflection())
->isInstanceOf('ReflectionMethod')
->string($reflection->getName())
->isEqualTo('strtoupper');
}
public function case_form_class_method()
{
$this
->when($result = new SUT(__CLASS__, 'strtoupper'))
->then
->string($result('foo'))
->isEqualTo('FOO')
->array($result->getValidCallback())
->isEqualTo([__CLASS__, 'strtoupper'])
->string($result->getHash())
->isEqualTo('class#' . __CLASS__ . '::strtoupper')
->isEqualTo($result . '')
->object($reflection = $result->getReflection())
->isInstanceOf('ReflectionMethod')
->string($reflection->getName())
->isEqualTo('strtoupper');
}
public function case_form_object_method()
{
$this
->when($result = new SUT($this, 'strtolower'))
->then
->string($result('FOO'))
->isEqualTo('foo')
->array($result->getValidCallback())
->isEqualTo([$this, 'strtolower'])
->string($result->getHash())
->matches(
'/^object\([^:]+\)#' .
preg_quote(__CLASS__) .
'::strtolower$/'
)
->isEqualTo($result . '')
->object($reflection = $result->getReflection())
->isInstanceOf('ReflectionMethod')
->string($reflection->getName())
->isEqualTo('strtolower');
}
public function case_form_object_invoke()
{
$this
->when($result = new SUT($this))
->then
->string($result('foo'))
->isEqualTo('FOO')
->array($result->getValidCallback())
->isEqualTo([$this, '__invoke'])
->string($result->getHash())
->matches(
'/^object\([^:]+\)#' .
preg_quote(__CLASS__) .
'::__invoke$/'
)
->isEqualTo($result . '')
->object($reflection = $result->getReflection())
->isInstanceOf('ReflectionMethod')
->string($reflection->getName())
->isEqualTo('__invoke');
}
public function case_form_closure()
{
$this
->given(
$closure = function ($string) {
return strtoupper($string);
}
)
->when($result = new SUT($closure))
->then
->string($result('foo'))
->isEqualTo('FOO')
->object($result->getValidCallback())
->isIdenticalTo($closure)
->string($result->getHash())
->matches('/^closure\([^:]+\)$/')
->isEqualTo($result . '')
->object($reflection = $result->getReflection())
->isInstanceOf('ReflectionFunction')
->string($reflection->getName())
->isEqualTo('Hoa\Consistency\Test\Unit\{closure}');
}
public function case_form_array_of_class_method()
{
$this
->when($result = new SUT([__CLASS__, 'strtoupper']))
->then
->string($result('foo'))
->isEqualTo('FOO')
->array($result->getValidCallback())
->isEqualTo([__CLASS__, 'strtoupper'])
->string($result->getHash())
->isEqualTo('class#' . __CLASS__ . '::strtoupper')
->isEqualTo($result . '')
->object($reflection = $result->getReflection())
->isInstanceOf('ReflectionMethod')
->string($reflection->getName())
->isEqualTo('strtoupper');
}
public function case_form_array_of_object_method()
{
$this
->when($result = new SUT([$this, 'strtolower']))
->then
->string($result('FOO'))
->isEqualTo('foo')
->array($result->getValidCallback())
->isEqualTo([$this, 'strtolower'])
->string($result->getHash())
->matches(
'/^object\([^:]+\)#' .
preg_quote(__CLASS__) .
'::strtolower$/'
)
->isEqualTo($result . '')
->object($reflection = $result->getReflection())
->isInstanceOf('ReflectionMethod')
->string($reflection->getName())
->isEqualTo('strtolower');
}
public function case_form_able_not_a_string()
{
$this
->exception(function () {
new SUT(__CLASS__, 123);
})
->isInstanceOf('Hoa\Consistency\Exception');
}
public function case_form_function_not_defined()
{
$this
->exception(function () {
new SUT('__hoa_test_undefined_function__');
})
->isInstanceOf('Hoa\Consistency\Exception');
}
public function case_form_able_cannot_be_deduced()
{
$this
->given($this->function->method_exists = false)
->exception(function () {
new SUT($this);
})
->isInstanceOf('Hoa\Consistency\Exception');
}
public function case_invoke()
{
$this
->given(
$callable = new SUT(
function ($x, $y, $z) {
return [$x, $y, $z];
}
)
)
->when($result = $callable(7, [4.2], 'foo'))
->then
->array($result)
->isEqualTo([7, [4.2], 'foo']);
}
public function case_distribute_arguments()
{
$this
->given(
$callable = new SUT(
function ($x, $y, $z) {
return [$x, $y, $z];
}
)
)
->when($result = $callable->distributeArguments([7, [4.2], 'foo']))
->then
->array($result)
->isEqualTo([7, [4.2], 'foo']);
}
protected function _get_valid_callback_stream_xxx($argument, $method)
{
$this
->given(
$stream = new \Mock\Hoa\Stream\IStream\Out(),
$arguments = [$argument],
$xcallable = new SUT($stream)
)
->when($result = $xcallable->getValidCallback($arguments))
->then
->array($result)
->isEqualTo([$stream, $method]);
}
public function case_get_valid_callback_stream_character()
{
return $this->_get_valid_callback_stream_xxx('f', 'writeCharacter');
}
public function case_get_valid_callback_stream_string()
{
return $this->_get_valid_callback_stream_xxx('foo', 'writeString');
}
public function case_get_valid_callback_stream_boolean()
{
return $this->_get_valid_callback_stream_xxx(true, 'writeBoolean');
}
public function case_get_valid_callback_stream_integer()
{
return $this->_get_valid_callback_stream_xxx(7, 'writeInteger');
}
public function case_get_valid_callback_stream_array()
{
return $this->_get_valid_callback_stream_xxx([4, 2], 'writeArray');
}
public function case_get_valid_callback_stream_float()
{
return $this->_get_valid_callback_stream_xxx(4.2, 'writeFloat');
}
public function case_get_valid_callback_stream_other()
{
return $this->_get_valid_callback_stream_xxx($this, 'writeAll');
}
public static function strtoupper($string)
{
return strtoupper($string);
}
public function strtolower($string)
{
return strtolower($string);
}
public function __invoke($string)
{
return strtoupper($string);
}
public function __toString()
{
return 'hello';
}
}

316
vendor/hoa/consistency/Xcallable.php vendored Normal file
View File

@ -0,0 +1,316 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Consistency;
use Hoa\Event;
use Hoa\Stream;
/**
* Class Hoa\Consistency\Xcallable.
*
* Build a callable object, i.e. function, class::method, object->method or
* closure, they all have the same behaviour. This callable is an extension of
* native PHP callable (aka callback) to integrate Hoa's structures.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Xcallable
{
/**
* Callback, with the PHP format.
*
* @var mixed
*/
protected $_callback = null;
/**
* Callable hash.
*
* @var string
*/
protected $_hash = null;
/**
* Build a callback.
* Accepted forms:
* * `'function'`,
* * `'class::method'`,
* * `'class', 'method'`,
* * `$object, 'method'`,
* * `$object, ''`,
* * `function (…) { … }`,
* * `['class', 'method']`,
* * `[$object, 'method']`.
*
* @param mixed $call First callable part.
* @param mixed $able Second callable part (if needed).
*/
public function __construct($call, $able = '')
{
if ($call instanceof \Closure) {
$this->_callback = $call;
return;
}
if (!is_string($able)) {
throw new Exception(
'Bad callback form; the able part must be a string.',
0
);
}
if ('' === $able) {
if (is_string($call)) {
if (false === strpos($call, '::')) {
if (!function_exists($call)) {
throw new Exception(
'Bad callback form; function %s does not exist.',
1,
$call
);
}
$this->_callback = $call;
return;
}
list($call, $able) = explode('::', $call);
} elseif (is_object($call)) {
if ($call instanceof Stream\IStream\Out) {
$able = null;
} elseif (method_exists($call, '__invoke')) {
$able = '__invoke';
} else {
throw new Exception(
'Bad callback form; an object but without a known ' .
'method.',
2
);
}
} elseif (is_array($call) && isset($call[0])) {
if (!isset($call[1])) {
return $this->__construct($call[0]);
}
return $this->__construct($call[0], $call[1]);
} else {
throw new Exception(
'Bad callback form.',
3
);
}
}
$this->_callback = [$call, $able];
return;
}
/**
* Call the callable.
*
* @param ...
* @return mixed
*/
public function __invoke()
{
$arguments = func_get_args();
$valid = $this->getValidCallback($arguments);
return call_user_func_array($valid, $arguments);
}
/**
* Distribute arguments according to an array.
*
* @param array $arguments Arguments.
* @return mixed
*/
public function distributeArguments(array $arguments)
{
return call_user_func_array([$this, '__invoke'], $arguments);
}
/**
* Get a valid callback in the PHP meaning.
*
* @param array &$arguments Arguments (could determine method on an
* object if not precised).
* @return mixed
*/
public function getValidCallback(array &$arguments = [])
{
$callback = $this->_callback;
$head = null;
if (isset($arguments[0])) {
$head = &$arguments[0];
}
// If method is undetermined, we find it (we understand event bucket and
// stream).
if (null !== $head &&
is_array($callback) &&
null === $callback[1]) {
if ($head instanceof Event\Bucket) {
$head = $head->getData();
}
switch ($type = gettype($head)) {
case 'string':
if (1 === strlen($head)) {
$method = 'writeCharacter';
} else {
$method = 'writeString';
}
break;
case 'boolean':
case 'integer':
case 'array':
$method = 'write' . ucfirst($type);
break;
case 'double':
$method = 'writeFloat';
break;
default:
$method = 'writeAll';
$head = $head . "\n";
}
$callback[1] = $method;
}
return $callback;
}
/**
* Get hash.
* Will produce:
* * function#…;
* * class#…::…;
* * object()#…::…;
* * closure().
*
* @return string
*/
public function getHash()
{
if (null !== $this->_hash) {
return $this->_hash;
}
$_ = &$this->_callback;
if (is_string($_)) {
return $this->_hash = 'function#' . $_;
}
if (is_array($_)) {
return
$this->_hash =
(is_object($_[0])
? 'object(' . spl_object_hash($_[0]) . ')' .
'#' . get_class($_[0])
: 'class#' . $_[0]) .
'::' .
(null !== $_[1]
? $_[1]
: '???');
}
return $this->_hash = 'closure(' . spl_object_hash($_) . ')';
}
/**
* Get appropriated reflection instance.
*
* @param ...
* @return \Reflector
*/
public function getReflection()
{
$arguments = func_get_args();
$valid = $this->getValidCallback($arguments);
if (is_string($valid)) {
return new \ReflectionFunction($valid);
}
if ($valid instanceof \Closure) {
return new \ReflectionFunction($valid);
}
if (is_array($valid)) {
if (is_string($valid[0])) {
if (false === method_exists($valid[0], $valid[1])) {
return new \ReflectionClass($valid[0]);
}
return new \ReflectionMethod($valid[0], $valid[1]);
}
$object = new \ReflectionObject($valid[0]);
if (null === $valid[1]) {
return $object;
}
return $object->getMethod($valid[1]);
}
}
/**
* Return the hash.
*
* @return string
*/
public function __toString()
{
return $this->getHash();
}
}

45
vendor/hoa/consistency/composer.json vendored Normal file
View File

@ -0,0 +1,45 @@
{
"name" : "hoa/consistency",
"description": "The Hoa\\Consistency library.",
"type" : "library",
"keywords" : ["library", "consistency", "autoloader", "entity", "flex",
"keyword", "callable"],
"homepage" : "https://hoa-project.net/",
"license" : "BSD-3-Clause",
"authors" : [
{
"name" : "Ivan Enderlin",
"email": "ivan.enderlin@hoa-project.net"
},
{
"name" : "Hoa community",
"homepage": "https://hoa-project.net/"
}
],
"support": {
"email" : "support@hoa-project.net",
"irc" : "irc://chat.freenode.net/hoaproject",
"forum" : "https://users.hoa-project.net/",
"docs" : "https://central.hoa-project.net/Documentation/Library/Consistency",
"source": "https://central.hoa-project.net/Resource/Library/Consistency"
},
"require": {
"php" : ">=5.5.0",
"hoa/exception": "~1.0"
},
"require-dev": {
"hoa/stream": "~1.0",
"hoa/test" : "~2.0"
},
"autoload": {
"psr-4": {
"Hoa\\Consistency\\": "."
},
"files": ["Prelude.php"]
},
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
}
}

1
vendor/hoa/event/.State vendored Normal file
View File

@ -0,0 +1 @@
finalized

2
vendor/hoa/event/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/vendor/
/composer.lock

136
vendor/hoa/event/Bucket.php vendored Normal file
View File

@ -0,0 +1,136 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Event;
/**
* Class \Hoa\Event\Bucket.
*
* This class is the object which is transmit through event channels.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Bucket
{
/**
* Source object.
*
* @var \Hoa\Event\Source
*/
protected $_source = null;
/**
* Data.
*
* @var mixed
*/
protected $_data = null;
/**
* Set data.
*
* @param mixed $data Data.
*/
public function __construct($data = null)
{
$this->setData($data);
return;
}
/**
* Send this object on the event channel.
*
* @param string $eventId Event ID.
* @param \Hoa\Event\Source $source Source.
* @return void
*/
public function send($eventId, Source $source)
{
return Event::notify($eventId, $source, $this);
}
/**
* Set source.
*
* @param \Hoa\Event\Source $source Source.
* @return \Hoa\Event\Source
*/
public function setSource(Source $source)
{
$old = $this->_source;
$this->_source = $source;
return $old;
}
/**
* Get source.
*
* @return \Hoa\Event\Source
*/
public function getSource()
{
return $this->_source;
}
/**
* Set data.
*
* @param mixed $data Data.
* @return mixed
*/
public function setData($data)
{
$old = $this->_data;
$this->_data = $data;
return $old;
}
/**
* Get data.
*
* @return mixed
*/
public function getData()
{
return $this->_data;
}
}

44
vendor/hoa/event/CHANGELOG.md vendored Normal file
View File

@ -0,0 +1,44 @@
# 1.17.01.13
* Quality: Happy new year! (Alexis von Glasow, 2017-01-11T23:09:35+01:00)
# 1.16.11.19
* Documentation: New `README.md` file. (Ivan Enderlin, 2016-10-18T16:34:43+02:00)
* Documentation: Update `support` properties. (Ivan Enderlin, 2016-10-05T20:36:30+02:00)
# 1.16.03.15
* Fix a typo (Metalaka, 2016-01-28T09:05:40+01:00)
* CHANGELOG: Add a missing newline. (Ivan Enderlin, 2016-01-11T09:37:32+01:00)
# 1.16.01.11
* Quality: Drop PHP5.4. (Ivan Enderlin, 2016-01-11T09:15:26+01:00)
* Quality: Run devtools:cs. (Ivan Enderlin, 2016-01-09T09:01:10+01:00)
* Core: Remove `Hoa\Core`. (Ivan Enderlin, 2016-01-09T08:14:54+01:00)
* Consistency: Use `Hoa\Consistency`. (Ivan Enderlin, 2015-12-08T11:10:00+01:00)
* Documentation: Fix typos. (Ivan Enderlin, 2015-11-23T22:05:56+01:00)
* Exception: Use `Hoa\Exception`. (Ivan Enderlin, 2015-11-20T07:40:34+01:00)
# 0.15.11.23
* Documentation: Fix typos. (Ivan Enderlin, 2015-11-23T22:05:56+01:00)
* Exception: Use `Hoa\Exception`. (Ivan Enderlin, 2015-11-20T07:40:34+01:00)
* Test: Fix a conflict between 2 test suites. (Ivan Enderlin, 2015-11-23T21:29:28+01:00)
* Test: Write test suite for `Hoa\Event\Listens`. (Ivan Enderlin, 2015-11-23T21:25:49+01:00)
* Listener: Add the `Listens` trait. (Ivan Enderlin, 2015-11-20T06:45:11+01:00)
* Documentation: Fix a typo. (Ivan Enderlin, 2015-11-23T13:01:56+01:00)
* Improve readability by adding constants to registered events container. (Metalaka, 2015-11-20T19:53:32+01:00)
* Add a `.gitignore` file. (Metalaka, 2015-11-20T19:37:52+01:00)
* README: Complete description and add usage. (Ivan Enderlin, 2015-11-13T08:43:08+01:00)
* Test: Write test suite for `Hoa\Event\Event`. (Ivan Enderlin, 2015-11-11T17:04:41+01:00)
* Test: Write test suite for `Hoa\Event\Exception`. (Ivan Enderlin, 2015-11-11T16:46:12+01:00)
* Composer: Add a keyword. (Ivan Enderlin, 2015-11-11T13:38:35+01:00)
* Test: Write test suite for `Hoa\Event\Listener`. (Ivan Enderlin, 2015-11-11T13:27:40+01:00)
* Test: Write test suite for `Hoa\Event\Source`. (Ivan Enderlin, 2015-11-10T21:56:37+01:00)
* Test: Write test suite for `Hoa\Event\Listenable`. (Ivan Enderlin, 2015-11-10T21:56:24+01:00)
* Test: Write test suite for `Hoa\Event\Bucket`. (Ivan Enderlin, 2015-11-10T21:55:45+01:00)
* Split from `Hoa\Core`. (Ivan Enderlin, 2015-11-10T21:28:31+01:00)
(first snapshot)

266
vendor/hoa/event/Event.php vendored Normal file
View File

@ -0,0 +1,266 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Event;
use Hoa\Consistency;
/**
* Class \Hoa\Event\Event.
*
* Events are asynchronous at registration, anonymous at use (until we
* receive a bucket) and useful to largely spread data through components
* without any known connection between them.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Event
{
/**
* Event ID key.
*
* @const int
*/
const KEY_EVENT = 0;
/**
* Source object key.
*
* @const int
*/
const KEY_SOURCE = 1;
/**
* Static register of all observable objects, i.e. \Hoa\Event\Source
* object, i.e. object that can send event.
*
* @var array
*/
private static $_register = [];
/**
* Callables, i.e. observer objects.
*
* @var array
*/
protected $_callable = [];
/**
* Privatize the constructor.
*
*/
private function __construct()
{
return;
}
/**
* Manage multiton of events, with the principle of asynchronous
* attachments.
*
* @param string $eventId Event ID.
* @return \Hoa\Event\Event
*/
public static function getEvent($eventId)
{
if (!isset(self::$_register[$eventId][self::KEY_EVENT])) {
self::$_register[$eventId] = [
self::KEY_EVENT => new self(),
self::KEY_SOURCE => null
];
}
return self::$_register[$eventId][self::KEY_EVENT];
}
/**
* Declare a new object in the observable collection.
* Note: Hoa's libraries use hoa://Event/AnID for their observable objects;
*
* @param string $eventId Event ID.
* @param \Hoa\Event\Source|string $source Observable object or class.
* @return void
* @throws \Hoa\Event\Exception
*/
public static function register($eventId, $source)
{
if (true === self::eventExists($eventId)) {
throw new Exception(
'Cannot redeclare an event with the same ID, i.e. the event ' .
'ID %s already exists.',
0,
$eventId
);
}
if (is_object($source) && !($source instanceof Source)) {
throw new Exception(
'The source must implement \Hoa\Event\Source ' .
'interface; given %s.',
1,
get_class($source)
);
} else {
$reflection = new \ReflectionClass($source);
if (false === $reflection->implementsInterface('\Hoa\Event\Source')) {
throw new Exception(
'The source must implement \Hoa\Event\Source ' .
'interface; given %s.',
2,
$source
);
}
}
if (!isset(self::$_register[$eventId][self::KEY_EVENT])) {
self::$_register[$eventId][self::KEY_EVENT] = new self();
}
self::$_register[$eventId][self::KEY_SOURCE] = $source;
return;
}
/**
* Undeclare an object in the observable collection.
*
* @param string $eventId Event ID.
* @param bool $hard If false, just delete the source, else,
* delete source and attached callables.
* @return void
*/
public static function unregister($eventId, $hard = false)
{
if (false !== $hard) {
unset(self::$_register[$eventId]);
} else {
self::$_register[$eventId][self::KEY_SOURCE] = null;
}
return;
}
/**
* Attach an object to an event.
* It can be a callable or an accepted callable form (please, see the
* \Hoa\Consistency\Xcallable class).
*
* @param mixed $callable Callable.
* @return \Hoa\Event\Event
*/
public function attach($callable)
{
$callable = xcallable($callable);
$this->_callable[$callable->getHash()] = $callable;
return $this;
}
/**
* Detach an object to an event.
* Please see $this->attach() method.
*
* @param mixed $callable Callable.
* @return \Hoa\Event\Event
*/
public function detach($callable)
{
unset($this->_callable[xcallable($callable)->getHash()]);
return $this;
}
/**
* Check if at least one callable is attached to an event.
*
* @return bool
*/
public function isListened()
{
return !empty($this->_callable);
}
/**
* Notify, i.e. send data to observers.
*
* @param string $eventId Event ID.
* @param \Hoa\Event\Source $source Source.
* @param \Hoa\Event\Bucket $data Data.
* @return void
* @throws \Hoa\Event\Exception
*/
public static function notify($eventId, Source $source, Bucket $data)
{
if (false === self::eventExists($eventId)) {
throw new Exception(
'Event ID %s does not exist, cannot send notification.',
3,
$eventId
);
}
$data->setSource($source);
$event = self::getEvent($eventId);
foreach ($event->_callable as $callable) {
$callable($data);
}
return;
}
/**
* Check whether an event exists.
*
* @param string $eventId Event ID.
* @return bool
*/
public static function eventExists($eventId)
{
return
array_key_exists($eventId, self::$_register) &&
self::$_register[$eventId][self::KEY_SOURCE] !== null;
}
}
/**
* Flex entity.
*/
Consistency::flexEntity('Hoa\Event\Event');

51
vendor/hoa/event/Exception.php vendored Normal file
View File

@ -0,0 +1,51 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Event;
use Hoa\Exception as HoaException;
/**
* Class \Hoa\Event\Exception.
*
* Extending the \Hoa\Exception\Exception class.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Exception extends HoaException
{
}

57
vendor/hoa/event/Listenable.php vendored Normal file
View File

@ -0,0 +1,57 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Event;
/**
* Interface \Hoa\Event\Listenable.
*
* Each object which is listenable must implement this interface.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
interface Listenable extends Source
{
/**
* Attach a callable to a listenable component.
*
* @param string $listenerId Listener ID.
* @param mixed $callable Callable.
* @return \Hoa\Event\Listenable
*/
public function on($listenerId, $callable);
}

184
vendor/hoa/event/Listener.php vendored Normal file
View File

@ -0,0 +1,184 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Event;
/**
* Class \Hoa\Event\Listener.
*
* A contrario of events, listeners are synchronous, identified at use and
* useful for close interactions between one or some components.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Listener
{
/**
* Source of listener (for Bucket).
*
* @var \Hoa\Event\Listenable
*/
protected $_source = null;
/**
* All listener IDs and associated listeners.
*
* @var array
*/
protected $_callables = [];
/**
* Build a listener.
*
* @param \Hoa\Event\Listenable $source Source (for Bucket).
* @param array $ids Accepted ID.
*/
public function __construct(Listenable $source, array $ids)
{
$this->_source = $source;
$this->addIds($ids);
return;
}
/**
* Add acceptable ID (or reset).
*
* @param array $ids Accepted ID.
* @return void
*/
public function addIds(array $ids)
{
foreach ($ids as $id) {
$this->_callables[$id] = [];
}
return;
}
/**
* Attach a callable to a listenable component.
*
* @param string $listenerId Listener ID.
* @param mixed $callable Callable.
* @return \Hoa\Event\Listener
* @throws \Hoa\Event\Exception
*/
public function attach($listenerId, $callable)
{
if (false === $this->listenerExists($listenerId)) {
throw new Exception(
'Cannot listen %s because it is not defined.',
0,
$listenerId
);
}
$callable = xcallable($callable);
$this->_callables[$listenerId][$callable->getHash()] = $callable;
return $this;
}
/**
* Detach a callable from a listenable component.
*
* @param string $listenerId Listener ID.
* @param mixed $callable Callable.
* @return \Hoa\Event\Listener
*/
public function detach($listenerId, $callable)
{
unset($this->_callables[$listenerId][xcallable($callable)->getHash()]);
return $this;
}
/**
* Detach all callables from a listenable component.
*
* @param string $listenerId Listener ID.
* @return \Hoa\Event\Listener
*/
public function detachAll($listenerId)
{
unset($this->_callables[$listenerId]);
return $this;
}
/**
* Check if a listener exists.
*
* @param string $listenerId Listener ID.
* @return bool
*/
public function listenerExists($listenerId)
{
return array_key_exists($listenerId, $this->_callables);
}
/**
* Send/fire a bucket to a listener.
*
* @param string $listenerId Listener ID.
* @param \Hoa\Event\Bucket $data Data.
* @return array
* @throws \Hoa\Event\Exception
*/
public function fire($listenerId, Bucket $data)
{
if (false === $this->listenerExists($listenerId)) {
throw new Exception(
'Cannot fire on %s because it is not defined.',
1,
$listenerId
);
}
$data->setSource($this->_source);
$out = [];
foreach ($this->_callables[$listenerId] as $callable) {
$out[] = $callable($data);
}
return $out;
}
}

106
vendor/hoa/event/Listens.php vendored Normal file
View File

@ -0,0 +1,106 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Event;
/**
* Trait \Hoa\Event\Listens.
*
* Implementation of a listener.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
trait Listens
{
/**
* Listener instance.
*
* @var \Hoa\Event\Listener
*/
protected $_listener = null;
/**
* Attach a callable to a listenable component.
*
* @param string $listenerId Listener ID.
* @param mixed $callable Callable.
* @return \Hoa\Event\Listenable
*/
public function on($listenerId, $callable)
{
$listener = $this->getListener();
if (null === $listener) {
throw new Exception(
'Cannot attach a callable to the listener %s because ' .
'it has not been initialized yet.',
0,
get_class($this)
);
}
$listener->attach($listenerId, $callable);
return $this;
}
/**
* Set listener.
*
* @param \Hoa\Event\Listener $listener Listener.
* @return \Hoa\Event\Listener
*/
protected function setListener(Listener $listener)
{
$old = $this->_listener;
$this->_listener = $listener;
return $old;
}
/**
* Get listener.
*
* @return \Hoa\Event\Listener
*/
protected function getListener()
{
return $this->_listener;
}
}

161
vendor/hoa/event/README.md vendored Normal file
View File

@ -0,0 +1,161 @@
<p align="center">
<img src="https://static.hoa-project.net/Image/Hoa.svg" alt="Hoa" width="250px" />
</p>
---
<p align="center">
<a href="https://travis-ci.org/hoaproject/event"><img src="https://img.shields.io/travis/hoaproject/event/master.svg" alt="Build status" /></a>
<a href="https://coveralls.io/github/hoaproject/event?branch=master"><img src="https://img.shields.io/coveralls/hoaproject/event/master.svg" alt="Code coverage" /></a>
<a href="https://packagist.org/packages/hoa/event"><img src="https://img.shields.io/packagist/dt/hoa/event.svg" alt="Packagist" /></a>
<a href="https://hoa-project.net/LICENSE"><img src="https://img.shields.io/packagist/l/hoa/event.svg" alt="License" /></a>
</p>
<p align="center">
Hoa is a <strong>modular</strong>, <strong>extensible</strong> and
<strong>structured</strong> set of PHP libraries.<br />
Moreover, Hoa aims at being a bridge between industrial and research worlds.
</p>
# Hoa\Event
[![Help on IRC](https://img.shields.io/badge/help-%23hoaproject-ff0066.svg)](https://webchat.freenode.net/?channels=#hoaproject)
[![Help on Gitter](https://img.shields.io/badge/help-gitter-ff0066.svg)](https://gitter.im/hoaproject/central)
[![Documentation](https://img.shields.io/badge/documentation-hack_book-ff0066.svg)](https://central.hoa-project.net/Documentation/Library/Event)
[![Board](https://img.shields.io/badge/organisation-board-ff0066.svg)](https://waffle.io/hoaproject/event)
This library allows to use events and listeners in PHP. This is an observer
design-pattern implementation.
[Learn more](https://central.hoa-project.net/Documentation/Library/Event).
## Installation
With [Composer](https://getcomposer.org/), to include this library into
your dependencies, you need to
require [`hoa/event`](https://packagist.org/packages/hoa/event):
```sh
$ composer require hoa/event '~1.0'
```
For more installation procedures, please read [the Source
page](https://hoa-project.net/Source.html).
## Testing
Before running the test suites, the development dependencies must be installed:
```sh
$ composer install
```
Then, to run all the test suites:
```sh
$ vendor/bin/hoa test:run
```
For more information, please read the [contributor
guide](https://hoa-project.net/Literature/Contributor/Guide.html).
## Quick usage
We propose a quick overview of how to use events and listeners.
### Events
An event is:
* **Asynchronous** when registering, because the observable may not exist yet
while observers start to observe,
* **Anonymous** when using, because the observable has no idea how many and
what observers are observing,
* It aims at a **large** diffusion of data through isolated components.
Wherever is the observable, we can observe its data.
In Hoa, an event channel has the following form:
`hoa://Event/LibraryName/AnId:pseudo-class#anAnchor`. For instance, the
`hoa://Event/Exception` channel contains all exceptions that have been thrown.
The `hoa://Event/Stream/StreamName:close-before` contains all streams that are
about to close. Thus, the following example will observe all thrown exceptions:
```php
Hoa\Event\Event::getEvent('hoa://Event/Exception')->attach(
function (Hoa\Event\Bucket $bucket) {
var_dump(
$bucket->getSource(),
$bucket->getData()
);
}
);
```
Because `attach` expects a callable and because Hoa's callable implementation is
smart, we can directly attach a stream to an event, like:
```php
Hoa\Event\Event::getEvent('hoa://Event/Exception')->attach(
new Hoa\File\Write('Foo.log')
);
```
This way, all exceptions will be printed on the `Foo.log` file.
### Listeners
Contrary to an event, a listener is:
* **Synchronous** when registering, because the observable must exist before
observers can observe,
* **Identified** when using, because the observable knows how many observers
are observing,
* It aims at a **close** diffusion of data. The observers must have an access
to the observable to observe.
The `Hoa\Event\Listenable` interface requires the `on` method to be present to
register a listener to a listener ID. For instance, the following example
listens the `message` listener ID, i.e. when a message is received by the
WebSocket server, the closure is executed:
```php
$server = new Hoa\Websocket\Server(…);
$server->on('message', function (Hoa\Event\Bucket $bucket) {
var_dump(
$bucket->getSource(),
$bucket->getData()
);
});
```
## Documentation
The
[hack book of `Hoa\Event`](https://central.hoa-project.net/Documentation/Library/Event) contains
detailed information about how to use this library and how it works.
To generate the documentation locally, execute the following commands:
```sh
$ composer require --dev hoa/devtools
$ vendor/bin/hoa devtools:documentation --open
```
More documentation can be found on the project's website:
[hoa-project.net](https://hoa-project.net/).
## Getting help
There are mainly two ways to get help:
* On the [`#hoaproject`](https://webchat.freenode.net/?channels=#hoaproject)
IRC channel,
* On the forum at [users.hoa-project.net](https://users.hoa-project.net).
## Contribution
Do you want to contribute? Thanks! A detailed [contributor
guide](https://hoa-project.net/Literature/Contributor/Guide.html) explains
everything you need to know.
## License
Hoa is under the New BSD License (BSD-3-Clause). Please, see
[`LICENSE`](https://hoa-project.net/LICENSE) for details.

49
vendor/hoa/event/Source.php vendored Normal file
View File

@ -0,0 +1,49 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Event;
/**
* Interface \Hoa\Event\Source.
*
* Each object which is listenable must implement this interface.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
interface Source
{
}

139
vendor/hoa/event/Test/Unit/Bucket.php vendored Normal file
View File

@ -0,0 +1,139 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Event\Test\Unit;
use Hoa\Event as LUT;
use Hoa\Event\Bucket as SUT;
use Hoa\Test;
/**
* Class \Hoa\Event\Test\Unit\Bucket.
*
* Test suite of the bucket.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Bucket extends Test\Unit\Suite
{
public function case_constructor()
{
$this
->when($result = new SUT('foo'))
->then
->object($result)
->isInstanceOf('Hoa\Event\Bucket')
->string($result->getData())
->isEqualTo('foo');
}
public function case_send()
{
$self = $this;
$this
->given(
$eventId = 'hoa://Event/Test',
$source = new \Mock\Hoa\Event\Source(),
LUT::register($eventId, $source),
$bucket = new SUT('foo'),
LUT::getEvent($eventId)->attach(
function (SUT $receivedBucket) use ($self, $bucket, &$called) {
$called = true;
$self
->object($receivedBucket)
->isIdenticalTo($bucket);
}
)
)
->when($result = $bucket->send($eventId, $source))
->then
->variable($result)
->isNull()
->boolean($called)
->isTrue();
}
public function case_set_source()
{
$this
->given(
$bucket = new SUT(),
$sourceA = new \Mock\Hoa\Event\Source()
)
->when($result = $bucket->setSource($sourceA))
->then
->variable($result)
->isNull()
->object($bucket->getSource())
->isIdenticalTo($sourceA)
->given($sourceB = new \Mock\Hoa\Event\Source())
->when($result = $bucket->setSource($sourceB))
->then
->object($result)
->isIdenticalTo($sourceA)
->object($bucket->getSource())
->isIdenticalTo($sourceB);
}
public function case_set_data()
{
$this
->given(
$bucket = new SUT(),
$datumA = 'foo'
)
->when($result = $bucket->setData($datumA))
->then
->variable($result)
->isNull()
->string($bucket->getData())
->isEqualTo($datumA)
->given($datumB = 'bar')
->when($result = $bucket->setData($datumB))
->then
->string($result)
->isEqualTo($datumA)
->string($bucket->getData())
->isEqualTo($datumB);
}
}

300
vendor/hoa/event/Test/Unit/Event.php vendored Normal file
View File

@ -0,0 +1,300 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Event\Test\Unit;
use Hoa\Event as LUT;
use Hoa\Event\Event as SUT;
use Hoa\Test;
/**
* Class \Hoa\Event\Test\Unit\Event.
*
* Test suite of the event class.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Event extends Test\Unit\Suite
{
public function case_multiton()
{
$this
->given($eventId = 'hoa://Event/Test')
->when($result = SUT::getEvent($eventId))
->then
->object($result)
->isInstanceOf('Hoa\Event\Event')
->object(SUT::getEvent($eventId))
->isIdenticalTo($result);
}
public function case_register_source_instance()
{
$this
->given(
$eventId = 'hoa://Event/Test',
$source = new \Mock\Hoa\Event\Source()
)
->when($result = SUT::register($eventId, $source))
->then
->variable($result)
->isNull()
->boolean(SUT::eventExists($eventId))
->isTrue();
}
public function case_register_source_name()
{
$this
->given(
$eventId = 'hoa://Event/Test',
$source = 'Mock\Hoa\Event\Source'
)
->when($result = SUT::register($eventId, $source))
->then
->variable($result)
->isNull()
->boolean(SUT::eventExists($eventId))
->isTrue();
}
public function case_register_redeclare()
{
$this
->given(
$eventId = 'hoa://Event/Test',
$source = new \Mock\Hoa\Event\Source(),
SUT::register($eventId, $source)
)
->exception(function () use ($eventId, $source) {
SUT::register($eventId, $source);
})
->isInstanceOf('Hoa\Event\Exception');
}
public function case_register_not_a_source_instance()
{
$this
->given(
$eventId = 'hoa://Event/Test',
$source = new \StdClass()
)
->exception(function () use ($eventId, $source) {
$result = SUT::register($eventId, $source);
})
->isInstanceOf('Hoa\Event\Exception');
}
public function case_register_not_a_source_name()
{
$this
->given(
$eventId = 'hoa://Event/Test',
$source = 'StdClass'
)
->exception(function () use ($eventId, $source) {
$result = SUT::register($eventId, $source);
})
->isInstanceOf('Hoa\Event\Exception');
}
public function case_unregister()
{
$this
->given(
$eventId = 'hoa://Event/Test',
$source = new \Mock\Hoa\Event\Source(),
SUT::register($eventId, $source)
)
->when($result = SUT::unregister($eventId))
->then
->boolean(SUT::eventExists($eventId))
->isFalse();
}
public function case_unregister_hard()
{
$this
->given(
$eventId = 'hoa://Event/Test',
$source = new \Mock\Hoa\Event\Source(),
SUT::register($eventId, $source),
$event = SUT::getEvent($eventId)
)
->when($result = SUT::unregister($eventId, true))
->then
->boolean(SUT::eventExists($eventId))
->isFalse()
->object(SUT::getEvent($eventId))
->isNotIdenticalTo($event);
}
public function case_unregister_not_registered()
{
$this
->given($eventId = 'hoa://Event/Test')
->when($result = SUT::unregister($eventId))
->then
->variable($result)
->isNull();
}
public function case_attach()
{
$this
->given(
$event = SUT::getEvent('hoa://Event/Test'),
$callable = function () { }
)
->when($result = $event->attach($callable))
->then
->object($result)
->isIdenticalTo($event)
->boolean($event->isListened())
->isTrue();
}
public function case_detach()
{
$this
->given(
$event = SUT::getEvent('hoa://Event/Test'),
$callable = function () { },
$event->attach($callable)
)
->when($result = $event->detach($callable))
->then
->object($result)
->isIdenticalTo($event)
->boolean($event->isListened())
->isFalse();
}
public function case_detach_unattached()
{
$this
->given(
$event = SUT::getEvent('hoa://Event/Test'),
$callable = function () { }
)
->when($result = $event->detach($callable))
->then
->object($result)
->isIdenticalTo($event)
->boolean($event->isListened())
->isFalse();
}
public function case_is_listened()
{
$this
->given($event = SUT::getEvent('hoa://Event/Test'))
->when($result = $event->isListened())
->then
->boolean($event->isListened())
->isFalse();
}
public function case_notify()
{
$self = $this;
$this
->given(
$eventId = 'hoa://Event/Test',
$source = new \Mock\Hoa\Event\Source(),
$bucket = new LUT\Bucket(),
SUT::register($eventId, $source),
SUT::getEvent($eventId)->attach(
function (LUT\Bucket $receivedBucket) use ($self, $source, $bucket, &$called) {
$called = true;
$this
->object($receivedBucket)
->isIdenticalTo($bucket)
->object($receivedBucket->getSource())
->isIdenticalTo($source);
}
)
)
->when($result = SUT::notify($eventId, $source, $bucket))
->then
->variable($result)
->isNull()
->boolean($called)
->isTrue();
}
public function case_notify_unregistered_event_id()
{
$this
->given(
$eventId = 'hoa://Event/Test',
$source = new \Mock\Hoa\Event\Source(),
$data = new LUT\Bucket()
)
->exception(function () use ($eventId, $source, $data) {
SUT::notify($eventId, $source, $data);
})
->isInstanceOf('Hoa\Event\Exception');
}
public function case_event_exists()
{
$this
->given(
$eventId = 'hoa://Event/Test',
$source = new \Mock\Hoa\Event\Source(),
SUT::register($eventId, $source)
)
->when($result = SUT::eventExists($eventId))
->then
->boolean($result)
->isTrue();
}
public function case_event_not_exists()
{
$this
->given($eventId = 'hoa://Event/Test')
->when($result = SUT::eventExists($eventId))
->then
->boolean($result)
->isFalse();
}
}

View File

@ -0,0 +1,60 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Event\Test\Unit;
use Hoa\Event\Exception as SUT;
use Hoa\Test;
/**
* Class \Hoa\Event\Test\Unit\Exception.
*
* Test suite of the exception.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Exception extends Test\Unit\Suite
{
public function case_hoa_exception()
{
$this
->when($result = new SUT('foo', 0))
->then
->object($result)
->isInstanceOf('Hoa\Exception\Exception');
}
}

View File

@ -0,0 +1,59 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Event\Test\Unit;
use Hoa\Test;
/**
* Class \Hoa\Event\Test\Unit\Listenable.
*
* Test suite of the listenable interface.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Listenable extends Test\Unit\Suite
{
public function case_interface()
{
$this
->when($result = new \Mock\Hoa\Event\Listenable())
->then
->object($result)
->isInstanceOf('Hoa\Event\Listenable');
}
}

240
vendor/hoa/event/Test/Unit/Listener.php vendored Normal file
View File

@ -0,0 +1,240 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Event\Test\Unit;
use Hoa\Event as LUT;
use Hoa\Event\Listener as SUT;
use Hoa\Test;
/**
* Class \Hoa\Event\Test\Unit\Listener.
*
* Test suite of the listener.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Listener extends Test\Unit\Suite
{
public function case_constructor()
{
$this
->given(
$source = new \Mock\Hoa\Event\Listenable(),
$ids = ['foo', 'bar', 'baz']
)
->when($result = new SUT($source, $ids))
->then
->object($result)
->isInstanceOf('Hoa\Event\Listener')
->boolean($result->listenerExists('foo'))
->isTrue()
->boolean($result->listenerExists('bar'))
->isTrue()
->boolean($result->listenerExists('baz'))
->isTrue();
}
public function case_attach()
{
$this
->given(
$source = new \Mock\Hoa\Event\Listenable(),
$listenerId = 'foo',
$listener = new SUT($source, ['foo', 'bar']),
$callable = function () {
return 42;
}
)
->when($result = $listener->attach($listenerId, $callable))
->then
->object($result)
->isIdenticalTo($listener)
->array($listener->fire($listenerId, new LUT\Bucket()))
->isEqualTo([42]);
}
public function case_attach_to_an_undefined_listener()
{
$this
->given(
$source = new \Mock\Hoa\Event\Listenable(),
$listenerId = 'bar',
$listener = new SUT($source, ['foo', 'baz']),
$callable = function () { }
)
->exception(function () use ($listener, $listenerId, $callable) {
$listener->attach($listenerId, $callable);
})
->isInstanceOf('Hoa\Event\Exception');
}
public function case_detach()
{
$this
->given(
$source = new \Mock\Hoa\Event\Listenable(),
$listenerId = 'foo',
$listener = new SUT($source, ['foo', 'bar']),
$callable = function () {
return 42;
},
$listener->attach($listenerId, $callable)
)
->when($result = $listener->detach($listenerId, $callable))
->then
->object($result)
->isIdenticalTo($listener)
->array($listener->fire($listenerId, new LUT\Bucket()))
->isEmpty();
}
public function case_detach_an_undefined_listener()
{
$this
->given(
$source = new \Mock\Hoa\Event\Listenable(),
$listenerId = 'bar',
$listener = new SUT($source, ['foo', 'baz']),
$callable = function () { }
)
->when($result = $listener->detach($listenerId, $callable))
->then
->object($result)
->isIdenticalTo($listener);
}
public function case_detach_all()
{
$this
->given(
$source = new \Mock\Hoa\Event\Listenable(),
$listenerId = 'foo',
$listener = new SUT($source, ['foo', 'bar'])
)
->when($result = $listener->detachAll($listenerId))
->then
->object($result)
->isIdenticalTo($listener)
->boolean($listener->listenerExists($listenerId))
->isFalse();
}
public function case_detach_all_with_an_undefined_listener()
{
$this
->given(
$source = new \Mock\Hoa\Event\Listenable(),
$listenerId = 'bar',
$listener = new SUT($source, ['foo', 'baz'])
)
->when($result = $listener->detachAll($listenerId))
->then
->object($result)
->isIdenticalTo($listener);
}
public function case_listener_exists()
{
$this
->given(
$source = new \Mock\Hoa\Event\Listenable(),
$ids = [],
$listener = new SUT($source, $ids)
)
->when($listener->addIds(['foo']))
->then
->boolean($listener->listenerExists('foo'))
->isTrue()
->boolean($listener->listenerExists('bar'))
->isFalse()
->when($listener->addIds(['bar']))
->then
->boolean($listener->listenerExists('bar'))
->isTrue();
}
public function case_fire()
{
$self = $this;
$this
->given(
$source = new \Mock\Hoa\Event\Listenable(),
$ids = ['foo', 'bar'],
$listener = new SUT($source, $ids),
$listenerId = 'foo',
$bucket = new LUT\Bucket(),
$listener->attach(
$listenerId,
function (LUT\Bucket $receivedBucket) use ($self, $bucket, $source, &$called) {
$called = true;
$self
->object($receivedBucket)
->isIdenticalTo($bucket)
->object($receivedBucket->getSource())
->isIdenticalTo($source);
return 42;
}
)
)
->when($result = $listener->fire($listenerId, $bucket))
->then
->array($result)
->isEqualTo([42])
->boolean($called)
->isTrue();
}
public function case_fire_an_undefined_listenerId()
{
$this
->given(
$source = new \Mock\Hoa\Event\Listenable(),
$ids = [],
$listener = new SUT($source, $ids)
)
->exception(function () use ($listener) {
$listener->fire('foo', new LUT\Bucket());
})
->isInstanceOf('Hoa\Event\Exception');
}
}

139
vendor/hoa/event/Test/Unit/Listens.php vendored Normal file
View File

@ -0,0 +1,139 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Event\Test\Unit;
use Hoa\Event as LUT;
use Hoa\Event\Listens as SUT;
use Hoa\Test;
/**
* Class \Hoa\Event\Test\Unit\Listens.
*
* Test suite of the listens trait.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Listens extends Test\Unit\Suite
{
public function case_set_listener()
{
$this
->given(
$listenable = new _Listenable(),
$listener = new LUT\Listener($listenable, ['foo'])
)
->when($result = $listenable->_setListener($listener))
->then
->variable($result)
->isNull();
}
public function case_get_listener()
{
$this
->given(
$listenable = new _Listenable(),
$listener = new LUT\Listener($listenable, ['foo']),
$listenable->_setListener($listener)
)
->when($result = $listenable->_getListener())
->then
->object($result)
->isIdenticalTo($listener);
}
public function case_on()
{
$this
->given(
$listenable = new _Listenable(),
$listener = new LUT\Listener($listenable, ['foo']),
$listenable->_setListener($listener),
$callable = function () use (&$called) {
$called = true;
return 42;
}
)
->when($result = $listenable->on('foo', $callable))
->then
->object($result)
->isIdenticalTo($listenable)
->when($listenable->doSomethingThatFires())
->then
->boolean($called)
->isTrue();
}
public function case_on_unregistered_listener()
{
$this
->given(
$listenable = new _Listenable(),
$listener = new LUT\Listener($listenable, ['foo']),
$listenable->_setListener($listener)
)
->exception(function () use ($listenable) {
$listenable->on('bar', null);
})
->isInstanceOf('Hoa\Event\Exception');
}
}
class _Listenable implements LUT\Listenable
{
use SUT;
public function _setListener(LUT\Listener $listener)
{
return $this->setListener($listener);
}
public function _getListener()
{
return $this->getListener();
}
public function doSomethingThatFires()
{
$this->getListener()->fire('foo', new LUT\Bucket('bar'));
return;
}
}

59
vendor/hoa/event/Test/Unit/Source.php vendored Normal file
View File

@ -0,0 +1,59 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Event\Test\Unit;
use Hoa\Test;
/**
* Class \Hoa\Event\Test\Unit\Source.
*
* Test suite of the source interface.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Source extends Test\Unit\Suite
{
public function case_interface()
{
$this
->when($result = new \Mock\Hoa\Event\Source())
->then
->object($result)
->isInstanceOf('Hoa\Event\Source');
}
}

42
vendor/hoa/event/composer.json vendored Normal file
View File

@ -0,0 +1,42 @@
{
"name" : "hoa/event",
"description": "The Hoa\\Event library.",
"type" : "library",
"keywords" : ["library", "event", "listener", "observer"],
"homepage" : "https://hoa-project.net/",
"license" : "BSD-3-Clause",
"authors" : [
{
"name" : "Ivan Enderlin",
"email": "ivan.enderlin@hoa-project.net"
},
{
"name" : "Hoa community",
"homepage": "https://hoa-project.net/"
}
],
"support": {
"email" : "support@hoa-project.net",
"irc" : "irc://chat.freenode.net/hoaproject",
"forum" : "https://users.hoa-project.net/",
"docs" : "https://central.hoa-project.net/Documentation/Library/Event",
"source": "https://central.hoa-project.net/Resource/Library/Event"
},
"require": {
"hoa/consistency": "~1.0",
"hoa/exception" : "~1.0"
},
"require-dev": {
"hoa/test": "~2.0"
},
"autoload": {
"psr-4": {
"Hoa\\Event\\": "."
}
},
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
}
}

1
vendor/hoa/exception/.State vendored Normal file
View File

@ -0,0 +1 @@
finalized

2
vendor/hoa/exception/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/vendor/
/composer.lock

30
vendor/hoa/exception/CHANGELOG.md vendored Normal file
View File

@ -0,0 +1,30 @@
# 1.17.01.16
* Quality: Happy new year! (Ivan Enderlin, 2017-01-16T08:52:04+01:00)
# 1.16.11.08
* Documentation: New `README.md` file. (Ivan Enderlin, 2016-10-19T16:31:55+02:00)
* Documentation: Update `support` properties. (Ivan Enderlin, 2016-10-05T20:39:14+02:00)
# 1.16.01.11
* Quality: Drop PHP5.4. (Ivan Enderlin, 2016-01-11T09:15:26+01:00)
* Quality: Run devtools:cs. (Ivan Enderlin, 2016-01-09T09:01:35+01:00)
* Core: Remove `Hoa\Core`. (Ivan Enderlin, 2016-01-09T08:16:03+01:00)
* Consistency: Use `Hoa\Consistency`. (Ivan Enderlin, 2015-12-08T11:11:27+01:00)
# 0.15.11.23
* Fix phpDoc and a mistake on a static call. (Metalaka, 2015-11-21T17:44:35+01:00)
* Add a `.gitignore` file. (Metalaka, 2015-11-21T17:39:21+01:00)
* Test: Add test cases for the uncaught handler. (Ivan Enderlin, 2015-11-18T21:48:20+01:00)
* Idle: Add uncaught handler. (Ivan Enderlin, 2015-11-18T21:47:40+01:00)
* README: Add a better description and new usages. (Ivan Enderlin, 2015-11-18T21:36:03+01:00)
* Test: Write test suite of `Hoa\Exception\Group`. (Ivan Enderlin, 2015-11-18T08:28:04+01:00)
* Test: Write test suite of `Hoa\Exception\Error`. (Ivan Enderlin, 2015-11-17T22:30:14+01:00)
* Test: Write test suite of `…\Exception\Exception`. (Ivan Enderlin, 2015-11-17T22:03:31+01:00)
* Test: Write test suite of `Hoa\Exception\Idle`. (Ivan Enderlin, 2015-11-17T21:41:07+01:00)
* Split from `Hoa\Core`. (Ivan Enderlin, 2015-11-13T08:58:45+01:00)
(first snapshot)

100
vendor/hoa/exception/Error.php vendored Normal file
View File

@ -0,0 +1,100 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Exception;
/**
* Class \Hoa\Exception\Error.
*
* This exception is the equivalent representation of PHP errors.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Error extends Exception
{
/**
* Constructor.
*
* @param string $message Message.
* @param int $code Code (the ID).
* @param string $file File.
* @param int $line Line.
* @param array $trace Trace.
*/
public function __construct(
$message,
$code,
$file,
$line,
array $trace = []
) {
$this->file = $file;
$this->line = $line;
$this->_trace = $trace;
parent::__construct($message, $code);
return;
}
/**
* Enable error handler: Transform PHP error into `\Hoa\Exception\Error`.
*
* @param bool $enable Enable.
* @return mixed
*/
public static function enableErrorHandler($enable = true)
{
if (false === $enable) {
return restore_error_handler();
}
return set_error_handler(
function ($no, $str, $file = null, $line = null, $ctx = null) {
if (0 === ($no & error_reporting())) {
return;
}
$trace = debug_backtrace();
array_shift($trace);
array_shift($trace);
throw new Error($str, $no, $file, $line, $trace);
}
);
}
}

100
vendor/hoa/exception/Exception.php vendored Normal file
View File

@ -0,0 +1,100 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Exception;
use Hoa\Consistency;
use Hoa\Event;
/**
* Class \Hoa\Exception\Exception.
*
* Each exception must extend \Hoa\Exception\Exception.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Exception extends Idle implements Event\Source
{
/**
* Create an exception.
* An exception is built with a formatted message, a code (an ID), and an
* array that contains the list of formatted string for the message. If
* chaining, we can add a previous exception.
*
* @param string $message Formatted message.
* @param int $code Code (the ID).
* @param array $arguments Arguments to format message.
* @param \Throwable $previous Previous exception in chaining.
*/
public function __construct(
$message,
$code = 0,
$arguments = [],
$previous = null
) {
parent::__construct($message, $code, $arguments, $previous);
if (false === Event::eventExists('hoa://Event/Exception')) {
Event::register('hoa://Event/Exception', __CLASS__);
}
$this->send();
return;
}
/**
* Send the exception on hoa://Event/Exception.
*
* @return void
*/
public function send()
{
Event::notify(
'hoa://Event/Exception',
$this,
new Event\Bucket($this)
);
return;
}
}
/**
* Flex entity.
*/
Consistency::flexEntity('Hoa\Exception\Exception');

283
vendor/hoa/exception/Group.php vendored Normal file
View File

@ -0,0 +1,283 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Exception;
/**
* Class \Hoa\Exception\Group.
*
* This is an exception that contains a group of exceptions.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Group extends Exception implements \ArrayAccess, \IteratorAggregate, \Countable
{
/**
* All exceptions (stored in a stack for transactions).
*
* @var \SplStack
*/
protected $_group = null;
/**
* Create an exception.
*
* @param string $message Formatted message.
* @param int $code Code (the ID).
* @param array $arguments Arguments to format message.
* @param \Exception $previous Previous exception in chaining.
*/
public function __construct(
$message,
$code = 0,
$arguments = [],
\Exception $previous = null
) {
parent::__construct($message, $code, $arguments, $previous);
$this->_group = new \SplStack();
$this->beginTransaction();
return;
}
/**
* Raise an exception as a string.
*
* @param bool $previous Whether raise previous exception if exists.
* @return string
*/
public function raise($previous = false)
{
$out = parent::raise($previous);
if (0 >= count($this)) {
return $out;
}
$out .= "\n\n" . 'Contains the following exceptions:';
foreach ($this as $exception) {
$out .=
"\n\n" . ' • ' .
str_replace(
"\n",
"\n" . ' ',
$exception->raise($previous)
);
}
return $out;
}
/**
* Begin a transaction.
*
* @return \Hoa\Exception\Group
*/
public function beginTransaction()
{
$this->_group->push(new \ArrayObject());
return $this;
}
/**
* Rollback a transaction.
*
* @return \Hoa\Exception\Group
*/
public function rollbackTransaction()
{
if (1 >= count($this->_group)) {
return $this;
}
$this->_group->pop();
return $this;
}
/**
* Commit a transaction.
*
* @return \Hoa\Exception\Group
*/
public function commitTransaction()
{
if (false === $this->hasUncommittedExceptions()) {
$this->_group->pop();
return $this;
}
foreach ($this->_group->pop() as $index => $exception) {
$this[$index] = $exception;
}
return $this;
}
/**
* Check if there is uncommitted exceptions.
*
* @return bool
*/
public function hasUncommittedExceptions()
{
return
1 < count($this->_group) &&
0 < count($this->_group->top());
}
/**
* Check if an index in the group exists.
*
* @param mixed $index Index.
* @return bool
*/
public function offsetExists($index)
{
foreach ($this->_group as $group) {
if (isset($group[$index])) {
return true;
}
}
return false;
}
/**
* Get an exception from the group.
*
* @param mixed $index Index.
* @return Exception
*/
public function offsetGet($index)
{
foreach ($this->_group as $group) {
if (isset($group[$index])) {
return $group[$index];
}
}
return null;
}
/**
* Set an exception in the group.
*
* @param mixed $index Index.
* @param Exception $exception Exception.
* @return void
*/
public function offsetSet($index, $exception)
{
if (!($exception instanceof \Exception)) {
return null;
}
$group = $this->_group->top();
if (null === $index ||
true === is_int($index)) {
$group[] = $exception;
} else {
$group[$index] = $exception;
}
return;
}
/**
* Remove an exception in the group.
*
* @param mixed $index Index.
* @return void
*/
public function offsetUnset($index)
{
foreach ($this->_group as $group) {
if (isset($group[$index])) {
unset($group[$index]);
}
}
return;
}
/**
* Get committed exceptions in the group.
*
* @return \ArrayObject
*/
public function getExceptions()
{
return $this->_group->bottom();
}
/**
* Get an iterator over all exceptions (committed or not).
*
* @return \ArrayIterator
*/
public function getIterator()
{
return $this->getExceptions()->getIterator();
}
/**
* Count the number of committed exceptions.
*
* @return int
*/
public function count()
{
return count($this->getExceptions());
}
/**
* Count the stack size, i.e. the number of opened transactions.
*
* @return int
*/
public function getStackSize()
{
return count($this->_group);
}
}

312
vendor/hoa/exception/Idle.php vendored Normal file
View File

@ -0,0 +1,312 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Exception;
/**
* Class \Hoa\Exception\Idle.
*
* `\Hoa\Exception\Idle` is the mother exception class of libraries. The only
* difference between `\Hoa\Exception\Idle` and its directly child
* `\Hoa\Exception` is that the latter fires events after beeing constructed.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Idle extends \Exception
{
/**
* Delay processing on arguments.
*
* @var array
*/
protected $_tmpArguments = null;
/**
* Arguments to format message.
*
* @var array
*/
protected $_arguments = null;
/**
* Backtrace.
*
* @var array
*/
protected $_trace = null;
/**
* Previous.
*
* @var \Exception
*/
protected $_previous = null;
/**
* Original message.
*
* @var string
*/
protected $_rawMessage = null;
/**
* Create an exception.
* An exception is built with a formatted message, a code (an ID) and an
* array that contains the list of formatted strings for the message. If
* chaining, we can add a previous exception.
*
* @param string $message Formatted message.
* @param int $code Code (the ID).
* @param array $arguments Arguments to format message.
* @param \Exception $previous Previous exception in chaining.
*/
public function __construct(
$message,
$code = 0,
$arguments = [],
\Exception $previous = null
) {
$this->_tmpArguments = $arguments;
parent::__construct($message, $code, $previous);
$this->_rawMessage = $message;
$this->message = @vsprintf($message, $this->getArguments());
return;
}
/**
* Get the backtrace.
* Do not use \Exception::getTrace() any more.
*
* @return array
*/
public function getBacktrace()
{
if (null === $this->_trace) {
$this->_trace = $this->getTrace();
}
return $this->_trace;
}
/**
* Get previous.
* Do not use \Exception::getPrevious() any more.
*
* @return \Exception
*/
public function getPreviousThrow()
{
if (null === $this->_previous) {
$this->_previous = $this->getPrevious();
}
return $this->_previous;
}
/**
* Get arguments for the message.
*
* @return array
*/
public function getArguments()
{
if (null === $this->_arguments) {
$arguments = $this->_tmpArguments;
if (!is_array($arguments)) {
$arguments = [$arguments];
}
foreach ($arguments as &$value) {
if (null === $value) {
$value = '(null)';
}
}
$this->_arguments = $arguments;
unset($this->_tmpArguments);
}
return $this->_arguments;
}
/**
* Get the raw message.
*
* @return string
*/
public function getRawMessage()
{
return $this->_rawMessage;
}
/**
* Get the message already formatted.
*
* @return string
*/
public function getFormattedMessage()
{
return $this->getMessage();
}
/**
* Get the source of the exception (class, method, function, main etc.).
*
* @return string
*/
public function getFrom()
{
$trace = $this->getBacktrace();
$from = '{main}';
if (!empty($trace)) {
$t = $trace[0];
$from = '';
if (isset($t['class'])) {
$from .= $t['class'] . '::';
}
if (isset($t['function'])) {
$from .= $t['function'] . '()';
}
}
return $from;
}
/**
* Raise an exception as a string.
*
* @param bool $previous Whether raise previous exception if exists.
* @return string
*/
public function raise($previous = false)
{
$message = $this->getFormattedMessage();
$trace = $this->getBacktrace();
$file = '/dev/null';
$line = -1;
$pre = $this->getFrom();
if (!empty($trace)) {
$file = isset($trace['file']) ? $trace['file'] : null;
$line = isset($trace['line']) ? $trace['line'] : null;
}
$pre .= ': ';
try {
$out =
$pre . '(' . $this->getCode() . ') ' . $message . "\n" .
'in ' . $this->getFile() . ' at line ' .
$this->getLine() . '.';
} catch (\Exception $e) {
$out =
$pre . '(' . $this->getCode() . ') ' . $message . "\n" .
'in ' . $file . ' around line ' . $line . '.';
}
if (true === $previous &&
null !== $previous = $this->getPreviousThrow()) {
$out .=
"\n\n" . ' ⬇' . "\n\n" .
'Nested exception (' . get_class($previous) . '):' . "\n" .
($previous instanceof self
? $previous->raise(true)
: $previous->getMessage());
}
return $out;
}
/**
* Catch uncaught exception (only \Hoa\Exception\Idle and children).
*
* @param \Throwable $exception The exception.
* @return void
* @throws \Throwable
*/
public static function uncaught($exception)
{
if (!($exception instanceof self)) {
throw $exception;
}
while (0 < ob_get_level()) {
ob_end_flush();
}
echo
'Uncaught exception (' . get_class($exception) . '):' . "\n" .
$exception->raise(true);
return;
}
/**
* String representation of object.
*
* @return string
*/
public function __toString()
{
return $this->raise();
}
/**
* Enable uncaught exception handler.
* This is restricted to Hoa's exceptions only.
*
* @param bool $enable Enable.
* @return mixed
*/
public static function enableUncaughtHandler($enable = true)
{
if (false === $enable) {
return restore_exception_handler();
}
return set_exception_handler(function ($exception) {
return self::uncaught($exception);
});
}
}

231
vendor/hoa/exception/README.md vendored Normal file
View File

@ -0,0 +1,231 @@
<p align="center">
<img src="https://static.hoa-project.net/Image/Hoa.svg" alt="Hoa" width="250px" />
</p>
---
<p align="center">
<a href="https://travis-ci.org/hoaproject/exception"><img src="https://img.shields.io/travis/hoaproject/exception/master.svg" alt="Build status" /></a>
<a href="https://coveralls.io/github/hoaproject/exception?branch=master"><img src="https://img.shields.io/coveralls/hoaproject/exception/master.svg" alt="Code coverage" /></a>
<a href="https://packagist.org/packages/hoa/exception"><img src="https://img.shields.io/packagist/dt/hoa/exception.svg" alt="Packagist" /></a>
<a href="https://hoa-project.net/LICENSE"><img src="https://img.shields.io/packagist/l/hoa/exception.svg" alt="License" /></a>
</p>
<p align="center">
Hoa is a <strong>modular</strong>, <strong>extensible</strong> and
<strong>structured</strong> set of PHP libraries.<br />
Moreover, Hoa aims at being a bridge between industrial and research worlds.
</p>
# Hoa\Exception
[![Help on IRC](https://img.shields.io/badge/help-%23hoaproject-ff0066.svg)](https://webchat.freenode.net/?channels=#hoaproject)
[![Help on Gitter](https://img.shields.io/badge/help-gitter-ff0066.svg)](https://gitter.im/hoaproject/central)
[![Documentation](https://img.shields.io/badge/documentation-hack_book-ff0066.svg)](https://central.hoa-project.net/Documentation/Library/Exception)
[![Board](https://img.shields.io/badge/organisation-board-ff0066.svg)](https://waffle.io/hoaproject/exception)
This library allows to use advanced exceptions. It provides generic exceptions
(that are sent over the `hoa://Event/Exception` event channel), idle exceptions
(that are not sent over an event channel), uncaught exception handlers, errors
to exceptions handler and group of exceptions (with transactions).
[Learn more](https://central.hoa-project.net/Documentation/Library/Exception).
## Installation
With [Composer](https://getcomposer.org/), to include this library into
your dependencies, you need to
require [`hoa/exception`](https://packagist.org/packages/hoa/exception):
```sh
$ composer require hoa/exception '~1.0'
```
For more installation procedures, please read [the Source
page](https://hoa-project.net/Source.html).
## Testing
Before running the test suites, the development dependencies must be installed:
```sh
$ composer install
```
Then, to run all the test suites:
```sh
$ vendor/bin/hoa test:run
```
For more information, please read the [contributor
guide](https://hoa-project.net/Literature/Contributor/Guide.html).
## Quick usage
We propose a quick overview of how to use generic exceptions, how to listen all
thrown exceptions through events and how to use group of exceptions.
### Generic exceptions
An exception is constitued of:
* A message,
* A code (optional),
* A list of arguments for the message (à la `printf`, optional),
* A previous exception (optional).
Thus, the following example builds an exception:
```php
$exception = new Hoa\Exception\Exception('Hello %s!', 0, 'world');
```
The exception message will be: `Hello world!`. The “raise” message (with all
information, not only the message) is:
```
{main}: (0) Hello world!
in … at line ….
```
Previous exceptions are shown too, for instance:
```php
$previous = new Hoa\Exception\Exception('Hello previous.');
$exception = new Hoa\Exception\Exception('Hello %s!', 0, 'world', $previous);
echo $exception->raise(true);
/**
* Will output:
* {main}: (0) Hello world!
* in … at line ….
*
* ⬇
*
* Nested exception (Hoa\Exception\Exception):
* {main}: (0) Hello previous.
* in … at line ….
*/
```
### Listen exceptions through events
Most exceptions in Hoa extend `Hoa\Exception\Exception`, which fire themselves
on the `hoa://Event/Exception` event channel (please, see [the `Hoa\Event`
library](http://central.hoa-project.net/Resource/Library/Event)). Consequently,
we can listen for all exceptions that are thrown in the application by writing:
```php
Hoa\Event\Event::getEvent('hoa://Event/Exception')->attach(
function (Hoa\Event\Bucket $bucket) {
$exception = $bucket->getData();
// …
}
);
```
Only the `Hoa\Exception\Idle` exceptions are not fired on the channel event.
### Group and transactions
Groups of exceptions are represented by the `Hoa\Exception\Group`. A group is an
exception that contains one or many exceptions. A transactional API is provided
to add more exceptions in the group with the following methods:
* `beginTransaction` to start a transaction,
* `rollbackTransaction` to remove all newly added exceptions since
`beginTransaction` call,
* `commitTransaction` to merge all newly added exceptions in the previous
transaction,
* `hasUncommittedExceptions` to check whether they are pending exceptions or
not.
For instance, if an exceptional behavior is due to several reasons, a group of
exceptions can be thrown instead of one exception. Group can be nested too,
which is useful to represent a tree of exceptions. Thus:
```php
// A group of exceptions.
$group = new Hoa\Exception\Group('Failed because of several reasons.');
$group['first'] = new Hoa\Exception\Exception('First reason');
$group['second'] = new Hoa\Exception\Exception('Second reason');
// Can nest another group.
$group['third'] = new Hoa\Exception\Group('Third reason');
$group['third']['fourth'] = new Hoa\Exception\Exception('Fourth reason');
echo $group->raise(true);
/**
* Will output:
* {main}: (0) Failed because of several reasons.
* in … at line ….
*
* Contains the following exceptions:
*
* • {main}: (0) First reason
* in … at line ….
*
* • {main}: (0) Second reason
* in … at line ….
*
* • {main}: (0) Third reason
* in … at line ….
*
* Contains the following exceptions:
*
* • {main}: (0) Fourth reason
* in … at line ….
*/
```
The following example uses a transaction to add new exceptions in the group:
```php
$group = new Hoa\Exception\Group('Failed because of several reasons.');
$group[] = new Hoa\Exception\Exception('Always present.');
$group->beginTransaction();
$group[] = new Hoa\Exception\Exception('Might be present.');
if (true === $condition) {
$group->commitTransaction();
} else {
$group->rollbackTransaction();
}
```
## Documentation
The
[hack book of `Hoa\Exception`](https://central.hoa-project.net/Documentation/Library/Exception)
contains detailed information about how to use this library and how it works.
To generate the documentation locally, execute the following commands:
```sh
$ composer require --dev hoa/devtools
$ vendor/bin/hoa devtools:documentation --open
```
More documentation can be found on the project's website:
[hoa-project.net](https://hoa-project.net/).
## Getting help
There are mainly two ways to get help:
* On the [`#hoaproject`](https://webchat.freenode.net/?channels=#hoaproject)
IRC channel,
* On the forum at [users.hoa-project.net](https://users.hoa-project.net).
## Contribution
Do you want to contribute? Thanks! A detailed [contributor
guide](https://hoa-project.net/Literature/Contributor/Guide.html) explains
everything you need to know.
## License
Hoa is under the New BSD License (BSD-3-Clause). Please, see
[`LICENSE`](https://hoa-project.net/LICENSE) for details.

145
vendor/hoa/exception/Test/Unit/Error.php vendored Normal file
View File

@ -0,0 +1,145 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Exception\Test\Unit;
use Hoa\Exception\Error as SUT;
use Hoa\Test;
/**
* Class \Hoa\Exception\Test\Unit\Error.
*
* Test suite of the error class.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Error extends Test\Unit\Suite
{
public function case_is_an_exception()
{
$this
->when($result = new SUT('foo', 42, '/hoa/flatland', 153))
->then
->object($result)
->isInstanceOf('Hoa\Exception\Exception');
}
public function case_get_message()
{
$this
->given($exception = new SUT('foo', 42, '/hoa/flatland', 153))
->when($result = $exception->raise())
->then
->string($result)
->isEqualTo(
'{main}: (42) foo' . "\n" .
'in /hoa/flatland at line 153.'
);
}
public function case_disable_error_handler()
{
$this
->given(
$this->function->restore_error_handler = function () use (&$called) {
$called = true;
return null;
}
)
->when($result = SUT::enableErrorHandler(false))
->then
->variable($result)
->isNull()
->boolean($called)
->isTrue();
}
public function case_enable_error_handler()
{
$self = $this;
$this
->given(
$this->function->set_error_handler = function ($handler) use ($self, &$called) {
$called = true;
$self
->object($handler)
->isInstanceOf('Closure')
->let($reflection = new \ReflectionObject($handler))
->array($invokeParameters = $reflection->getMethod('__invoke')->getParameters())
->hasSize(5)
->string($invokeParameters[0]->getName())
->isEqualTo('no')
->string($invokeParameters[1]->getName())
->isEqualTo('str')
->string($invokeParameters[2]->getName())
->isEqualTo('file')
->boolean($invokeParameters[2]->isOptional())
->isTrue()
->string($invokeParameters[3]->getName())
->isEqualTo('line')
->boolean($invokeParameters[3]->isOptional())
->isTrue()
->string($invokeParameters[4]->getName())
->isEqualTo('ctx')
->boolean($invokeParameters[4]->isOptional())
->isTrue();
return null;
}
)
->when($result = SUT::enableErrorHandler())
->then
->variable($result)
->isNull()
->boolean($called)
->isTrue();
}
public function case_error_handler()
{
$this
->given(SUT::enableErrorHandler())
->exception(function () {
++$i;
})
->isInstanceOf('Hoa\Exception\Error')
->hasMessage('Undefined variable: i');
}
}

View File

@ -0,0 +1,97 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Exception\Test\Unit;
use Hoa\Event;
use Hoa\Exception\Exception as SUT;
use Hoa\Test;
/**
* Class \Hoa\Exception\Test\Unit\Exception.
*
* Test suite of the exception class.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Exception extends Test\Unit\Suite
{
public function case_is_an_idle_exception()
{
$this
->when($result = new SUT('foo'))
->then
->object($result)
->isInstanceOf('Hoa\Exception\Idle');
}
public function case_event_is_registered()
{
$this
->given(new SUT('foo'))
->when($result = Event::eventExists('hoa://Event/Exception'))
->then
->boolean($result)
->isTrue();
}
public function case_event_is_sent()
{
$self = $this;
$this
->given(
Event::getEvent('hoa://Event/Exception')->attach(
function (Event\Bucket $bucket) use ($self, &$called) {
$called = true;
$self
->object($bucket->getSource())
->isInstanceOf('Hoa\Exception\Exception')
->string($bucket->getSource()->getMessage())
->isEqualTo('foo')
->object($bucket->getData())
->isIdenticalTo($bucket->getSource());
}
)
)
->when(new SUT('foo'))
->then
->boolean($called)
->isTrue();
}
}

610
vendor/hoa/exception/Test/Unit/Group.php vendored Normal file
View File

@ -0,0 +1,610 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Exception\Test\Unit;
use Hoa\Exception\Group as SUT;
use Hoa\Test;
/**
* Class \Hoa\Exception\Test\Unit\Group.
*
* Test suite of the group class.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Group extends Test\Unit\Suite
{
public function case_is_an_exception_arrayaccess_iteratoraggregate_countable()
{
$this
->when($result = new SUT('foo'))
->then
->object($result)
->isInstanceOf('Hoa\Exception\Exception')
->isInstanceOf('ArrayAccess')
->isInstanceOf('IteratorAggregate')
->isInstanceOf('Countable');
}
public function case_constructor()
{
$this
->given(
$message = 'foo %s %d %s',
$code = 7,
$arguments = ['arg', 42, null],
$previous = new SUT('previous')
)
->when($result = new SUT($message, $code, $arguments, $previous), $line = __LINE__)
->then
->string($result->getMessage())
->isEqualTo('foo arg 42 (null)')
->integer($result->getCode())
->isEqualTo(7)
->array($result->getArguments())
->isEqualTo(['arg', 42, '(null)'])
->object($result->getPreviousThrow())
->isIdenticalTo($previous)
->boolean($result->hasUncommittedExceptions())
->isFalse();
}
public function case_raise_zero_exception()
{
$this
->given($group = new SUT('foo'), $line = __LINE__)
->when($result = $group->raise())
->then
->string($result)
->isEqualTo(
__METHOD__ . '(): (0) foo' . "\n" .
'in ' . __FILE__ . ' at line ' . $line . '.'
);
}
public function case_raise_one_exception()
{
$this
->given(
$exception1 = new SUT('bar'), $barLine = __LINE__,
$group = new SUT('foo'), $fooLine = __LINE__,
$group[] = $exception1
)
->when($result = $group->raise())
->then
->string($result)
->isEqualTo(
__METHOD__ . '(): (0) foo' . "\n" .
'in ' . __FILE__ . ' at line ' . $fooLine . '.' . "\n\n" .
'Contains the following exceptions:' . "\n\n" .
' • ' . __METHOD__ . '(): (0) bar' . "\n" .
' in ' . __FILE__ . ' at line ' . $barLine . '.'
);
}
public function case_raise_more_exceptions()
{
$this
->given(
$exception1 = new SUT('bar'), $barLine = __LINE__,
$exception2 = new SUT('baz'), $bazLine = __LINE__,
$group = new SUT('foo'), $fooLine = __LINE__,
$group[] = $exception1,
$group[] = $exception2
)
->when($result = $group->raise())
->then
->string($result)
->isEqualTo(
__METHOD__ . '(): (0) foo' . "\n" .
'in ' . __FILE__ . ' at line ' . $fooLine . '.' . "\n\n" .
'Contains the following exceptions:' . "\n\n" .
' • ' . __METHOD__ . '(): (0) bar' . "\n" .
' in ' . __FILE__ . ' at line ' . $barLine . '.' . "\n\n" .
' • ' . __METHOD__ . '(): (0) baz' . "\n" .
' in ' . __FILE__ . ' at line ' . $bazLine . '.'
);
}
public function case_begin_transaction()
{
$this
->given(
$group = new SUT('foo'),
$oldStackSize = $group->getStackSize()
)
->when(
$result = $group->beginTransaction(),
$stackSize = $group->getStackSize()
)
->then
->integer($oldStackSize)
->isEqualTo(1)
->object($result)
->isIdenticalTo($group)
->integer($stackSize)
->isEqualTo($oldStackSize + 1);
}
public function case_rollback_transaction_with_an_empty_stack()
{
$this
->given(
$group = new SUT('foo'),
$oldStackSize = $group->getStackSize()
)
->when(
$result = $group->rollbackTransaction(),
$stackSize = $group->getStackSize()
)
->then
->integer($oldStackSize)
->isEqualTo(1)
->object($result)
->isIdenticalTo($group)
->integer($stackSize)
->isEqualTo($oldStackSize);
}
public function case_rollback_transaction()
{
$this
->given(
$group = new SUT('foo'),
$group->beginTransaction(),
$group->beginTransaction(),
$oldStackSize = $group->getStackSize(),
$group->rollbackTransaction()
)
->when(
$result = $group->rollbackTransaction(),
$stackSize = $group->getStackSize()
)
->then
->integer($oldStackSize)
->isEqualTo(3)
->object($result)
->isIdenticalTo($group)
->integer($stackSize)
->isEqualTo($oldStackSize - 2);
}
public function case_commit_transaction_with_an_empty_stack()
{
$this
->given(
$group = new SUT('foo'),
$group->beginTransaction(),
$oldCount = count($group),
$oldStackSize = $group->getStackSize()
)
->when(
$result = $group->commitTransaction(),
$count = count($group),
$stackSize = $group->getStackSize()
)
->then
->integer($oldCount)
->isEqualTo(0)
->integer($oldStackSize)
->isEqualTo(2)
->object($result)
->isIdenticalTo($group)
->integer($count)
->isEqualTo($oldCount)
->integer($stackSize)
->isEqualTo($oldStackSize - 1);
}
public function case_commit_transaction()
{
$this
->given(
$group = new SUT('foo'),
$group->beginTransaction(),
$exception1 = new SUT('bar'),
$exception2 = new SUT('baz'),
$group[] = $exception1,
$group[] = $exception2,
$oldCount = count($group),
$oldStackSize = $group->getStackSize()
)
->when(
$result = $group->commitTransaction(),
$count = count($group),
$stackSize = $group->getStackSize()
)
->then
->integer($oldCount)
->isEqualTo(0)
->integer($oldStackSize)
->isEqualTo(2)
->object($result)
->isIdenticalTo($group)
->integer($count)
->isEqualTo($oldCount + 2)
->integer($stackSize)
->isEqualTo($oldStackSize - 1)
->array(iterator_to_array($group->getIterator()))
->isEqualTo([
0 => $exception1,
1 => $exception2
]);
}
public function case_has_uncommitted_exceptions()
{
$this
->given(
$group = new SUT('foo'),
$group->beginTransaction(),
$group[] = new SUT('bar')
)
->when($result = $group->hasUncommittedExceptions())
->then
->boolean($result)
->isTrue();
}
public function case_has_no_uncommitted_exceptions()
{
$this
->given(
$group = new SUT('foo'),
$group->beginTransaction()
)
->when($result = $group->hasUncommittedExceptions())
->then
->boolean($result)
->isFalse();
}
public function case_has_no_uncommitted_exceptions_with_empty_stack()
{
$this
->given(
$group = new SUT('foo'),
$group[] = new SUT('bar')
)
->when($result = $group->hasUncommittedExceptions())
->then
->boolean($result)
->isFalse();
}
public function case_offset_exists_with_no_uncommited_exceptions()
{
$this
->given(
$group = new SUT('foo'),
$group['bar'] = new SUT('bar')
)
->when($result = $group->offsetExists('bar'))
->then
->boolean($result)
->isTrue();
}
public function case_offset_does_not_exist_with_no_uncommited_exceptions()
{
$this
->given(
$group = new SUT('foo'),
$group['bar'] = new SUT('bar')
)
->when($result = $group->offsetExists('baz'))
->then
->boolean($result)
->isFalse();
}
public function case_offset_exists()
{
$this
->given(
$group = new SUT('foo'),
$group->beginTransaction(),
$group->beginTransaction(),
$group['bar'] = new SUT('bar')
)
->when($result = $group->offsetExists('bar'))
->then
->boolean($result)
->isTrue();
}
public function case_offset_does_not_exist()
{
$this
->given(
$group = new SUT('foo'),
$group->beginTransaction(),
$group->beginTransaction(),
$group['bar'] = new SUT('bar')
)
->when($result = $group->offsetExists('baz'))
->then
->boolean($result)
->isFalse();
}
public function case_offset_get_with_no_uncommited_exceptions()
{
$this
->given(
$group = new SUT('foo'),
$exception1 = new SUT('bar'),
$group['bar'] = $exception1
)
->when($result = $group->offsetGet('bar'))
->then
->object($result)
->isIdenticalTo($exception1);
}
public function case_offset_get_does_not_exist_with_no_uncommited_exceptions()
{
$this
->given(
$group = new SUT('foo'),
$exception1 = new SUT('bar'),
$group['bar'] = $exception1
)
->when($result = $group->offsetGet('baz'))
->then
->variable($result)
->isNull();
}
public function case_offset_get()
{
$this
->given(
$group = new SUT('foo'),
$group->beginTransaction(),
$group->beginTransaction(),
$exception1 = new SUT('bar'),
$group['bar'] = $exception1
)
->when($result = $group->offsetGet('bar'))
->then
->object($result)
->isIdenticalTo($exception1);
}
public function case_offset_get_does_not_exist()
{
$this
->given(
$group = new SUT('foo'),
$group->beginTransaction(),
$group->beginTransaction(),
$exception1 = new SUT('bar'),
$group['bar'] = $exception1
)
->when($result = $group->offsetGet('baz'))
->then
->variable($result)
->isNull();
}
public function case_offset_set_not_an_exception()
{
$this
->given($group = new SUT('foo'))
->when($group->offsetSet('bar', new \StdClass()))
->then
->boolean($group->offsetExists('bar'))
->isFalse();
}
public function case_offset_set()
{
$this
->given(
$group = new SUT('foo'),
$exception1 = new SUT('bar')
)
->when($result = $group->offsetExists('bar'))
->then
->boolean($result)
->isFalse()
->when($group->offsetSet('bar', $exception1))
->then
->boolean($group->offsetExists('bar'))
->isTrue()
->object($group->offsetGet('bar'))
->isIdenticalTo($exception1);
}
public function case_offset_set_with_a_null_index()
{
$this
->given(
$group = new SUT('foo'),
$exception1 = new SUT('bar')
)
->when($group->offsetSet(null, $exception1))
->then
->boolean($group->offsetExists(0))
->isTrue()
->object($group->offsetGet(0))
->isIdenticalTo($exception1);
}
public function case_offset_set_with_an_integer_index()
{
$this
->given(
$group = new SUT('foo'),
$exception1 = new SUT('bar')
)
->when($group->offsetSet(42, $exception1))
->then
->boolean($group->offsetExists(42))
->isFalse()
->boolean($group->offsetExists(0))
->isTrue()
->object($group->offsetGet(0))
->isIdenticalTo($exception1);
}
public function case_offset_unset_with_no_uncommited_exceptions()
{
$this
->given(
$group = new SUT('foo'),
$group['bar'] = new SUT('bar')
)
->when($group->offsetUnset('bar'))
->then
->boolean($group->offsetExists('bar'))
->isFalse();
}
public function case_offset_unset_does_not_exist_with_no_uncommited_exceptions()
{
$this
->given($group = new SUT('foo'))
->when($group->offsetUnset('bar'))
->then
->boolean($group->offsetExists('bar'))
->isFalse();
}
public function case_offset_unset()
{
$this
->given(
$group = new SUT('foo'),
$group->beginTransaction(),
$group->beginTransaction(),
$group['bar'] = new SUT('bar')
)
->when($result = $group->offsetUnset('bar'))
->then
->boolean($group->offsetExists('bar'))
->isFalse();
}
public function case_offset_unset_does_not_exist()
{
$this
->given(
$group = new SUT('foo'),
$group->beginTransaction(),
$group->beginTransaction()
)
->when($result = $group->offsetUnset('bar'))
->then
->boolean($group->offsetExists('bar'))
->isFalse();
}
public function case_get_exceptions()
{
$this
->given(
$group = new SUT('foo'),
$exception1 = new SUT('bar'),
$exception2 = new SUT('baz'),
$group['bar'] = $exception1,
$group->beginTransaction(),
$group['baz'] = $exception2
)
->when($result = $group->getExceptions())
->then
->object($result)
->isInstanceOf('ArrayObject')
->object($result['bar'])
->isIdenticalTo($exception1);
}
public function case_get_iterator()
{
$this
->given(
$group = new SUT('foo'),
$exception1 = new SUT('bar'),
$group['bar'] = $exception1
)
->when($result = $group->getIterator())
->then
->object($result)
->isInstanceOf('ArrayIterator')
->array(iterator_to_array($result))
->isEqualTo([
'bar' => $exception1
]);
}
public function case_count()
{
$this
->given(
$group = new SUT('foo'),
$exception1 = new SUT('bar'),
$exception2 = new SUT('baz'),
$group['bar'] = $exception1,
$group->beginTransaction(),
$group['baz'] = $exception2
)
->when($result = count($group))
->then
->integer($result)
->isEqualTo(1);
}
public function get_get_stack_size()
{
$this
->given(
$group = new SUT('foo'),
$exception1 = new SUT('bar'),
$exception2 = new SUT('baz'),
$group['bar'] = $exception1,
$group->beginTransaction(),
$group['baz'] = $exception2
)
->when($result = $group->getStackSize())
->then
->integer($result)
->isEqualTo(2);
}
}

267
vendor/hoa/exception/Test/Unit/Idle.php vendored Normal file
View File

@ -0,0 +1,267 @@
<?php
/**
* Hoa
*
*
* @license
*
* New BSD License
*
* Copyright © 2007-2017, Hoa community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Hoa 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 HOLDERS AND 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.
*/
namespace Hoa\Exception\Test\Unit;
use Hoa\Exception\Idle as SUT;
use Hoa\Test;
/**
* Class \Hoa\Exception\Test\Unit\Idle.
*
* Test suite of the idle exception.
*
* @copyright Copyright © 2007-2017 Hoa community
* @license New BSD License
*/
class Idle extends Test\Unit\Suite
{
public function case_is_a_real_exception()
{
$this
->when($result = new SUT('foo'))
->then
->object($result)
->isInstanceOf('Exception');
}
public function case_get_backtrace()
{
$this
->given($exception = new SUT('foo'))
->when($result = $exception->getBacktrace())
->then
->array($result)
->hasKey(0)
->array($result[0])
->hasKey('file')
->hasKey('line')
->hasKey('function')
->hasKey('class')
->hasKey('type')
->hasKey('args');
}
public function case_get_previous_throw()
{
$this
->given(
$previous = new SUT('previous'),
$exception = new SUT('foo', 0, [], $previous)
)
->when($result = $exception->getPreviousThrow())
->then
->object($result)
->isIdenticalTo($previous);
}
public function case_get_arguments()
{
$this
->given($exception = new SUT('foo', 0, ['arg', 42, null]))
->when($result = $exception->getArguments())
->then
->array($result)
->isEqualTo(['arg', 42, '(null)']);
}
public function case_get_arguments_from_a_string()
{
$this
->given($exception = new SUT('foo', 0, 'arg'))
->when($result = $exception->getArguments())
->then
->array($result)
->isEqualTo(['arg']);
}
public function case_get_raw_message()
{
$this
->given(
$message = 'foo %s',
$exception = new SUT($message)
)
->when($result = $exception->getRawMessage())
->then
->string($result)
->isEqualTo($message);
}
public function case_get_formatted_message()
{
$this
->given(
$message = 'foo %s',
$exception = new SUT($message, 0, 'bar')
)
->when($result = $exception->getFormattedMessage())
->then
->string($result)
->isEqualTo($exception->getMessage())
->isEqualTo('foo bar');
}
public function case_get_from_object()
{
$this
->given($exception = new SUT('foo'))
->when($result = $exception->getFrom())
->then
->string($result)
->isEqualTo(__METHOD__ . '()');
}
public function case_raise()
{
$this
->given($exception = new SUT('foo'), $line = __LINE__)
->when($result = $exception->raise())
->then
->string($result)
->isEqualTo(
__METHOD__ . '(): (0) foo' . "\n" .
'in ' . __FILE__ . ' at line ' . $line . '.'
);
}
public function case_raise_with_previous()
{
$this
->given(
$previous = new SUT('previous'), $previousLine = __LINE__,
$exception = new SUT('foo', 0, [], $previous), $line = __LINE__
)
->when($result = $exception->raise(true))
->then
->string($result)
->isEqualTo(
__METHOD__ . '(): (0) foo' . "\n" .
'in ' . __FILE__ . ' at line ' . $line . '.' . "\n\n" .
' ⬇' . "\n\n" .
'Nested exception (' . get_class($previous) . '):' . "\n" .
__METHOD__ . '(): (0) previous' . "\n" .
'in ' . __FILE__ . ' at line ' . $previousLine . '.'
);
}
public function case_uncaught()
{
$this
->given(
$this->function->ob_get_level = 0,
$exception = new SUT('foo'), $line = __LINE__
)
->when($result = SUT::uncaught($exception))
->then
->variable($result)
->isNull()
->output
->isEqualTo(
'Uncaught exception (' . get_class($exception) . '):' . "\n" .
__METHOD__ . '(): (0) foo' . "\n" .
'in ' . __FILE__ . ' at line ' . $line . '.'
);
}
public function case_uncaught_not_Hoa()
{
$this
->exception(function () {
SUT::uncaught(new \Exception('foo'));
})
->isInstanceOf('Exception')
->output
->isEmpty();
}
public function case_to_string()
{
$this
->given($exception = new SUT('foo'))
->when($result = $exception->__toString())
->then
->string($result)
->isEqualTo($exception->raise());
}
public function case_disable_uncaught_handler()
{
$this
->given(
$this->function->restore_exception_handler = function () use (&$called) {
$called = true;
return null;
}
)
->when($result = SUT::enableUncaughtHandler(false))
->then
->variable($result)
->isNull()
->boolean($called)
->isTrue();
}
public function case_enable_uncaught_handler()
{
$self = $this;
$this
->given(
$this->function->set_exception_handler = function ($handler) use ($self, &$called) {
$called = true;
$self
->object($handler)
->isInstanceOf('Closure')
->let($reflection = new \ReflectionObject($handler))
->array($invokeParameters = $reflection->getMethod('__invoke')->getParameters())
->hasSize(1)
->string($invokeParameters[0]->getName())
->isEqualTo('exception');
return null;
}
)
->when($result = SUT::enableUncaughtHandler())
->then
->variable($result)
->isNull()
->boolean($called)
->isTrue();
}
}

42
vendor/hoa/exception/composer.json vendored Normal file
View File

@ -0,0 +1,42 @@
{
"name" : "hoa/exception",
"description": "The Hoa\\Exception library.",
"type" : "library",
"keywords" : ["library", "exception"],
"homepage" : "https://hoa-project.net/",
"license" : "BSD-3-Clause",
"authors" : [
{
"name" : "Ivan Enderlin",
"email": "ivan.enderlin@hoa-project.net"
},
{
"name" : "Hoa community",
"homepage": "https://hoa-project.net/"
}
],
"support": {
"email" : "support@hoa-project.net",
"irc" : "irc://chat.freenode.net/hoaproject",
"forum" : "https://users.hoa-project.net/",
"docs" : "https://central.hoa-project.net/Documentation/Library/Exception",
"source": "https://central.hoa-project.net/Resource/Library/Exception"
},
"require": {
"hoa/consistency": "~1.0",
"hoa/event" : "~1.0"
},
"require-dev": {
"hoa/test": "~2.0"
},
"autoload": {
"psr-4": {
"Hoa\\Exception\\": "."
}
},
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
}
}

22
vendor/paragonie/random_compat/LICENSE vendored Normal file
View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Paragon Initiative Enterprises
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

@ -0,0 +1,38 @@
{
"name": "paragonie/random_compat",
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
"keywords": [
"csprng",
"random",
"polyfill",
"pseudorandom"
],
"license": "MIT",
"type": "library",
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com",
"homepage": "https://paragonie.com"
}
],
"support": {
"issues": "https://github.com/paragonie/random_compat/issues",
"email": "info@paragonie.com",
"source": "https://github.com/paragonie/random_compat"
},
"require": {
"php": ">=5.2.0"
},
"require-dev": {
"phpunit/phpunit": "4.*|5.*"
},
"suggest": {
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
},
"autoload": {
"files": [
"lib/random.php"
]
}
}

View File

@ -0,0 +1,5 @@
-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEEd+wCqJDrx5B4OldM0dQE0ZMX+lx1ZWm
pui0SUqD4G29L3NGsz9UhJ/0HjBdbnkhIK5xviT0X5vtjacF6ajgcCArbTB+ds+p
+h7Q084NuSuIpNb6YPfoUFgC/CL9kAoc
-----END PUBLIC KEY-----

View File

@ -0,0 +1,11 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (MingW32)
iQEcBAABAgAGBQJWtW1hAAoJEGuXocKCZATaJf0H+wbZGgskK1dcRTsuVJl9IWip
QwGw/qIKI280SD6/ckoUMxKDCJiFuPR14zmqnS36k7N5UNPnpdTJTS8T11jttSpg
1LCmgpbEIpgaTah+cELDqFCav99fS+bEiAL5lWDAHBTE/XPjGVCqeehyPYref4IW
NDBIEsvnHPHPLsn6X5jq4+Yj5oUixgxaMPiR+bcO4Sh+RzOVB6i2D0upWfRXBFXA
NNnsg9/zjvoC7ZW73y9uSH+dPJTt/Vgfeiv52/v41XliyzbUyLalf02GNPY+9goV
JHG1ulEEBJOCiUD9cE1PUIJwHA/HqyhHIvV350YoEFiHl8iSwm7SiZu5kPjaq74=
=B6+8
-----END PGP SIGNATURE-----

View File

@ -0,0 +1,195 @@
<?php
/**
* Random_* Compatibility Library
* for using the new PHP 7 random_* API in PHP 5 projects
*
* The MIT License (MIT)
*
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
*
* 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.
*/
if (!is_callable('RandomCompat_strlen')) {
if (
defined('MB_OVERLOAD_STRING')
&&
((int) ini_get('mbstring.func_overload')) & MB_OVERLOAD_STRING
) {
/**
* strlen() implementation that isn't brittle to mbstring.func_overload
*
* This version uses mb_strlen() in '8bit' mode to treat strings as raw
* binary rather than UTF-8, ISO-8859-1, etc
*
* @param string $binary_string
*
* @throws TypeError
*
* @return int
*/
function RandomCompat_strlen($binary_string)
{
if (!is_string($binary_string)) {
throw new TypeError(
'RandomCompat_strlen() expects a string'
);
}
return (int) mb_strlen($binary_string, '8bit');
}
} else {
/**
* strlen() implementation that isn't brittle to mbstring.func_overload
*
* This version just used the default strlen()
*
* @param string $binary_string
*
* @throws TypeError
*
* @return int
*/
function RandomCompat_strlen($binary_string)
{
if (!is_string($binary_string)) {
throw new TypeError(
'RandomCompat_strlen() expects a string'
);
}
return (int) strlen($binary_string);
}
}
}
if (!is_callable('RandomCompat_substr')) {
if (
defined('MB_OVERLOAD_STRING')
&&
((int) ini_get('mbstring.func_overload')) & MB_OVERLOAD_STRING
) {
/**
* substr() implementation that isn't brittle to mbstring.func_overload
*
* This version uses mb_substr() in '8bit' mode to treat strings as raw
* binary rather than UTF-8, ISO-8859-1, etc
*
* @param string $binary_string
* @param int $start
* @param int|null $length (optional)
*
* @throws TypeError
*
* @return string
*/
function RandomCompat_substr($binary_string, $start, $length = null)
{
if (!is_string($binary_string)) {
throw new TypeError(
'RandomCompat_substr(): First argument should be a string'
);
}
if (!is_int($start)) {
throw new TypeError(
'RandomCompat_substr(): Second argument should be an integer'
);
}
if ($length === null) {
/**
* mb_substr($str, 0, NULL, '8bit') returns an empty string on
* PHP 5.3, so we have to find the length ourselves.
*/
/** @var int $length */
$length = RandomCompat_strlen($binary_string) - $start;
} elseif (!is_int($length)) {
throw new TypeError(
'RandomCompat_substr(): Third argument should be an integer, or omitted'
);
}
// Consistency with PHP's behavior
if ($start === RandomCompat_strlen($binary_string) && $length === 0) {
return '';
}
if ($start > RandomCompat_strlen($binary_string)) {
return '';
}
return (string) mb_substr(
(string) $binary_string,
(int) $start,
(int) $length,
'8bit'
);
}
} else {
/**
* substr() implementation that isn't brittle to mbstring.func_overload
*
* This version just uses the default substr()
*
* @param string $binary_string
* @param int $start
* @param int|null $length (optional)
*
* @throws TypeError
*
* @return string
*/
function RandomCompat_substr($binary_string, $start, $length = null)
{
if (!is_string($binary_string)) {
throw new TypeError(
'RandomCompat_substr(): First argument should be a string'
);
}
if (!is_int($start)) {
throw new TypeError(
'RandomCompat_substr(): Second argument should be an integer'
);
}
if ($length !== null) {
if (!is_int($length)) {
throw new TypeError(
'RandomCompat_substr(): Third argument should be an integer, or omitted'
);
}
return (string) substr(
(string )$binary_string,
(int) $start,
(int) $length
);
}
return (string) substr(
(string) $binary_string,
(int) $start
);
}
}
}

View File

@ -0,0 +1,77 @@
<?php
/**
* Random_* Compatibility Library
* for using the new PHP 7 random_* API in PHP 5 projects
*
* The MIT License (MIT)
*
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
*
* 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.
*/
if (!is_callable('RandomCompat_intval')) {
/**
* Cast to an integer if we can, safely.
*
* If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX)
* (non-inclusive), it will sanely cast it to an int. If you it's equal to
* ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats
* lose precision, so the <= and => operators might accidentally let a float
* through.
*
* @param int|float $number The number we want to convert to an int
* @param bool $fail_open Set to true to not throw an exception
*
* @return float|int
* @psalm-suppress InvalidReturnType
*
* @throws TypeError
*/
function RandomCompat_intval($number, $fail_open = false)
{
if (is_int($number) || is_float($number)) {
$number += 0;
} elseif (is_numeric($number)) {
/** @psalm-suppress InvalidOperand */
$number += 0;
}
/** @var int|float $number */
if (
is_float($number)
&&
$number > ~PHP_INT_MAX
&&
$number < PHP_INT_MAX
) {
$number = (int) $number;
}
if (is_int($number)) {
return (int) $number;
} elseif (!$fail_open) {
throw new TypeError(
'Expected an integer.'
);
}
return $number;
}
}

View File

@ -0,0 +1,49 @@
<?php
/**
* Random_* Compatibility Library
* for using the new PHP 7 random_* API in PHP 5 projects
*
* The MIT License (MIT)
*
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
*
* 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.
*/
if (!class_exists('Error', false)) {
// We can't really avoid making this extend Exception in PHP 5.
class Error extends Exception
{
}
}
if (!class_exists('TypeError', false)) {
if (is_subclass_of('Error', 'Exception')) {
class TypeError extends Error
{
}
} else {
class TypeError extends Exception
{
}
}
}

View File

@ -0,0 +1,225 @@
<?php
/**
* Random_* Compatibility Library
* for using the new PHP 7 random_* API in PHP 5 projects
*
* @version 2.0.17
* @released 2018-07-04
*
* The MIT License (MIT)
*
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
*
* 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.
*/
if (!defined('PHP_VERSION_ID')) {
// This constant was introduced in PHP 5.2.7
$RandomCompatversion = array_map('intval', explode('.', PHP_VERSION));
define(
'PHP_VERSION_ID',
$RandomCompatversion[0] * 10000
+ $RandomCompatversion[1] * 100
+ $RandomCompatversion[2]
);
$RandomCompatversion = null;
}
/**
* PHP 7.0.0 and newer have these functions natively.
*/
if (PHP_VERSION_ID >= 70000) {
return;
}
if (!defined('RANDOM_COMPAT_READ_BUFFER')) {
define('RANDOM_COMPAT_READ_BUFFER', 8);
}
$RandomCompatDIR = dirname(__FILE__);
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'byte_safe_strings.php';
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'cast_to_int.php';
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'error_polyfill.php';
if (!is_callable('random_bytes')) {
/**
* PHP 5.2.0 - 5.6.x way to implement random_bytes()
*
* We use conditional statements here to define the function in accordance
* to the operating environment. It's a micro-optimization.
*
* In order of preference:
* 1. Use libsodium if available.
* 2. fread() /dev/urandom if available (never on Windows)
* 3. mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM)
* 4. COM('CAPICOM.Utilities.1')->GetRandom()
*
* See RATIONALE.md for our reasoning behind this particular order
*/
if (extension_loaded('libsodium')) {
// See random_bytes_libsodium.php
if (PHP_VERSION_ID >= 50300 && is_callable('\\Sodium\\randombytes_buf')) {
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_libsodium.php';
} elseif (method_exists('Sodium', 'randombytes_buf')) {
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_libsodium_legacy.php';
}
}
/**
* Reading directly from /dev/urandom:
*/
if (DIRECTORY_SEPARATOR === '/') {
// DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast
// way to exclude Windows.
$RandomCompatUrandom = true;
$RandomCompat_basedir = ini_get('open_basedir');
if (!empty($RandomCompat_basedir)) {
$RandomCompat_open_basedir = explode(
PATH_SEPARATOR,
strtolower($RandomCompat_basedir)
);
$RandomCompatUrandom = (array() !== array_intersect(
array('/dev', '/dev/', '/dev/urandom'),
$RandomCompat_open_basedir
));
$RandomCompat_open_basedir = null;
}
if (
!is_callable('random_bytes')
&&
$RandomCompatUrandom
&&
@is_readable('/dev/urandom')
) {
// Error suppression on is_readable() in case of an open_basedir
// or safe_mode failure. All we care about is whether or not we
// can read it at this point. If the PHP environment is going to
// panic over trying to see if the file can be read in the first
// place, that is not helpful to us here.
// See random_bytes_dev_urandom.php
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_dev_urandom.php';
}
// Unset variables after use
$RandomCompat_basedir = null;
} else {
$RandomCompatUrandom = false;
}
/**
* mcrypt_create_iv()
*
* We only want to use mcypt_create_iv() if:
*
* - random_bytes() hasn't already been defined
* - the mcrypt extensions is loaded
* - One of these two conditions is true:
* - We're on Windows (DIRECTORY_SEPARATOR !== '/')
* - We're not on Windows and /dev/urandom is readabale
* (i.e. we're not in a chroot jail)
* - Special case:
* - If we're not on Windows, but the PHP version is between
* 5.6.10 and 5.6.12, we don't want to use mcrypt. It will
* hang indefinitely. This is bad.
* - If we're on Windows, we want to use PHP >= 5.3.7 or else
* we get insufficient entropy errors.
*/
if (
!is_callable('random_bytes')
&&
// Windows on PHP < 5.3.7 is broken, but non-Windows is not known to be.
(DIRECTORY_SEPARATOR === '/' || PHP_VERSION_ID >= 50307)
&&
// Prevent this code from hanging indefinitely on non-Windows;
// see https://bugs.php.net/bug.php?id=69833
(
DIRECTORY_SEPARATOR !== '/' ||
(PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613)
)
&&
extension_loaded('mcrypt')
) {
// See random_bytes_mcrypt.php
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_mcrypt.php';
}
$RandomCompatUrandom = null;
/**
* This is a Windows-specific fallback, for when the mcrypt extension
* isn't loaded.
*/
if (
!is_callable('random_bytes')
&&
extension_loaded('com_dotnet')
&&
class_exists('COM')
) {
$RandomCompat_disabled_classes = preg_split(
'#\s*,\s*#',
strtolower(ini_get('disable_classes'))
);
if (!in_array('com', $RandomCompat_disabled_classes)) {
try {
$RandomCompatCOMtest = new COM('CAPICOM.Utilities.1');
if (method_exists($RandomCompatCOMtest, 'GetRandom')) {
// See random_bytes_com_dotnet.php
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_com_dotnet.php';
}
} catch (com_exception $e) {
// Don't try to use it.
}
}
$RandomCompat_disabled_classes = null;
$RandomCompatCOMtest = null;
}
/**
* throw new Exception
*/
if (!is_callable('random_bytes')) {
/**
* We don't have any more options, so let's throw an exception right now
* and hope the developer won't let it fail silently.
*
* @param mixed $length
* @psalm-suppress InvalidReturnType
* @throws Exception
* @return string
*/
function random_bytes($length)
{
unset($length); // Suppress "variable not used" warnings.
throw new Exception(
'There is no suitable CSPRNG installed on your system'
);
return '';
}
}
}
if (!is_callable('random_int')) {
require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_int.php';
}
$RandomCompatDIR = null;

View File

@ -0,0 +1,91 @@
<?php
/**
* Random_* Compatibility Library
* for using the new PHP 7 random_* API in PHP 5 projects
*
* The MIT License (MIT)
*
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
*
* 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.
*/
if (!is_callable('random_bytes')) {
/**
* Windows with PHP < 5.3.0 will not have the function
* openssl_random_pseudo_bytes() available, so let's use
* CAPICOM to work around this deficiency.
*
* @param int $bytes
*
* @throws Exception
*
* @return string
*/
function random_bytes($bytes)
{
try {
/** @var int $bytes */
$bytes = RandomCompat_intval($bytes);
} catch (TypeError $ex) {
throw new TypeError(
'random_bytes(): $bytes must be an integer'
);
}
if ($bytes < 1) {
throw new Error(
'Length must be greater than 0'
);
}
/** @var string $buf */
$buf = '';
if (!class_exists('COM')) {
throw new Error(
'COM does not exist'
);
}
/** @var COM $util */
$util = new COM('CAPICOM.Utilities.1');
$execCount = 0;
/**
* Let's not let it loop forever. If we run N times and fail to
* get N bytes of random data, then CAPICOM has failed us.
*/
do {
$buf .= base64_decode((string) $util->GetRandom($bytes, 0));
if (RandomCompat_strlen($buf) >= $bytes) {
/**
* Return our random entropy buffer here:
*/
return (string) RandomCompat_substr($buf, 0, $bytes);
}
++$execCount;
} while ($execCount < $bytes);
/**
* If we reach here, PHP has failed us.
*/
throw new Exception(
'Could not gather sufficient random data'
);
}
}

View File

@ -0,0 +1,190 @@
<?php
/**
* Random_* Compatibility Library
* for using the new PHP 7 random_* API in PHP 5 projects
*
* The MIT License (MIT)
*
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
*
* 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.
*/
if (!defined('RANDOM_COMPAT_READ_BUFFER')) {
define('RANDOM_COMPAT_READ_BUFFER', 8);
}
if (!is_callable('random_bytes')) {
/**
* Unless open_basedir is enabled, use /dev/urandom for
* random numbers in accordance with best practices
*
* Why we use /dev/urandom and not /dev/random
* @ref https://www.2uo.de/myths-about-urandom
* @ref http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers
*
* @param int $bytes
*
* @throws Exception
*
* @return string
*/
function random_bytes($bytes)
{
/** @var resource $fp */
static $fp = null;
/**
* This block should only be run once
*/
if (empty($fp)) {
/**
* We don't want to ever read C:\dev\random, only /dev/urandom on
* Unix-like operating systems. While we guard against this
* condition in random.php, it doesn't hurt to be defensive in depth
* here.
*
* To that end, we only try to open /dev/urandom if we're on a Unix-
* like operating system (which means the directory separator is set
* to "/" not "\".
*/
if (DIRECTORY_SEPARATOR === '/') {
if (!is_readable('/dev/urandom')) {
throw new Exception(
'Environment misconfiguration: ' .
'/dev/urandom cannot be read.'
);
}
/**
* We use /dev/urandom if it is a char device.
* We never fall back to /dev/random
*/
/** @var resource|bool $fp */
$fp = fopen('/dev/urandom', 'rb');
if (is_resource($fp)) {
/** @var array<string, int> $st */
$st = fstat($fp);
if (($st['mode'] & 0170000) !== 020000) {
fclose($fp);
$fp = false;
}
}
}
if (is_resource($fp)) {
/**
* stream_set_read_buffer() does not exist in HHVM
*
* If we don't set the stream's read buffer to 0, PHP will
* internally buffer 8192 bytes, which can waste entropy
*
* stream_set_read_buffer returns 0 on success
*/
if (is_callable('stream_set_read_buffer')) {
stream_set_read_buffer($fp, RANDOM_COMPAT_READ_BUFFER);
}
if (is_callable('stream_set_chunk_size')) {
stream_set_chunk_size($fp, RANDOM_COMPAT_READ_BUFFER);
}
}
}
try {
/** @var int $bytes */
$bytes = RandomCompat_intval($bytes);
} catch (TypeError $ex) {
throw new TypeError(
'random_bytes(): $bytes must be an integer'
);
}
if ($bytes < 1) {
throw new Error(
'Length must be greater than 0'
);
}
/**
* This if() block only runs if we managed to open a file handle
*
* It does not belong in an else {} block, because the above
* if (empty($fp)) line is logic that should only be run once per
* page load.
*/
if (is_resource($fp)) {
/**
* @var int
*/
$remaining = $bytes;
/**
* @var string|bool
*/
$buf = '';
/**
* We use fread() in a loop to protect against partial reads
*/
do {
/**
* @var string|bool
*/
$read = fread($fp, $remaining);
if (!is_string($read)) {
/**
* We cannot safely read from the file. Exit the
* do-while loop and trigger the exception condition
*
* @var string|bool
*/
$buf = false;
break;
}
/**
* Decrease the number of bytes returned from remaining
*/
$remaining -= RandomCompat_strlen($read);
/**
* @var string $buf
*/
$buf .= $read;
} while ($remaining > 0);
/**
* Is our result valid?
* @var string|bool $buf
*/
if (is_string($buf)) {
if (RandomCompat_strlen($buf) === $bytes) {
/**
* Return our random entropy buffer here:
*/
return $buf;
}
}
}
/**
* If we reach here, PHP has failed us.
*/
throw new Exception(
'Error reading from source device'
);
}
}

View File

@ -0,0 +1,91 @@
<?php
/**
* Random_* Compatibility Library
* for using the new PHP 7 random_* API in PHP 5 projects
*
* The MIT License (MIT)
*
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
*
* 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.
*/
if (!is_callable('random_bytes')) {
/**
* If the libsodium PHP extension is loaded, we'll use it above any other
* solution.
*
* libsodium-php project:
* @ref https://github.com/jedisct1/libsodium-php
*
* @param int $bytes
*
* @throws Exception
*
* @return string
*/
function random_bytes($bytes)
{
try {
/** @var int $bytes */
$bytes = RandomCompat_intval($bytes);
} catch (TypeError $ex) {
throw new TypeError(
'random_bytes(): $bytes must be an integer'
);
}
if ($bytes < 1) {
throw new Error(
'Length must be greater than 0'
);
}
/**
* \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be
* generated in one invocation.
*/
/** @var string|bool $buf */
if ($bytes > 2147483647) {
$buf = '';
for ($i = 0; $i < $bytes; $i += 1073741824) {
$n = ($bytes - $i) > 1073741824
? 1073741824
: $bytes - $i;
$buf .= \Sodium\randombytes_buf($n);
}
} else {
/** @var string|bool $buf */
$buf = \Sodium\randombytes_buf($bytes);
}
if (is_string($buf)) {
if (RandomCompat_strlen($buf) === $bytes) {
return $buf;
}
}
/**
* If we reach here, PHP has failed us.
*/
throw new Exception(
'Could not gather sufficient random data'
);
}
}

View File

@ -0,0 +1,93 @@
<?php
/**
* Random_* Compatibility Library
* for using the new PHP 7 random_* API in PHP 5 projects
*
* The MIT License (MIT)
*
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
*
* 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.
*/
if (!is_callable('random_bytes')) {
/**
* If the libsodium PHP extension is loaded, we'll use it above any other
* solution.
*
* libsodium-php project:
* @ref https://github.com/jedisct1/libsodium-php
*
* @param int $bytes
*
* @throws Exception
*
* @return string
*/
function random_bytes($bytes)
{
try {
/** @var int $bytes */
$bytes = RandomCompat_intval($bytes);
} catch (TypeError $ex) {
throw new TypeError(
'random_bytes(): $bytes must be an integer'
);
}
if ($bytes < 1) {
throw new Error(
'Length must be greater than 0'
);
}
/**
* @var string
*/
$buf = '';
/**
* \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be
* generated in one invocation.
*/
if ($bytes > 2147483647) {
for ($i = 0; $i < $bytes; $i += 1073741824) {
$n = ($bytes - $i) > 1073741824
? 1073741824
: $bytes - $i;
$buf .= Sodium::randombytes_buf((int) $n);
}
} else {
$buf .= Sodium::randombytes_buf((int) $bytes);
}
if (is_string($buf)) {
if (RandomCompat_strlen($buf) === $bytes) {
return $buf;
}
}
/**
* If we reach here, PHP has failed us.
*/
throw new Exception(
'Could not gather sufficient random data'
);
}
}

View File

@ -0,0 +1,79 @@
<?php
/**
* Random_* Compatibility Library
* for using the new PHP 7 random_* API in PHP 5 projects
*
* The MIT License (MIT)
*
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
*
* 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.
*/
if (!is_callable('random_bytes')) {
/**
* Powered by ext/mcrypt (and thankfully NOT libmcrypt)
*
* @ref https://bugs.php.net/bug.php?id=55169
* @ref https://github.com/php/php-src/blob/c568ffe5171d942161fc8dda066bce844bdef676/ext/mcrypt/mcrypt.c#L1321-L1386
*
* @param int $bytes
*
* @throws Exception
*
* @return string
*/
function random_bytes($bytes)
{
try {
/** @var int $bytes */
$bytes = RandomCompat_intval($bytes);
} catch (TypeError $ex) {
throw new TypeError(
'random_bytes(): $bytes must be an integer'
);
}
if ($bytes < 1) {
throw new Error(
'Length must be greater than 0'
);
}
/** @var string|bool $buf */
$buf = @mcrypt_create_iv((int) $bytes, (int) MCRYPT_DEV_URANDOM);
if (
is_string($buf)
&&
RandomCompat_strlen($buf) === $bytes
) {
/**
* Return our random entropy buffer here:
*/
return $buf;
}
/**
* If we reach here, PHP has failed us.
*/
throw new Exception(
'Could not gather sufficient random data'
);
}
}

View File

@ -0,0 +1,204 @@
<?php
if (!is_callable('random_int')) {
/**
* Random_* Compatibility Library
* for using the new PHP 7 random_* API in PHP 5 projects
*
* The MIT License (MIT)
*
* Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
*
* 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.
*/
/**
* Fetch a random integer between $min and $max inclusive
*
* @param int $min
* @param int $max
*
* @throws Exception
*
* @return int
*/
function random_int($min, $max)
{
/**
* Type and input logic checks
*
* If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX)
* (non-inclusive), it will sanely cast it to an int. If you it's equal to
* ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats
* lose precision, so the <= and => operators might accidentally let a float
* through.
*/
try {
/** @var int $min */
$min = RandomCompat_intval($min);
} catch (TypeError $ex) {
throw new TypeError(
'random_int(): $min must be an integer'
);
}
try {
/** @var int $max */
$max = RandomCompat_intval($max);
} catch (TypeError $ex) {
throw new TypeError(
'random_int(): $max must be an integer'
);
}
/**
* Now that we've verified our weak typing system has given us an integer,
* let's validate the logic then we can move forward with generating random
* integers along a given range.
*/
if ($min > $max) {
throw new Error(
'Minimum value must be less than or equal to the maximum value'
);
}
if ($max === $min) {
return (int) $min;
}
/**
* Initialize variables to 0
*
* We want to store:
* $bytes => the number of random bytes we need
* $mask => an integer bitmask (for use with the &) operator
* so we can minimize the number of discards
*/
$attempts = $bits = $bytes = $mask = $valueShift = 0;
/** @var int $attempts */
/** @var int $bits */
/** @var int $bytes */
/** @var int $mask */
/** @var int $valueShift */
/**
* At this point, $range is a positive number greater than 0. It might
* overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to
* a float and we will lose some precision.
*
* @var int|float $range
*/
$range = $max - $min;
/**
* Test for integer overflow:
*/
if (!is_int($range)) {
/**
* Still safely calculate wider ranges.
* Provided by @CodesInChaos, @oittaa
*
* @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435
*
* We use ~0 as a mask in this case because it generates all 1s
*
* @ref https://eval.in/400356 (32-bit)
* @ref http://3v4l.org/XX9r5 (64-bit)
*/
$bytes = PHP_INT_SIZE;
/** @var int $mask */
$mask = ~0;
} else {
/**
* $bits is effectively ceil(log($range, 2)) without dealing with
* type juggling
*/
while ($range > 0) {
if ($bits % 8 === 0) {
++$bytes;
}
++$bits;
$range >>= 1;
/** @var int $mask */
$mask = $mask << 1 | 1;
}
$valueShift = $min;
}
/** @var int $val */
$val = 0;
/**
* Now that we have our parameters set up, let's begin generating
* random integers until one falls between $min and $max
*/
/** @psalm-suppress RedundantCondition */
do {
/**
* The rejection probability is at most 0.5, so this corresponds
* to a failure probability of 2^-128 for a working RNG
*/
if ($attempts > 128) {
throw new Exception(
'random_int: RNG is broken - too many rejections'
);
}
/**
* Let's grab the necessary number of random bytes
*/
$randomByteString = random_bytes($bytes);
/**
* Let's turn $randomByteString into an integer
*
* This uses bitwise operators (<< and |) to build an integer
* out of the values extracted from ord()
*
* Example: [9F] | [6D] | [32] | [0C] =>
* 159 + 27904 + 3276800 + 201326592 =>
* 204631455
*/
$val &= 0;
for ($i = 0; $i < $bytes; ++$i) {
$val |= ord($randomByteString[$i]) << ($i * 8);
}
/** @var int $val */
/**
* Apply mask
*/
$val &= $mask;
$val += $valueShift;
++$attempts;
/**
* If $val overflows to a floating point number,
* ... or is larger than $max,
* ... or smaller than $min,
* then try again.
*/
} while (!is_int($val) || $val > $max || $val < $min);
return (int) $val;
}
}

1783
vendor/phpseclib/phpseclib/composer.lock generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,224 @@
<?php
/**
* Miccrosoft BLOB Formatted RSA Key Handler
*
* More info:
*
* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375601(v=vs.85).aspx
*
* PHP version 5
*
* @category Crypt
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2015 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Crypt\RSA;
use ParagonIE\ConstantTime\Base64;
use phpseclib\Math\BigInteger;
/**
* Microsoft BLOB Formatted RSA Key Handler
*
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class MSBLOB
{
/**#@+
* @access private
*/
/**
* Public/Private Key Pair
*/
const PRIVATEKEYBLOB = 0x7;
/**
* Public Key
*/
const PUBLICKEYBLOB = 0x6;
/**
* Public Key
*/
const PUBLICKEYBLOBEX = 0xA;
/**
* RSA public key exchange algorithm
*/
const CALG_RSA_KEYX = 0x0000A400;
/**
* RSA public key exchange algorithm
*/
const CALG_RSA_SIGN = 0x00002400;
/**
* Public Key
*/
const RSA1 = 0x31415352;
/**
* Private Key
*/
const RSA2 = 0x32415352;
/**#@-*/
/**
* Break a public or private key down into its constituent components
*
* @access public
* @param string $key
* @param string $password optional
* @return array
*/
static function load($key, $password = '')
{
if (!is_string($key)) {
return false;
}
$key = Base64::decode($key);
if (!is_string($key) || strlen($key) < 20) {
return false;
}
// PUBLICKEYSTRUC publickeystruc
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa387453(v=vs.85).aspx
extract(unpack('atype/aversion/vreserved/Valgo', self::_string_shift($key, 8)));
switch (ord($type)) {
case self::PUBLICKEYBLOB:
case self::PUBLICKEYBLOBEX:
$publickey = true;
break;
case self::PRIVATEKEYBLOB:
$publickey = false;
break;
default:
return false;
}
$components = array('isPublicKey' => $publickey);
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa375549(v=vs.85).aspx
switch ($algo) {
case self::CALG_RSA_KEYX:
case self::CALG_RSA_SIGN:
break;
default:
return false;
}
// RSAPUBKEY rsapubkey
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa387685(v=vs.85).aspx
// could do V for pubexp but that's unsigned 32-bit whereas some PHP installs only do signed 32-bit
extract(unpack('Vmagic/Vbitlen/a4pubexp', self::_string_shift($key, 12)));
switch ($magic) {
case self::RSA2:
$components['isPublicKey'] = false;
case self::RSA1:
break;
default:
return false;
}
$baseLength = $bitlen / 16;
if (strlen($key) != 2 * $baseLength && strlen($key) != 9 * $baseLength) {
return false;
}
$components[$components['isPublicKey'] ? 'publicExponent' : 'privateExponent'] = new BigInteger(strrev($pubexp), 256);
// BYTE modulus[rsapubkey.bitlen/8]
$components['modulus'] = new BigInteger(strrev(self::_string_shift($key, $bitlen / 8)), 256);
if ($publickey) {
return $components;
}
$components['isPublicKey'] = false;
// BYTE prime1[rsapubkey.bitlen/16]
$components['primes'] = array(1 => new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256));
// BYTE prime2[rsapubkey.bitlen/16]
$components['primes'][] = new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256);
// BYTE exponent1[rsapubkey.bitlen/16]
$components['exponents'] = array(1 => new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256));
// BYTE exponent2[rsapubkey.bitlen/16]
$components['exponents'][] = new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256);
// BYTE coefficient[rsapubkey.bitlen/16]
$components['coefficients'] = array(2 => new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256));
if (isset($components['privateExponent'])) {
$components['publicExponent'] = $components['privateExponent'];
}
// BYTE privateExponent[rsapubkey.bitlen/8]
$components['privateExponent'] = new BigInteger(strrev(self::_string_shift($key, $bitlen / 8)), 256);
return $components;
}
/**
* Convert a private key to the appropriate format.
*
* @access public
* @param \phpseclib\Math\BigInteger $n
* @param \phpseclib\Math\BigInteger $e
* @param \phpseclib\Math\BigInteger $d
* @param array $primes
* @param array $exponents
* @param array $coefficients
* @param string $password optional
* @return string
*/
static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '')
{
$n = strrev($n->toBytes());
$e = str_pad(strrev($e->toBytes()), 4, "\0");
$key = pack('aavV', chr(self::PRIVATEKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX);
$key.= pack('VVa*', self::RSA2, 8 * strlen($n), $e);
$key.= $n;
$key.= strrev($primes[1]->toBytes());
$key.= strrev($primes[2]->toBytes());
$key.= strrev($exponents[1]->toBytes());
$key.= strrev($exponents[2]->toBytes());
$key.= strrev($coefficients[1]->toBytes());
$key.= strrev($d->toBytes());
return Base64::encode($key);
}
/**
* Convert a public key to the appropriate format
*
* @access public
* @param \phpseclib\Math\BigInteger $n
* @param \phpseclib\Math\BigInteger $e
* @return string
*/
static function savePublicKey(BigInteger $n, BigInteger $e)
{
$n = strrev($n->toBytes());
$e = str_pad(strrev($e->toBytes()), 4, "\0");
$key = pack('aavV', chr(self::PUBLICKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX);
$key.= pack('VVa*', self::RSA1, 8 * strlen($n), $e);
$key.= $n;
return Base64::encode($key);
}
/**
* String Shift
*
* Inspired by array_shift
*
* @param string $string
* @param int $index
* @return string
* @access private
*/
static function _string_shift(&$string, $index = 1)
{
$substr = substr($string, 0, $index);
$string = substr($string, $index);
return $substr;
}
}

View File

@ -0,0 +1,141 @@
<?php
/**
* OpenSSH Formatted RSA Key Handler
*
* PHP version 5
*
* Place in $HOME/.ssh/authorized_keys
*
* @category Crypt
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2015 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Crypt\RSA;
use ParagonIE\ConstantTime\Base64;
use phpseclib\Math\BigInteger;
/**
* OpenSSH Formatted RSA Key Handler
*
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class OpenSSH
{
/**
* Default comment
*
* @var string
* @access private
*/
static $comment = 'phpseclib-generated-key';
/**
* Sets the default comment
*
* @access public
* @param string $comment
*/
static function setComment($comment)
{
self::$comment = str_replace(array("\r", "\n"), '', $comment);
}
/**
* Break a public or private key down into its constituent components
*
* @access public
* @param string $key
* @param string $password optional
* @return array
*/
static function load($key, $password = '')
{
if (!is_string($key)) {
return false;
}
$parts = explode(' ', $key, 3);
$key = isset($parts[1]) ? Base64::decode($parts[1]) : Base64::decode($parts[0]);
if ($key === false) {
return false;
}
$comment = isset($parts[2]) ? $parts[2] : false;
if (substr($key, 0, 11) != "\0\0\0\7ssh-rsa") {
return false;
}
self::_string_shift($key, 11);
if (strlen($key) <= 4) {
return false;
}
extract(unpack('Nlength', self::_string_shift($key, 4)));
if (strlen($key) <= $length) {
return false;
}
$publicExponent = new BigInteger(self::_string_shift($key, $length), -256);
if (strlen($key) <= 4) {
return false;
}
extract(unpack('Nlength', self::_string_shift($key, 4)));
if (strlen($key) != $length) {
return false;
}
$modulus = new BigInteger(self::_string_shift($key, $length), -256);
return array(
'isPublicKey' => true,
'modulus' => $modulus,
'publicExponent' => $publicExponent,
'comment' => $comment
);
}
/**
* Convert a public key to the appropriate format
*
* @access public
* @param \phpseclib\Math\BigInteger $n
* @param \phpseclib\Math\BigInteger $e
* @return string
*/
static function savePublicKey(BigInteger $n, BigInteger $e)
{
$publicExponent = $e->toBytes(true);
$modulus = $n->toBytes(true);
// from <http://tools.ietf.org/html/rfc4253#page-15>:
// string "ssh-rsa"
// mpint e
// mpint n
$RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus);
$RSAPublicKey = 'ssh-rsa ' . Base64::encode($RSAPublicKey) . ' ' . self::$comment;
return $RSAPublicKey;
}
/**
* String Shift
*
* Inspired by array_shift
*
* @param string $string
* @param int $index
* @return string
* @access private
*/
static function _string_shift(&$string, $index = 1)
{
$substr = substr($string, 0, $index);
$string = substr($string, $index);
return $substr;
}
}

View File

@ -0,0 +1,487 @@
<?php
/**
* PKCS Formatted RSA Key Handler
*
* PHP version 5
*
* @category Crypt
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2015 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Crypt\RSA;
use ParagonIE\ConstantTime\Base64;
use ParagonIE\ConstantTime\Hex;
use phpseclib\Crypt\AES;
use phpseclib\Crypt\Base;
use phpseclib\Crypt\DES;
use phpseclib\Crypt\TripleDES;
use phpseclib\Math\BigInteger;
/**
* PKCS Formatted RSA Key Handler
*
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
abstract class PKCS
{
/**#@+
* @access private
* @see \phpseclib\Crypt\RSA::createKey()
*/
/**
* ASN1 Integer
*/
const ASN1_INTEGER = 2;
/**
* ASN1 Bit String
*/
const ASN1_BITSTRING = 3;
/**
* ASN1 Octet String
*/
const ASN1_OCTETSTRING = 4;
/**
* ASN1 Object Identifier
*/
const ASN1_OBJECT = 6;
/**
* ASN1 Sequence (with the constucted bit set)
*/
const ASN1_SEQUENCE = 48;
/**#@-*/
/**#@+
* @access private
*/
/**
* Auto-detect the format
*/
const MODE_ANY = 0;
/**
* Require base64-encoded PEM's be supplied
*/
const MODE_PEM = 1;
/**
* Require raw DER's be supplied
*/
const MODE_DER = 2;
/**#@-*/
/**
* Is the key a base-64 encoded PEM, DER or should it be auto-detected?
*
* @access private
* @param int
*/
static $format = self::MODE_ANY;
/**
* Returns the mode constant corresponding to the mode string
*
* @access public
* @param string $mode
* @return int
* @throws \UnexpectedValueException if the block cipher mode is unsupported
*/
static function getEncryptionMode($mode)
{
switch ($mode) {
case 'CBC':
return Base::MODE_CBC;
case 'ECB':
return Base::MODE_ECB;
case 'CFB':
return Base::MODE_CFB;
case 'OFB':
return Base::MODE_OFB;
case 'CTR':
return Base::MODE_CTR;
}
throw new \UnexpectedValueException('Unsupported block cipher mode of operation');
}
/**
* Returns a cipher object corresponding to a string
*
* @access public
* @param string $algo
* @return string
* @throws \UnexpectedValueException if the encryption algorithm is unsupported
*/
static function getEncryptionObject($algo)
{
$modes = '(CBC|ECB|CFB|OFB|CTR)';
switch (true) {
case preg_match("#^AES-(128|192|256)-$modes$#", $algo, $matches):
$cipher = new AES(self::getEncryptionMode($matches[2]));
$cipher->setKeyLength($matches[1]);
return $cipher;
case preg_match("#^DES-EDE3-$modes$#", $algo, $matches):
return new TripleDES(self::getEncryptionMode($matches[1]));
case preg_match("#^DES-$modes$#", $algo, $matches):
return new DES(self::getEncryptionMode($matches[1]));
default:
throw new \UnexpectedValueException('Unsupported encryption algorithmn');
}
}
/**
* Generate a symmetric key for PKCS#1 keys
*
* @access public
* @param string $password
* @param string $iv
* @param int $length
* @return string
*/
static function generateSymmetricKey($password, $iv, $length)
{
$symkey = '';
$iv = substr($iv, 0, 8);
while (strlen($symkey) < $length) {
$symkey.= md5($symkey . $password . $iv, true);
}
return substr($symkey, 0, $length);
}
/**
* Break a public or private key down into its constituent components
*
* @access public
* @param string $key
* @param string $password optional
* @return array
*/
static function load($key, $password = '')
{
if (!is_string($key)) {
return false;
}
$components = array('isPublicKey' => strpos($key, 'PUBLIC') !== false);
/* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is
"outside the scope" of PKCS#1. PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to
protect private keys, however, that's not what OpenSSL* does. OpenSSL protects private keys by adding
two new "fields" to the key - DEK-Info and Proc-Type. These fields are discussed here:
http://tools.ietf.org/html/rfc1421#section-4.6.1.1
http://tools.ietf.org/html/rfc1421#section-4.6.1.3
DES-EDE3-CBC as an algorithm, however, is not discussed anywhere, near as I can tell.
DES-CBC and DES-EDE are discussed in RFC1423, however, DES-EDE3-CBC isn't, nor is its key derivation
function. As is, the definitive authority on this encoding scheme isn't the IETF but rather OpenSSL's
own implementation. ie. the implementation *is* the standard and any bugs that may exist in that
implementation are part of the standard, as well.
* OpenSSL is the de facto standard. It's utilized by OpenSSH and other projects */
if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) {
$iv = Hex::decode(trim($matches[2]));
// remove the Proc-Type / DEK-Info sections as they're no longer needed
$key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $key);
$ciphertext = self::_extractBER($key);
if ($ciphertext === false) {
$ciphertext = $key;
}
$crypto = self::getEncryptionObject($matches[1]);
$crypto->setKey(self::generateSymmetricKey($password, $iv, $crypto->getKeyLength() >> 3));
$crypto->setIV($iv);
$key = $crypto->decrypt($ciphertext);
if ($key === false) {
return false;
}
} else {
if (self::$format != self::MODE_DER) {
$decoded = self::_extractBER($key);
if ($decoded !== false) {
$key = $decoded;
} elseif (self::$format == self::MODE_PEM) {
return false;
}
}
}
if (ord(self::_string_shift($key)) != self::ASN1_SEQUENCE) {
return false;
}
if (self::_decodeLength($key) != strlen($key)) {
return false;
}
$tag = ord(self::_string_shift($key));
/* intended for keys for which OpenSSL's asn1parse returns the following:
0:d=0 hl=4 l= 631 cons: SEQUENCE
4:d=1 hl=2 l= 1 prim: INTEGER :00
7:d=1 hl=2 l= 13 cons: SEQUENCE
9:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
20:d=2 hl=2 l= 0 prim: NULL
22:d=1 hl=4 l= 609 prim: OCTET STRING
ie. PKCS8 keys */
if ($tag == self::ASN1_INTEGER && substr($key, 0, 3) == "\x01\x00\x30") {
self::_string_shift($key, 3);
$tag = self::ASN1_SEQUENCE;
}
if ($tag == self::ASN1_SEQUENCE) {
$temp = self::_string_shift($key, self::_decodeLength($key));
if (ord(self::_string_shift($temp)) != self::ASN1_OBJECT) {
return false;
}
$length = self::_decodeLength($temp);
switch (self::_string_shift($temp, $length)) {
case "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01": // rsaEncryption
break;
case "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03": // pbeWithMD5AndDES-CBC
/*
PBEParameter ::= SEQUENCE {
salt OCTET STRING (SIZE(8)),
iterationCount INTEGER }
*/
if (ord(self::_string_shift($temp)) != self::ASN1_SEQUENCE) {
return false;
}
if (self::_decodeLength($temp) != strlen($temp)) {
return false;
}
self::_string_shift($temp); // assume it's an octet string
$salt = self::_string_shift($temp, self::_decodeLength($temp));
if (ord(self::_string_shift($temp)) != self::ASN1_INTEGER) {
return false;
}
self::_decodeLength($temp);
list(, $iterationCount) = unpack('N', str_pad($temp, 4, chr(0), STR_PAD_LEFT));
self::_string_shift($key); // assume it's an octet string
$length = self::_decodeLength($key);
if (strlen($key) != $length) {
return false;
}
$crypto = new DES(DES::MODE_CBC);
$crypto->setPassword($password, 'pbkdf1', 'md5', $salt, $iterationCount);
$key = $crypto->decrypt($key);
if ($key === false) {
return false;
}
return self::load($key);
default:
return false;
}
/* intended for keys for which OpenSSL's asn1parse returns the following:
0:d=0 hl=4 l= 290 cons: SEQUENCE
4:d=1 hl=2 l= 13 cons: SEQUENCE
6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
17:d=2 hl=2 l= 0 prim: NULL
19:d=1 hl=4 l= 271 prim: BIT STRING */
$tag = ord(self::_string_shift($key)); // skip over the BIT STRING / OCTET STRING tag
self::_decodeLength($key); // skip over the BIT STRING / OCTET STRING length
// "The initial octet shall encode, as an unsigned binary integer wtih bit 1 as the least significant bit, the number of
// unused bits in the final subsequent octet. The number shall be in the range zero to seven."
// -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf (section 8.6.2.2)
if ($tag == self::ASN1_BITSTRING) {
self::_string_shift($key);
}
if (ord(self::_string_shift($key)) != self::ASN1_SEQUENCE) {
return false;
}
if (self::_decodeLength($key) != strlen($key)) {
return false;
}
$tag = ord(self::_string_shift($key));
}
if ($tag != self::ASN1_INTEGER) {
return false;
}
$length = self::_decodeLength($key);
$temp = self::_string_shift($key, $length);
if (strlen($temp) != 1 || ord($temp) > 2) {
$components['modulus'] = new BigInteger($temp, 256);
self::_string_shift($key); // skip over self::ASN1_INTEGER
$length = self::_decodeLength($key);
$components[$components['isPublicKey'] ? 'publicExponent' : 'privateExponent'] = new BigInteger(self::_string_shift($key, $length), 256);
return $components;
}
if (ord(self::_string_shift($key)) != self::ASN1_INTEGER) {
return false;
}
$length = self::_decodeLength($key);
$components['modulus'] = new BigInteger(self::_string_shift($key, $length), 256);
self::_string_shift($key);
$length = self::_decodeLength($key);
$components['publicExponent'] = new BigInteger(self::_string_shift($key, $length), 256);
self::_string_shift($key);
$length = self::_decodeLength($key);
$components['privateExponent'] = new BigInteger(self::_string_shift($key, $length), 256);
self::_string_shift($key);
$length = self::_decodeLength($key);
$components['primes'] = array(1 => new BigInteger(self::_string_shift($key, $length), 256));
self::_string_shift($key);
$length = self::_decodeLength($key);
$components['primes'][] = new BigInteger(self::_string_shift($key, $length), 256);
self::_string_shift($key);
$length = self::_decodeLength($key);
$components['exponents'] = array(1 => new BigInteger(self::_string_shift($key, $length), 256));
self::_string_shift($key);
$length = self::_decodeLength($key);
$components['exponents'][] = new BigInteger(self::_string_shift($key, $length), 256);
self::_string_shift($key);
$length = self::_decodeLength($key);
$components['coefficients'] = array(2 => new BigInteger(self::_string_shift($key, $length), 256));
if (!empty($key)) {
if (ord(self::_string_shift($key)) != self::ASN1_SEQUENCE) {
return false;
}
self::_decodeLength($key);
while (!empty($key)) {
if (ord(self::_string_shift($key)) != self::ASN1_SEQUENCE) {
return false;
}
self::_decodeLength($key);
$key = substr($key, 1);
$length = self::_decodeLength($key);
$components['primes'][] = new BigInteger(self::_string_shift($key, $length), 256);
self::_string_shift($key);
$length = self::_decodeLength($key);
$components['exponents'][] = new BigInteger(self::_string_shift($key, $length), 256);
self::_string_shift($key);
$length = self::_decodeLength($key);
$components['coefficients'][] = new BigInteger(self::_string_shift($key, $length), 256);
}
}
return $components;
}
/**
* Require base64-encoded PEM's be supplied
*
* @see self::load()
* @access public
*/
static function requirePEM()
{
self::$format = self::MODE_PEM;
}
/**
* Require raw DER's be supplied
*
* @see self::load()
* @access public
*/
static function requireDER()
{
self::$format = self::MODE_DER;
}
/**
* Accept any format and auto detect the format
*
* This is the default setting
*
* @see self::load()
* @access public
*/
static function requireAny()
{
self::$format = self::MODE_ANY;
}
/**
* DER-decode the length
*
* DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
* {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
*
* @access private
* @param string $string
* @return int
*/
static function _decodeLength(&$string)
{
$length = ord(self::_string_shift($string));
if ($length & 0x80) { // definite length, long form
$length&= 0x7F;
$temp = self::_string_shift($string, $length);
list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4));
}
return $length;
}
/**
* DER-encode the length
*
* DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
* {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
*
* @access private
* @param int $length
* @return string
*/
static function _encodeLength($length)
{
if ($length <= 0x7F) {
return chr($length);
}
$temp = ltrim(pack('N', $length), chr(0));
return pack('Ca*', 0x80 | strlen($temp), $temp);
}
/**
* String Shift
*
* Inspired by array_shift
*
* @param string $string
* @param int $index
* @return string
* @access private
*/
static function _string_shift(&$string, $index = 1)
{
$substr = substr($string, 0, $index);
$string = substr($string, $index);
return $substr;
}
/**
* Extract raw BER from Base64 encoding
*
* @access private
* @param string $str
* @return string
*/
static function _extractBER($str)
{
/* X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them
* above and beyond the ceritificate.
* ie. some may have the following preceding the -----BEGIN CERTIFICATE----- line:
*
* Bag Attributes
* localKeyID: 01 00 00 00
* subject=/O=organization/OU=org unit/CN=common name
* issuer=/O=organization/CN=common name
*/
$temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1);
// remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
$temp = preg_replace('#-+[^-]+-+#', '', $temp);
// remove new lines
$temp = str_replace(array("\r", "\n", ' '), '', $temp);
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? Base64::decode($temp) : false;
return $temp != false ? $temp : $str;
}
}

View File

@ -0,0 +1,174 @@
<?php
/**
* PKCS#1 Formatted RSA Key Handler
*
* PHP version 5
*
* Used by File/X509.php
*
* Has the following header:
*
* -----BEGIN RSA PUBLIC KEY-----
*
* Analogous to ssh-keygen's pem format (as specified by -m)
*
* @category Crypt
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2015 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Crypt\RSA;
use ParagonIE\ConstantTime\Base64;
use ParagonIE\ConstantTime\Hex;
use phpseclib\Crypt\AES;
use phpseclib\Crypt\DES;
use phpseclib\Crypt\Random;
use phpseclib\Crypt\TripleDES;
use phpseclib\Math\BigInteger;
/**
* PKCS#1 Formatted RSA Key Handler
*
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class PKCS1 extends PKCS
{
/**
* Default encryption algorithm
*
* @var string
* @access private
*/
static $defaultEncryptionAlgorithm = 'DES-EDE3-CBC';
/**
* Sets the default encryption algorithm
*
* @access public
* @param string $algo
*/
static function setEncryptionAlgorithm($algo)
{
self::$defaultEncryptionAlgorithm = $algo;
}
/**
* Convert a private key to the appropriate format.
*
* @access public
* @param \phpseclib\Math\BigInteger $n
* @param \phpseclib\Math\BigInteger $e
* @param \phpseclib\Math\BigInteger $d
* @param array $primes
* @param array $exponents
* @param array $coefficients
* @param string $password optional
* @return string
*/
static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '')
{
$num_primes = count($primes);
$raw = array(
'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi
'modulus' => $n->toBytes(true),
'publicExponent' => $e->toBytes(true),
'privateExponent' => $d->toBytes(true),
'prime1' => $primes[1]->toBytes(true),
'prime2' => $primes[2]->toBytes(true),
'exponent1' => $exponents[1]->toBytes(true),
'exponent2' => $exponents[2]->toBytes(true),
'coefficient' => $coefficients[2]->toBytes(true)
);
$components = array();
foreach ($raw as $name => $value) {
$components[$name] = pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($value)), $value);
}
$RSAPrivateKey = implode('', $components);
if ($num_primes > 2) {
$OtherPrimeInfos = '';
for ($i = 3; $i <= $num_primes; $i++) {
// OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
//
// OtherPrimeInfo ::= SEQUENCE {
// prime INTEGER, -- ri
// exponent INTEGER, -- di
// coefficient INTEGER -- ti
// }
$OtherPrimeInfo = pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true));
$OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true));
$OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true));
$OtherPrimeInfos.= pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo);
}
$RSAPrivateKey.= pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos);
}
$RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
if (!empty($password) || is_string($password)) {
$cipher = self::getEncryptionObject(self::$defaultEncryptionAlgorithm);
$iv = Random::string($cipher->getBlockLength() >> 3);
$cipher->setKey(self::generateSymmetricKey($password, $iv, $cipher->getKeyLength() >> 3));
$cipher->setIV($iv);
$iv = strtoupper(Hex::encode($iv));
$RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" .
"Proc-Type: 4,ENCRYPTED\r\n" .
"DEK-Info: " . self::$defaultEncryptionAlgorithm . ",$iv\r\n" .
"\r\n" .
chunk_split(Base64::encode($cipher->encrypt($RSAPrivateKey)), 64) .
'-----END RSA PRIVATE KEY-----';
} else {
$RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" .
chunk_split(Base64::encode($RSAPrivateKey), 64) .
'-----END RSA PRIVATE KEY-----';
}
return $RSAPrivateKey;
}
/**
* Convert a public key to the appropriate format
*
* @access public
* @param \phpseclib\Math\BigInteger $n
* @param \phpseclib\Math\BigInteger $e
* @return string
*/
static function savePublicKey(BigInteger $n, BigInteger $e)
{
$modulus = $n->toBytes(true);
$publicExponent = $e->toBytes(true);
// from <http://tools.ietf.org/html/rfc3447#appendix-A.1.1>:
// RSAPublicKey ::= SEQUENCE {
// modulus INTEGER, -- n
// publicExponent INTEGER -- e
// }
$components = array(
'modulus' => pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($modulus)), $modulus),
'publicExponent' => pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($publicExponent)), $publicExponent)
);
$RSAPublicKey = pack(
'Ca*a*a*',
self::ASN1_SEQUENCE,
self::_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])),
$components['modulus'],
$components['publicExponent']
);
$RSAPublicKey = "-----BEGIN RSA PUBLIC KEY-----\r\n" .
chunk_split(Base64::encode($RSAPublicKey), 64) .
'-----END RSA PUBLIC KEY-----';
return $RSAPublicKey;
}
}

View File

@ -0,0 +1,209 @@
<?php
/**
* PKCS#8 Formatted RSA Key Handler
*
* PHP version 5
*
* Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set)
*
* Has the following header:
*
* -----BEGIN PUBLIC KEY-----
*
* Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
* is specific to private keys it's basically creating a DER-encoded wrapper
* for keys. This just extends that same concept to public keys (much like ssh-keygen)
*
* @category Crypt
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2015 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Crypt\RSA;
use ParagonIE\ConstantTime\Base64;
use phpseclib\Crypt\DES;
use phpseclib\Crypt\Random;
use phpseclib\Math\BigInteger;
/**
* PKCS#8 Formatted RSA Key Handler
*
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class PKCS8 extends PKCS
{
/**
* Convert a private key to the appropriate format.
*
* @access public
* @param \phpseclib\Math\BigInteger $n
* @param \phpseclib\Math\BigInteger $e
* @param \phpseclib\Math\BigInteger $d
* @param array $primes
* @param array $exponents
* @param array $coefficients
* @param string $password optional
* @return string
*/
static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '')
{
$num_primes = count($primes);
$raw = array(
'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi
'modulus' => $n->toBytes(true),
'publicExponent' => $e->toBytes(true),
'privateExponent' => $d->toBytes(true),
'prime1' => $primes[1]->toBytes(true),
'prime2' => $primes[2]->toBytes(true),
'exponent1' => $exponents[1]->toBytes(true),
'exponent2' => $exponents[2]->toBytes(true),
'coefficient' => $coefficients[2]->toBytes(true)
);
$components = array();
foreach ($raw as $name => $value) {
$components[$name] = pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($value)), $value);
}
$RSAPrivateKey = implode('', $components);
if ($num_primes > 2) {
$OtherPrimeInfos = '';
for ($i = 3; $i <= $num_primes; $i++) {
// OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
//
// OtherPrimeInfo ::= SEQUENCE {
// prime INTEGER, -- ri
// exponent INTEGER, -- di
// coefficient INTEGER -- ti
// }
$OtherPrimeInfo = pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true));
$OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true));
$OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true));
$OtherPrimeInfos.= pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo);
}
$RSAPrivateKey.= pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos);
}
$RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
$rsaOID = "\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00"; // hex version of MA0GCSqGSIb3DQEBAQUA
$RSAPrivateKey = pack(
'Ca*a*Ca*a*',
self::ASN1_INTEGER,
"\01\00",
$rsaOID,
4,
self::_encodeLength(strlen($RSAPrivateKey)),
$RSAPrivateKey
);
$RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
if (!empty($password) || is_string($password)) {
$salt = Random::string(8);
$iterationCount = 2048;
$crypto = new DES(DES::MODE_CBC);
$crypto->setPassword($password, 'pbkdf1', 'md5', $salt, $iterationCount);
$RSAPrivateKey = $crypto->encrypt($RSAPrivateKey);
$parameters = pack(
'Ca*a*Ca*N',
self::ASN1_OCTETSTRING,
self::_encodeLength(strlen($salt)),
$salt,
self::ASN1_INTEGER,
self::_encodeLength(4),
$iterationCount
);
$pbeWithMD5AndDES_CBC = "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03";
$encryptionAlgorithm = pack(
'Ca*a*Ca*a*',
self::ASN1_OBJECT,
self::_encodeLength(strlen($pbeWithMD5AndDES_CBC)),
$pbeWithMD5AndDES_CBC,
self::ASN1_SEQUENCE,
self::_encodeLength(strlen($parameters)),
$parameters
);
$RSAPrivateKey = pack(
'Ca*a*Ca*a*',
self::ASN1_SEQUENCE,
self::_encodeLength(strlen($encryptionAlgorithm)),
$encryptionAlgorithm,
self::ASN1_OCTETSTRING,
self::_encodeLength(strlen($RSAPrivateKey)),
$RSAPrivateKey
);
$RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey);
$RSAPrivateKey = "-----BEGIN ENCRYPTED PRIVATE KEY-----\r\n" .
chunk_split(Base64::encode($RSAPrivateKey), 64) .
'-----END ENCRYPTED PRIVATE KEY-----';
} else {
$RSAPrivateKey = "-----BEGIN PRIVATE KEY-----\r\n" .
chunk_split(Base64::encode($RSAPrivateKey), 64) .
'-----END PRIVATE KEY-----';
}
return $RSAPrivateKey;
}
/**
* Convert a public key to the appropriate format
*
* @access public
* @param \phpseclib\Math\BigInteger $n
* @param \phpseclib\Math\BigInteger $e
* @return string
*/
static function savePublicKey(BigInteger $n, BigInteger $e)
{
$modulus = $n->toBytes(true);
$publicExponent = $e->toBytes(true);
// from <http://tools.ietf.org/html/rfc3447#appendix-A.1.1>:
// RSAPublicKey ::= SEQUENCE {
// modulus INTEGER, -- n
// publicExponent INTEGER -- e
// }
$components = array(
'modulus' => pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($modulus)), $modulus),
'publicExponent' => pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($publicExponent)), $publicExponent)
);
$RSAPublicKey = pack(
'Ca*a*a*',
self::ASN1_SEQUENCE,
self::_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])),
$components['modulus'],
$components['publicExponent']
);
// sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.
$rsaOID = "\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00"; // hex version of MA0GCSqGSIb3DQEBAQUA
$RSAPublicKey = chr(0) . $RSAPublicKey;
$RSAPublicKey = chr(3) . self::_encodeLength(strlen($RSAPublicKey)) . $RSAPublicKey;
$RSAPublicKey = pack(
'Ca*a*',
self::ASN1_SEQUENCE,
self::_encodeLength(strlen($rsaOID . $RSAPublicKey)),
$rsaOID . $RSAPublicKey
);
$RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
chunk_split(Base64::encode($RSAPublicKey), 64) .
'-----END PUBLIC KEY-----';
return $RSAPublicKey;
}
}

View File

@ -0,0 +1,313 @@
<?php
/**
* PuTTY Formatted RSA Key Handler
*
* PHP version 5
*
* @category Crypt
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2015 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Crypt\RSA;
use ParagonIE\ConstantTime\Base64;
use ParagonIE\ConstantTime\Hex;
use phpseclib\Crypt\AES;
use phpseclib\Crypt\Hash;
use phpseclib\Math\BigInteger;
/**
* PuTTY Formatted RSA Key Handler
*
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class PuTTY
{
/**
* Default comment
*
* @var string
* @access private
*/
static $comment = 'phpseclib-generated-key';
/**
* Sets the default comment
*
* @access public
* @param string $comment
*/
static function setComment($comment)
{
self::$comment = str_replace(array("\r", "\n"), '', $comment);
}
/**
* Generate a symmetric key for PuTTY keys
*
* @access public
* @param string $password
* @param string $iv
* @param int $length
* @return string
*/
static function generateSymmetricKey($password, $length)
{
$symkey = '';
$sequence = 0;
while (strlen($symkey) < $length) {
$temp = pack('Na*', $sequence++, $password);
$symkey.= Hex::decode(sha1($temp));
}
return substr($symkey, 0, $length);
}
/**
* Break a public or private key down into its constituent components
*
* @access public
* @param string $key
* @param string $password optional
* @return array
*/
static function load($key, $password = '')
{
if (!is_string($key)) {
return false;
}
static $one;
if (!isset($one)) {
$one = new BigInteger(1);
}
if (strpos($key, 'BEGIN SSH2 PUBLIC KEY')) {
$data = preg_split('#[\r\n]+#', $key);
$data = array_splice($data, 2, -1);
$data = implode('', $data);
$components = OpenSSH::load($data);
if ($components === false) {
return false;
}
if (!preg_match('#Comment: "(.+)"#', $key, $matches)) {
return false;
}
$components['comment'] = str_replace(array('\\\\', '\"'), array('\\', '"'), $matches[1]);
return $components;
}
$components = array('isPublicKey' => false);
$key = preg_split('#\r\n|\r|\n#', $key);
$type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0]));
if ($type != 'ssh-rsa') {
return false;
}
$encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1]));
$components['comment'] = trim(preg_replace('#Comment: (.+)#', '$1', $key[2]));
$publicLength = trim(preg_replace('#Public-Lines: (\d+)#', '$1', $key[3]));
$public = Base64::decode(implode('', array_map('trim', array_slice($key, 4, $publicLength))));
$public = substr($public, 11);
extract(unpack('Nlength', self::_string_shift($public, 4)));
$components['publicExponent'] = new BigInteger(self::_string_shift($public, $length), -256);
extract(unpack('Nlength', self::_string_shift($public, 4)));
$components['modulus'] = new BigInteger(self::_string_shift($public, $length), -256);
$privateLength = trim(preg_replace('#Private-Lines: (\d+)#', '$1', $key[$publicLength + 4]));
$private = Base64::decode(implode('', array_map('trim', array_slice($key, $publicLength + 5, $privateLength))));
switch ($encryption) {
case 'aes256-cbc':
$symkey = static::generateSymmetricKey($password, 32);
$crypto = new AES(AES::MODE_CBC);
}
if ($encryption != 'none') {
$crypto->setKey($symkey);
$crypto->setIV(str_repeat("\0", $crypto->getBlockLength() >> 3));
$crypto->disablePadding();
$private = $crypto->decrypt($private);
if ($private === false) {
return false;
}
}
extract(unpack('Nlength', self::_string_shift($private, 4)));
if (strlen($private) < $length) {
return false;
}
$components['privateExponent'] = new BigInteger(self::_string_shift($private, $length), -256);
extract(unpack('Nlength', self::_string_shift($private, 4)));
if (strlen($private) < $length) {
return false;
}
$components['primes'] = array(1 => new BigInteger(self::_string_shift($private, $length), -256));
extract(unpack('Nlength', self::_string_shift($private, 4)));
if (strlen($private) < $length) {
return false;
}
$components['primes'][] = new BigInteger(self::_string_shift($private, $length), -256);
$temp = $components['primes'][1]->subtract($one);
$components['exponents'] = array(1 => $components['publicExponent']->modInverse($temp));
$temp = $components['primes'][2]->subtract($one);
$components['exponents'][] = $components['publicExponent']->modInverse($temp);
extract(unpack('Nlength', self::_string_shift($private, 4)));
if (strlen($private) < $length) {
return false;
}
$components['coefficients'] = array(2 => new BigInteger(self::_string_shift($private, $length), -256));
return $components;
}
/**
* String Shift
*
* Inspired by array_shift
*
* @param string $string
* @param int $index
* @return string
* @access private
*/
static function _string_shift(&$string, $index = 1)
{
$substr = substr($string, 0, $index);
$string = substr($string, $index);
return $substr;
}
/**
* Convert a private key to the appropriate format.
*
* @access public
* @param \phpseclib\Math\BigInteger $n
* @param \phpseclib\Math\BigInteger $e
* @param \phpseclib\Math\BigInteger $d
* @param array $primes
* @param array $exponents
* @param array $coefficients
* @param string $password optional
* @return string
*/
static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '')
{
if (count($primes) != 2) {
return false;
}
$raw = array(
'modulus' => $n->toBytes(true),
'publicExponent' => $e->toBytes(true),
'privateExponent' => $d->toBytes(true),
'prime1' => $primes[1]->toBytes(true),
'prime2' => $primes[2]->toBytes(true),
'exponent1' => $exponents[1]->toBytes(true),
'exponent2' => $exponents[2]->toBytes(true),
'coefficient' => $coefficients[2]->toBytes(true)
);
$key = "PuTTY-User-Key-File-2: ssh-rsa\r\nEncryption: ";
$encryption = (!empty($password) || is_string($password)) ? 'aes256-cbc' : 'none';
$key.= $encryption;
$key.= "\r\nComment: " . self::$comment . "\r\n";
$public = pack(
'Na*Na*Na*',
strlen('ssh-rsa'),
'ssh-rsa',
strlen($raw['publicExponent']),
$raw['publicExponent'],
strlen($raw['modulus']),
$raw['modulus']
);
$source = pack(
'Na*Na*Na*Na*',
strlen('ssh-rsa'),
'ssh-rsa',
strlen($encryption),
$encryption,
strlen(self::$comment),
self::$comment,
strlen($public),
$public
);
$public = Base64::encode($public);
$key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n";
$key.= chunk_split($public, 64);
$private = pack(
'Na*Na*Na*Na*',
strlen($raw['privateExponent']),
$raw['privateExponent'],
strlen($raw['prime1']),
$raw['prime1'],
strlen($raw['prime2']),
$raw['prime2'],
strlen($raw['coefficient']),
$raw['coefficient']
);
if (empty($password) && !is_string($password)) {
$source.= pack('Na*', strlen($private), $private);
$hashkey = 'putty-private-key-file-mac-key';
} else {
$private.= Random::string(16 - (strlen($private) & 15));
$source.= pack('Na*', strlen($private), $private);
$crypto = new AES();
$crypto->setKey(static::generateSymmetricKey($password, 32));
$crypto->setIV(str_repeat("\0", $crypto->getBlockLength() >> 3));
$crypto->disablePadding();
$private = $crypto->encrypt($private);
$hashkey = 'putty-private-key-file-mac-key' . $password;
}
$private = Base64::encode($private);
$key.= 'Private-Lines: ' . ((strlen($private) + 63) >> 6) . "\r\n";
$key.= chunk_split($private, 64);
$hash = new Hash('sha1');
$hash->setKey(sha1($hashkey, true));
$key.= 'Private-MAC: ' . Hex::encode($hash->hash($source)) . "\r\n";
return $key;
}
/**
* Convert a public key to the appropriate format
*
* @access public
* @param \phpseclib\Math\BigInteger $n
* @param \phpseclib\Math\BigInteger $e
* @return string
*/
static function savePublicKey(BigInteger $n, BigInteger $e)
{
$n = $n->toBytes(true);
$e = $e->toBytes(true);
$key = pack(
'Na*Na*Na*',
strlen('ssh-rsa'),
'ssh-rsa',
strlen($e),
$e,
strlen($n),
$n
);
$key = "---- BEGIN SSH2 PUBLIC KEY ----\r\n" .
'Comment: "' . str_replace(array('\\', '"'), array('\\\\', '\"'), self::$comment) . "\"\r\n";
chunk_split(Base64::encode($key), 64) .
'---- END SSH2 PUBLIC KEY ----';
return $key;
}
}

View File

@ -0,0 +1,103 @@
<?php
/**
* Raw RSA Key Handler
*
* PHP version 5
*
* An array containing two \phpseclib\Math\BigInteger objects.
*
* The exponent can be indexed with any of the following:
*
* 0, e, exponent, publicExponent
*
* The modulus can be indexed with any of the following:
*
* 1, n, modulo, modulus
*
* @category Crypt
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2015 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Crypt\RSA;
use phpseclib\Math\BigInteger;
/**
* Raw RSA Key Handler
*
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class Raw
{
/**
* Break a public or private key down into its constituent components
*
* @access public
* @param string $key
* @param string $password optional
* @return array
*/
static function load($key, $password = '')
{
if (!is_array($key)) {
return false;
}
if (isset($key['isPublicKey']) && isset($key['modulus'])) {
if (isset($key['privateExponent']) || isset($key['publicExponent'])) {
if (!isset($key['primes'])) {
return $key;
}
if (isset($key['exponents']) && isset($key['coefficients']) && isset($key['publicExponent']) && isset($key['privateExponent'])) {
return $key;
}
}
}
$components = array('isPublicKey' => true);
switch (true) {
case isset($key['e']):
$components['publicExponent'] = $key['e'];
break;
case isset($key['exponent']):
$components['publicExponent'] = $key['exponent'];
break;
case isset($key['publicExponent']):
$components['publicExponent'] = $key['publicExponent'];
break;
case isset($key[0]):
$components['publicExponent'] = $key[0];
}
switch (true) {
case isset($key['n']):
$components['modulus'] = $key['n'];
break;
case isset($key['modulo']):
$components['modulus'] = $key['modulo'];
break;
case isset($key['modulus']):
$components['modulus'] = $key['modulus'];
break;
case isset($key[1]):
$components['modulus'] = $key[1];
}
return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false;
}
/**
* Convert a public key to the appropriate format
*
* @access public
* @param \phpseclib\Math\BigInteger $n
* @param \phpseclib\Math\BigInteger $e
* @return string
*/
static function savePublicKey(BigInteger $n, BigInteger $e)
{
return array('e' => clone $e, 'n' => clone $n);
}
}

View File

@ -0,0 +1,147 @@
<?php
/**
* XML Formatted RSA Key Handler
*
* More info:
*
* http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
* http://en.wikipedia.org/wiki/XML_Signature
*
* PHP version 5
*
* @category Crypt
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2015 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Crypt\RSA;
use ParagonIE\ConstantTime\Base64;
use phpseclib\Math\BigInteger;
/**
* XML Formatted RSA Key Handler
*
* @package RSA
* @author Jim Wigginton <terrafrost@php.net>
* @access public
*/
class XML
{
/**
* Break a public or private key down into its constituent components
*
* @access public
* @param string $key
* @param string $password optional
* @return array
*/
static function load($key, $password = '')
{
if (!is_string($key)) {
return false;
}
$components = array(
'isPublicKey' => false,
'primes' => array(),
'exponents' => array(),
'coefficients' => array()
);
$use_errors = libxml_use_internal_errors(true);
$dom = new \DOMDocument();
if (!$dom->loadXML('<xml>' . $key . '</xml>')) {
return false;
}
$xpath = new \DOMXPath($dom);
$keys = array('modulus', 'exponent', 'p', 'q', 'dp', 'dq', 'inverseq', 'd');
foreach ($keys as $key) {
// $dom->getElementsByTagName($key) is case-sensitive
$temp = $xpath->query("//*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='$key']");
if (!$temp->length) {
continue;
}
$value = new BigInteger(Base64::decode($temp->item(0)->nodeValue), 256);
switch ($key) {
case 'modulus':
$components['modulus'] = $value;
break;
case 'exponent':
$components['publicExponent'] = $value;
break;
case 'p':
$components['primes'][1] = $value;
break;
case 'q':
$components['primes'][2] = $value;
break;
case 'dp':
$components['exponents'][1] = $value;
break;
case 'dq':
$components['exponents'][2] = $value;
break;
case 'inverseq':
$components['coefficients'][2] = $value;
break;
case 'd':
$components['privateExponent'] = $value;
}
}
libxml_use_internal_errors($use_errors);
return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false;
}
/**
* Convert a private key to the appropriate format.
*
* @access public
* @param \phpseclib\Math\BigInteger $n
* @param \phpseclib\Math\BigInteger $e
* @param \phpseclib\Math\BigInteger $d
* @param array $primes
* @param array $exponents
* @param array $coefficients
* @param string $password optional
* @return string
*/
static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '')
{
if (count($primes) != 2) {
return false;
}
return "<RSAKeyValue>\r\n" .
' <Modulus>' . Base64::encode($n->toBytes()) . "</Modulus>\r\n" .
' <Exponent>' . Base64::encode($e->toBytes()) . "</Exponent>\r\n" .
' <P>' . Base64::encode($primes[1]->toBytes()) . "</P>\r\n" .
' <Q>' . Base64::encode($primes[2]->toBytes()) . "</Q>\r\n" .
' <DP>' . Base64::encode($exponents[1]->toBytes()) . "</DP>\r\n" .
' <DQ>' . Base64::encode($exponents[2]->toBytes()) . "</DQ>\r\n" .
' <InverseQ>' . Base64::encode($coefficients[2]->toBytes()) . "</InverseQ>\r\n" .
' <D>' . Base64::encode($d->toBytes()) . "</D>\r\n" .
'</RSAKeyValue>';
}
/**
* Convert a public key to the appropriate format
*
* @access public
* @param \phpseclib\Math\BigInteger $n
* @param \phpseclib\Math\BigInteger $e
* @return string
*/
static function savePublicKey(BigInteger $n, BigInteger $e)
{
return "<RSAKeyValue>\r\n" .
' <Modulus>' . Base64::encode($n->toBytes()) . "</Modulus>\r\n" .
' <Exponent>' . Base64::encode($e->toBytes()) . "</Exponent>\r\n" .
'</RSAKeyValue>';
}
}

View File

@ -0,0 +1,26 @@
<?php
/**
* BadConfigurationException
*
* PHP version 5
*
* @category Exception
* @package BadConfigurationException
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2015 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Exception;
/**
* BadConfigurationException
*
* @package BadConfigurationException
* @author Jim Wigginton <terrafrost@php.net>
*/
class BadConfigurationException extends \RuntimeException
{
}

View File

@ -0,0 +1,26 @@
<?php
/**
* FileNotFoundException
*
* PHP version 5
*
* @category Exception
* @package FileNotFoundException
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2015 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Exception;
/**
* FileNotFoundException
*
* @package FileNotFoundException
* @author Jim Wigginton <terrafrost@php.net>
*/
class FileNotFoundException extends \RuntimeException
{
}

View File

@ -0,0 +1,26 @@
<?php
/**
* NoSupportedAlgorithmsException
*
* PHP version 5
*
* @category Exception
* @package NoSupportedAlgorithmsException
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2015 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Exception;
/**
* NoSupportedAlgorithmsException
*
* @package NoSupportedAlgorithmsException
* @author Jim Wigginton <terrafrost@php.net>
*/
class NoSupportedAlgorithmsException extends \RuntimeException
{
}

View File

@ -0,0 +1,26 @@
<?php
/**
* UnsupportedAlgorithmException
*
* PHP version 5
*
* @category Exception
* @package UnsupportedAlgorithmException
* @author Jim Wigginton <terrafrost@php.net>
* @copyright 2015 Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
namespace phpseclib\Exception;
/**
* UnsupportedAlgorithmException
*
* @package UnsupportedAlgorithmException
* @author Jim Wigginton <terrafrost@php.net>
*/
class UnsupportedAlgorithmException extends \RuntimeException
{
}