misc cleanup, update vendor stuff, fix captcha

This commit is contained in:
Floorb 2023-02-24 06:26:40 -05:00
parent 624d9d63d8
commit 5193b4266c
592 changed files with 19688 additions and 5691 deletions

View file

@ -1,53 +0,0 @@
<?php
define('IN_PONEPASTE', 1);
require_once(__DIR__ . '/common.php');
// DB table to use
$table = 'pastes';
// Table's primary key
$primaryKey = 'id';
// Array of database columns which should be read and sent back to DataTables.
// The `db` parameter represents the column name in the database, while the `dt`
// parameter represents the DataTables column identifier. In this case simple
// indexes
$columns = array(
array('db' => 'id', 'dt' => 0),
array('db' => 'member', 'dt' => 1),
array('db' => 'ip', 'dt' => 2),
array('db' => 'visible', 'dt' => 3)
);
$columns2 = array(
array('db' => 'id', 'dt' => 0),
array('db' => 'member', 'dt' => 1),
array('db' => 'ip', 'dt' => 2),
array('db' => 'visible', 'dt' => 3),
array('db' => 'details', 'dt' => 4),
array('db' => 'view', 'dt' => 5),
array('db' => 'delete', 'dt' => 6)
);
// SQL server connection information
$sql_details = array(
'user' => $db_user,
'pass' => $db_pass,
'db' => $db_schema,
'host' => $db_host
);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* If you just want to use the basic configuration for DataTables with PHP
* server-side, there is no need to edit below this line.
*/
require('ssp.pastes.php');
echo json_encode(
SSP::simple($_GET, $sql_details, $table, $primaryKey, $columns, $columns2)
);

View file

@ -8,7 +8,7 @@ require_once('../includes/common.php');
use PonePaste\Models\AdminLog;
use PonePaste\Models\User;
function updateAdminHistory(User $admin, int $action) {
function updateAdminHistory(User $admin, int $action) : void {
$log = new AdminLog([
'user_id' => $admin->id,
'action' => $action,

View file

@ -7,7 +7,7 @@ require_once('common.php');
const CONFIG_FILE_PATH = '../config/site.php';
function updateConfiguration(string $path, array $new_config) {
function updateConfiguration(string $path, array $new_config) : void {
$fp = fopen($path, 'w');
$new_config_text = var_export($new_config, true);

View file

@ -5,7 +5,7 @@ require_once(__DIR__ . '/../includes/common.php');
use PonePaste\Models\User;
use PonePaste\Models\AdminLog;
function updateAdminHistory(User $admin, int $action) {
function updateAdminHistory(User $admin, int $action) : void {
$log = new AdminLog([
'user_id' => $admin->id,
'action' => $action,

429
composer.lock generated
View file

@ -7,29 +7,84 @@
"content-hash": "bc050acf9c5c5997281c5c3a6f33c811",
"packages": [
{
"name": "doctrine/inflector",
"version": "2.0.4",
"name": "brick/math",
"version": "0.11.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
"reference": "8b7ff3e4b7de6b2c84da85637b59fd2880ecaa89"
"url": "https://github.com/brick/math.git",
"reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/8b7ff3e4b7de6b2c84da85637b59fd2880ecaa89",
"reference": "8b7ff3e4b7de6b2c84da85637b59fd2880ecaa89",
"url": "https://api.github.com/repos/brick/math/zipball/0ad82ce168c82ba30d1c01ec86116ab52f589478",
"reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478",
"shasum": ""
},
"require": {
"php": "^8.0"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.2",
"phpunit/phpunit": "^9.0",
"vimeo/psalm": "5.0.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Brick\\Math\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Arbitrary-precision arithmetic library",
"keywords": [
"Arbitrary-precision",
"BigInteger",
"BigRational",
"arithmetic",
"bigdecimal",
"bignum",
"brick",
"math"
],
"support": {
"issues": "https://github.com/brick/math/issues",
"source": "https://github.com/brick/math/tree/0.11.0"
},
"funding": [
{
"url": "https://github.com/BenMorel",
"type": "github"
}
],
"time": "2023-01-15T23:15:59+00:00"
},
{
"name": "doctrine/inflector",
"version": "2.0.6",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
"reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/d9d313a36c872fd6ee06d9a6cbcf713eaa40f024",
"reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^8.2",
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"phpstan/phpstan-strict-rules": "^0.12",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
"vimeo/psalm": "^4.10"
"doctrine/coding-standard": "^10",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpstan/phpstan-strict-rules": "^1.3",
"phpunit/phpunit": "^8.5 || ^9.5",
"vimeo/psalm": "^4.25"
},
"type": "library",
"autoload": {
@ -79,7 +134,7 @@
],
"support": {
"issues": "https://github.com/doctrine/inflector/issues",
"source": "https://github.com/doctrine/inflector/tree/2.0.4"
"source": "https://github.com/doctrine/inflector/tree/2.0.6"
},
"funding": [
{
@ -95,7 +150,7 @@
"type": "tidelift"
}
],
"time": "2021-10-22T20:16:43+00:00"
"time": "2022-10-20T09:10:12+00:00"
},
{
"name": "erusev/parsedown",
@ -149,16 +204,16 @@
},
{
"name": "illuminate/collections",
"version": "v9.4.1",
"version": "v9.52.4",
"source": {
"type": "git",
"url": "https://github.com/illuminate/collections.git",
"reference": "22c4bb17f4e6c6fb470b5957e8232b1b5baf76b0"
"reference": "0168d0e44ea0c4fe5451fe08cde7049b9e9f9741"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/collections/zipball/22c4bb17f4e6c6fb470b5957e8232b1b5baf76b0",
"reference": "22c4bb17f4e6c6fb470b5957e8232b1b5baf76b0",
"url": "https://api.github.com/repos/illuminate/collections/zipball/0168d0e44ea0c4fe5451fe08cde7049b9e9f9741",
"reference": "0168d0e44ea0c4fe5451fe08cde7049b9e9f9741",
"shasum": ""
},
"require": {
@ -200,20 +255,20 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2022-03-07T15:02:25+00:00"
"time": "2023-02-22T11:32:27+00:00"
},
{
"name": "illuminate/conditionable",
"version": "v9.4.1",
"version": "v9.52.4",
"source": {
"type": "git",
"url": "https://github.com/illuminate/conditionable.git",
"reference": "56b4ba1166c264064bf63896f498a2bee320d16a"
"reference": "bea24daa0fa84b7e7b0d5b84f62c71b7e2dc3364"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/conditionable/zipball/56b4ba1166c264064bf63896f498a2bee320d16a",
"reference": "56b4ba1166c264064bf63896f498a2bee320d16a",
"url": "https://api.github.com/repos/illuminate/conditionable/zipball/bea24daa0fa84b7e7b0d5b84f62c71b7e2dc3364",
"reference": "bea24daa0fa84b7e7b0d5b84f62c71b7e2dc3364",
"shasum": ""
},
"require": {
@ -246,20 +301,20 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2022-02-28T16:37:46+00:00"
"time": "2023-02-01T21:42:32+00:00"
},
{
"name": "illuminate/container",
"version": "v9.4.1",
"version": "v9.52.4",
"source": {
"type": "git",
"url": "https://github.com/illuminate/container.git",
"reference": "66f9049b19fb34e74134c6eeff92a442cee068e5"
"reference": "1641dda2d0750b68bb1264a3b37ff3973f2e6265"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/container/zipball/66f9049b19fb34e74134c6eeff92a442cee068e5",
"reference": "66f9049b19fb34e74134c6eeff92a442cee068e5",
"url": "https://api.github.com/repos/illuminate/container/zipball/1641dda2d0750b68bb1264a3b37ff3973f2e6265",
"reference": "1641dda2d0750b68bb1264a3b37ff3973f2e6265",
"shasum": ""
},
"require": {
@ -297,20 +352,20 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2022-03-03T14:08:19+00:00"
"time": "2023-01-24T16:54:18+00:00"
},
{
"name": "illuminate/contracts",
"version": "v9.4.1",
"version": "v9.52.4",
"source": {
"type": "git",
"url": "https://github.com/illuminate/contracts.git",
"reference": "ce68106c575410c71f92ac1c91c5d95c561033bc"
"reference": "44f65d723b13823baa02ff69751a5948bde60c22"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/ce68106c575410c71f92ac1c91c5d95c561033bc",
"reference": "ce68106c575410c71f92ac1c91c5d95c561033bc",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/44f65d723b13823baa02ff69751a5948bde60c22",
"reference": "44f65d723b13823baa02ff69751a5948bde60c22",
"shasum": ""
},
"require": {
@ -345,35 +400,37 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2022-03-04T18:18:32+00:00"
"time": "2023-02-08T14:36:30+00:00"
},
{
"name": "illuminate/database",
"version": "v9.4.1",
"version": "v9.52.4",
"source": {
"type": "git",
"url": "https://github.com/illuminate/database.git",
"reference": "0fffd6ba91eb58330cbf7331c77ea38c2a16b5d9"
"reference": "fc7e9cf5d4c7c4c0a2800c0d345cc9985fb1b040"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/database/zipball/0fffd6ba91eb58330cbf7331c77ea38c2a16b5d9",
"reference": "0fffd6ba91eb58330cbf7331c77ea38c2a16b5d9",
"url": "https://api.github.com/repos/illuminate/database/zipball/fc7e9cf5d4c7c4c0a2800c0d345cc9985fb1b040",
"reference": "fc7e9cf5d4c7c4c0a2800c0d345cc9985fb1b040",
"shasum": ""
},
"require": {
"ext-json": "*",
"brick/math": "^0.9.3|^0.10.2|^0.11",
"ext-pdo": "*",
"illuminate/collections": "^9.0",
"illuminate/container": "^9.0",
"illuminate/contracts": "^9.0",
"illuminate/macroable": "^9.0",
"illuminate/support": "^9.0",
"php": "^8.0.2",
"symfony/console": "^6.0"
"symfony/console": "^6.0.9"
},
"suggest": {
"doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.13.3|^3.1.4).",
"fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).",
"ext-filter": "Required to use the Postgres database driver.",
"fakerphp/faker": "Required to use the eloquent factory builder (^1.21).",
"illuminate/console": "Required to use the database commands (^9.0).",
"illuminate/events": "Required to use the observers with Eloquent (^9.0).",
"illuminate/filesystem": "Required to use the migrations (^9.0).",
@ -413,20 +470,20 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2022-03-07T01:28:38+00:00"
"time": "2023-02-12T20:16:50+00:00"
},
{
"name": "illuminate/macroable",
"version": "v9.4.1",
"version": "v9.52.4",
"source": {
"type": "git",
"url": "https://github.com/illuminate/macroable.git",
"reference": "25a2c6dac2b7541ecbadef952702e84ae15f5354"
"reference": "e3bfaf6401742a9c6abca61b9b10e998e5b6449a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/macroable/zipball/25a2c6dac2b7541ecbadef952702e84ae15f5354",
"reference": "25a2c6dac2b7541ecbadef952702e84ae15f5354",
"url": "https://api.github.com/repos/illuminate/macroable/zipball/e3bfaf6401742a9c6abca61b9b10e998e5b6449a",
"reference": "e3bfaf6401742a9c6abca61b9b10e998e5b6449a",
"shasum": ""
},
"require": {
@ -459,31 +516,32 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2022-02-01T14:44:21+00:00"
"time": "2022-08-09T13:29:29+00:00"
},
{
"name": "illuminate/support",
"version": "v9.4.1",
"version": "v9.52.4",
"source": {
"type": "git",
"url": "https://github.com/illuminate/support.git",
"reference": "568ed7a21a75e0bd9ca641b6c4a626872ee26d6f"
"reference": "63dcb4523ccdfc01cdf5be17791f07cc20982a1e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/support/zipball/568ed7a21a75e0bd9ca641b6c4a626872ee26d6f",
"reference": "568ed7a21a75e0bd9ca641b6c4a626872ee26d6f",
"url": "https://api.github.com/repos/illuminate/support/zipball/63dcb4523ccdfc01cdf5be17791f07cc20982a1e",
"reference": "63dcb4523ccdfc01cdf5be17791f07cc20982a1e",
"shasum": ""
},
"require": {
"doctrine/inflector": "^2.0",
"ext-json": "*",
"ext-ctype": "*",
"ext-filter": "*",
"ext-mbstring": "*",
"illuminate/collections": "^9.0",
"illuminate/conditionable": "^9.0",
"illuminate/contracts": "^9.0",
"illuminate/macroable": "^9.0",
"nesbot/carbon": "^2.53.1",
"nesbot/carbon": "^2.62.1",
"php": "^8.0.2",
"voku/portable-ascii": "^2.0"
},
@ -493,8 +551,9 @@
"suggest": {
"illuminate/filesystem": "Required to use the composer class (^9.0).",
"league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.0.2).",
"ramsey/uuid": "Required to use Str::uuid() (^4.2.2).",
"ramsey/uuid": "Required to use Str::uuid() (^4.7).",
"symfony/process": "Required to use the composer class (^6.0).",
"symfony/uid": "Required to use Str::ulid() (^6.0).",
"symfony/var-dumper": "Required to use the dd function (^6.0).",
"vlucas/phpdotenv": "Required to use the Env class and env helper (^5.4.1)."
},
@ -528,20 +587,20 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2022-03-08T14:39:38+00:00"
"time": "2023-02-13T16:54:43+00:00"
},
{
"name": "nesbot/carbon",
"version": "2.57.0",
"version": "2.66.0",
"source": {
"type": "git",
"url": "https://github.com/briannesbitt/Carbon.git",
"reference": "4a54375c21eea4811dbd1149fe6b246517554e78"
"reference": "496712849902241f04902033b0441b269effe001"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4a54375c21eea4811dbd1149fe6b246517554e78",
"reference": "4a54375c21eea4811dbd1149fe6b246517554e78",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/496712849902241f04902033b0441b269effe001",
"reference": "496712849902241f04902033b0441b269effe001",
"shasum": ""
},
"require": {
@ -552,14 +611,16 @@
"symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0"
},
"require-dev": {
"doctrine/dbal": "^2.0 || ^3.0",
"doctrine/dbal": "^2.0 || ^3.1.4",
"doctrine/orm": "^2.7",
"friendsofphp/php-cs-fixer": "^3.0",
"kylekatarnls/multi-tester": "^2.0",
"ondrejmirtes/better-reflection": "*",
"phpmd/phpmd": "^2.9",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12.54 || ^1.0",
"phpunit/phpunit": "^7.5.20 || ^8.5.14",
"phpstan/phpstan": "^0.12.99 || ^1.7.14",
"phpunit/php-file-iterator": "^2.0.5 || ^3.0.6",
"phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20",
"squizlabs/php_codesniffer": "^3.4"
},
"bin": [
@ -616,15 +677,19 @@
},
"funding": [
{
"url": "https://opencollective.com/Carbon",
"type": "open_collective"
"url": "https://github.com/sponsors/kylekatarnls",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/nesbot/carbon",
"url": "https://opencollective.com/Carbon#sponsor",
"type": "opencollective"
},
{
"url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme",
"type": "tidelift"
}
],
"time": "2022-02-13T18:13:33+00:00"
"time": "2023-01-29T18:53:47+00:00"
},
{
"name": "psr/container",
@ -810,20 +875,21 @@
},
{
"name": "symfony/console",
"version": "v6.0.5",
"version": "v6.2.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "3bebf4108b9e07492a2a4057d207aa5a77d146b1"
"reference": "3e294254f2191762c1d137aed4b94e966965e985"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/3bebf4108b9e07492a2a4057d207aa5a77d146b1",
"reference": "3bebf4108b9e07492a2a4057d207aa5a77d146b1",
"url": "https://api.github.com/repos/symfony/console/zipball/3e294254f2191762c1d137aed4b94e966965e985",
"reference": "3e294254f2191762c1d137aed4b94e966965e985",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"php": ">=8.1",
"symfony/deprecation-contracts": "^2.1|^3",
"symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^1.1|^2|^3",
"symfony/string": "^5.4|^6.0"
@ -885,7 +951,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v6.0.5"
"source": "https://github.com/symfony/console/tree/v6.2.5"
},
"funding": [
{
@ -901,20 +967,87 @@
"type": "tidelift"
}
],
"time": "2022-02-25T10:48:52+00:00"
"time": "2023-01-01T08:38:09+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.25.0",
"name": "symfony/deprecation-contracts",
"version": "v3.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "30885182c981ab175d4d034db0f6f469898070ab"
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
"reference": "30885182c981ab175d4d034db0f6f469898070ab",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/1ee04c65529dea5d8744774d474e7cbd2f1206d3",
"reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.3-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-25T10:21:52+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"shasum": ""
},
"require": {
@ -929,7 +1062,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -967,7 +1100,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
},
"funding": [
{
@ -983,20 +1116,20 @@
"type": "tidelift"
}
],
"time": "2021-10-20T20:35:02+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.25.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "81b86b50cf841a64252b439e738e97f4a34e2783"
"reference": "511a08c03c1960e08a883f4cffcacd219b758354"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783",
"reference": "81b86b50cf841a64252b439e738e97f4a34e2783",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354",
"shasum": ""
},
"require": {
@ -1008,7 +1141,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1048,7 +1181,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
},
"funding": [
{
@ -1064,20 +1197,20 @@
"type": "tidelift"
}
],
"time": "2021-11-23T21:10:46+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.25.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"shasum": ""
},
"require": {
@ -1089,7 +1222,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1132,7 +1265,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
},
"funding": [
{
@ -1148,20 +1281,20 @@
"type": "tidelift"
}
],
"time": "2021-02-19T12:13:01+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.25.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825"
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825",
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"shasum": ""
},
"require": {
@ -1176,7 +1309,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1215,7 +1348,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
},
"funding": [
{
@ -1231,20 +1364,20 @@
"type": "tidelift"
}
],
"time": "2021-11-30T18:21:41+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.25.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c"
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c",
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"shasum": ""
},
"require": {
@ -1253,7 +1386,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1298,7 +1431,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
},
"funding": [
{
@ -1314,24 +1447,24 @@
"type": "tidelift"
}
],
"time": "2022-03-04T08:16:47+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/service-contracts",
"version": "v3.0.0",
"version": "v3.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "36715ebf9fb9db73db0cb24263c79077c6fe8603"
"reference": "aac98028c69df04ee77eb69b96b86ee51fbf4b75"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/36715ebf9fb9db73db0cb24263c79077c6fe8603",
"reference": "36715ebf9fb9db73db0cb24263c79077c6fe8603",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/aac98028c69df04ee77eb69b96b86ee51fbf4b75",
"reference": "aac98028c69df04ee77eb69b96b86ee51fbf4b75",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"php": ">=8.1",
"psr/container": "^2.0"
},
"conflict": {
@ -1343,7 +1476,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.0-dev"
"dev-main": "3.3-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -1353,7 +1486,10 @@
"autoload": {
"psr-4": {
"Symfony\\Contracts\\Service\\": ""
}
},
"exclude-from-classmap": [
"/Test/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@ -1380,7 +1516,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v3.0.0"
"source": "https://github.com/symfony/service-contracts/tree/v3.2.0"
},
"funding": [
{
@ -1396,24 +1532,24 @@
"type": "tidelift"
}
],
"time": "2021-11-04T17:53:12+00:00"
"time": "2022-11-25T10:21:52+00:00"
},
{
"name": "symfony/string",
"version": "v6.0.3",
"version": "v6.2.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "522144f0c4c004c80d56fa47e40e17028e2eefc2"
"reference": "b2dac0fa27b1ac0f9c0c0b23b43977f12308d0b0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/522144f0c4c004c80d56fa47e40e17028e2eefc2",
"reference": "522144f0c4c004c80d56fa47e40e17028e2eefc2",
"url": "https://api.github.com/repos/symfony/string/zipball/b2dac0fa27b1ac0f9c0c0b23b43977f12308d0b0",
"reference": "b2dac0fa27b1ac0f9c0c0b23b43977f12308d0b0",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"php": ">=8.1",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
@ -1425,6 +1561,7 @@
"require-dev": {
"symfony/error-handler": "^5.4|^6.0",
"symfony/http-client": "^5.4|^6.0",
"symfony/intl": "^6.2",
"symfony/translation-contracts": "^2.0|^3.0",
"symfony/var-exporter": "^5.4|^6.0"
},
@ -1465,7 +1602,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v6.0.3"
"source": "https://github.com/symfony/string/tree/v6.2.5"
},
"funding": [
{
@ -1481,24 +1618,24 @@
"type": "tidelift"
}
],
"time": "2022-01-02T09:55:41+00:00"
"time": "2023-01-01T08:38:09+00:00"
},
{
"name": "symfony/translation",
"version": "v6.0.6",
"version": "v6.2.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "f6639cb9b5e0c57fe31e3263b900a77eedb0c908"
"reference": "60556925a703cfbc1581cde3b3f35b0bb0ea904c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/f6639cb9b5e0c57fe31e3263b900a77eedb0c908",
"reference": "f6639cb9b5e0c57fe31e3263b900a77eedb0c908",
"url": "https://api.github.com/repos/symfony/translation/zipball/60556925a703cfbc1581cde3b3f35b0bb0ea904c",
"reference": "60556925a703cfbc1581cde3b3f35b0bb0ea904c",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"php": ">=8.1",
"symfony/polyfill-mbstring": "~1.0",
"symfony/translation-contracts": "^2.3|^3.0"
},
@ -1514,6 +1651,7 @@
"symfony/translation-implementation": "2.3|3.0"
},
"require-dev": {
"nikic/php-parser": "^4.13",
"psr/log": "^1|^2|^3",
"symfony/config": "^5.4|^6.0",
"symfony/console": "^5.4|^6.0",
@ -1523,10 +1661,12 @@
"symfony/http-kernel": "^5.4|^6.0",
"symfony/intl": "^5.4|^6.0",
"symfony/polyfill-intl-icu": "^1.21",
"symfony/routing": "^5.4|^6.0",
"symfony/service-contracts": "^1.1.2|^2|^3",
"symfony/yaml": "^5.4|^6.0"
},
"suggest": {
"nikic/php-parser": "To use PhpAstExtractor",
"psr/log-implementation": "To use logging capability in translator",
"symfony/config": "",
"symfony/yaml": ""
@ -1560,7 +1700,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/translation/tree/v6.0.6"
"source": "https://github.com/symfony/translation/tree/v6.2.5"
},
"funding": [
{
@ -1576,24 +1716,24 @@
"type": "tidelift"
}
],
"time": "2022-03-02T12:58:14+00:00"
"time": "2023-01-05T07:00:27+00:00"
},
{
"name": "symfony/translation-contracts",
"version": "v3.0.0",
"version": "v3.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation-contracts.git",
"reference": "1b6ea5a7442af5a12dba3dbd6d71034b5b234e77"
"reference": "68cce71402305a015f8c1589bfada1280dc64fe7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/1b6ea5a7442af5a12dba3dbd6d71034b5b234e77",
"reference": "1b6ea5a7442af5a12dba3dbd6d71034b5b234e77",
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/68cce71402305a015f8c1589bfada1280dc64fe7",
"reference": "68cce71402305a015f8c1589bfada1280dc64fe7",
"shasum": ""
},
"require": {
"php": ">=8.0.2"
"php": ">=8.1"
},
"suggest": {
"symfony/translation-implementation": ""
@ -1601,7 +1741,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.0-dev"
"dev-main": "3.3-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -1611,7 +1751,10 @@
"autoload": {
"psr-4": {
"Symfony\\Contracts\\Translation\\": ""
}
},
"exclude-from-classmap": [
"/Test/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@ -1638,7 +1781,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/translation-contracts/tree/v3.0.0"
"source": "https://github.com/symfony/translation-contracts/tree/v3.2.0"
},
"funding": [
{
@ -1654,7 +1797,7 @@
"type": "tidelift"
}
],
"time": "2021-09-07T12:43:40+00:00"
"time": "2022-11-25T10:21:52+00:00"
},
{
"name": "voku/portable-ascii",
@ -1745,5 +1888,5 @@
"ext-redis": "*"
},
"platform-dev": [],
"plugin-api-version": "2.2.0"
"plugin-api-version": "2.3.0"
}

View file

@ -32,4 +32,4 @@ class AbilityHelper {
return false;
}
}
}

View file

@ -25,7 +25,7 @@ class SessionHelper {
return null;
}
public static function destroySession() {
public static function destroySession() : void {
$token = $_COOKIE[SessionHelper::REMEMBER_TOKEN_COOKIE];
UserSession::where('token', $token)->delete();

13
includes/Models/Badge.php Normal file
View file

@ -0,0 +1,13 @@
<?php
namespace PonePaste\Models;
use Illuminate\Database\Eloquent\Model;
class Badge extends Model {
protected $table = 'badges';
public $timestamps = false;
protected $fillable = [
'name', 'image_url'
];
}

View file

@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
class User extends Model {
protected $table = 'users';
protected $fillable = [
'username', 'password', 'recovery_code_hash', 'date'
'username', 'password', 'recovery_code_hash'
];
public function session() {
@ -22,5 +22,9 @@ class User extends Model {
return $this->hasMany(Paste::class)
->whereRaw("((expiry IS NULL) OR ((expiry != 'SELF') AND (expiry > NOW())))");
}
public function badges() {
return $this->hasMany(Badge::class);
}
}

View file

@ -1,5 +1,5 @@
<?php
function setupCaptcha() : string {
function setupCaptcha($token = null) : string {
global $redis;
$allowed = "ABCDEFGHIJKLMNOPQRSTUVYXYZabcdefghijklmnopqrstuvwxyz0123456789";
@ -8,7 +8,9 @@ function setupCaptcha() : string {
$code .= substr($allowed, rand() % (strlen($allowed)), 1);
}
$token = pp_random_password();
if ($token === null) {
$token = pp_random_password();
}
$redis->setex('captcha/' . md5($token), 600, $code);

View file

@ -6,6 +6,7 @@ require_once(__DIR__ . '/../vendor/autoload.php');
require_once(__DIR__ . '/config.php');
require_once(__DIR__ . '/functions.php');
require_once(__DIR__ . '/passwords.php');
require_once(__DIR__ . '/captcha.php');
use Illuminate\Database\Capsule\Manager as Capsule;
use PonePaste\Helpers\SessionHelper;
@ -18,10 +19,10 @@ use PonePaste\Helpers\AbilityHelper;
/* View functions */
function javascriptIncludeTag(string $name) : string {
if (PP_DEBUG) {
return "<script src=\"/assets/bundle/${name}.js\"></script>";
return "<script src=\"/assets/bundle/{$name}.js\"></script>";
}
return "<script src=\"/assets/bundle/${name}.min.js\"></script>";
return "<script src=\"/assets/bundle/{$name}.min.js\"></script>";
}
function urlForPage($page = '') : string {
@ -76,7 +77,7 @@ function optionsForSelect(array $displays, array $values, string $currentSelecti
/**
* @throws Exception if the flash level is invalid
*/
function flash(string $level, string $message) {
function flash(string $level, string $message) : void {
if (!isset($_SESSION['flashes'])) {
$_SESSION['flashes'] = [
'success' => [],
@ -93,15 +94,15 @@ function flash(string $level, string $message) {
}
function flashError(string $message) {
function flashError(string $message) : void {
flash('error', $message);
}
function flashWarning(string $message) {
function flashWarning(string $message) : void {
flash('warning', $message);
}
function flashSuccess(string $message) {
function flashSuccess(string $message) : void {
flash('success', $message);
}
@ -117,8 +118,8 @@ function getFlashes() {
return $flashes;
}
function outputFlashes($flashes) {
function __outputFlash($level, $flash) {
function outputFlashes($flashes) : void {
function __outputFlash($level, $flash) : void {
echo '<div class="notification is-' . $level . ' flash">
<i class="fa fa-exclamation-circle" aria-hidden="true"></i>'
. pp_html_escape($flash) .

View file

@ -56,7 +56,7 @@ function tagsToHtmlUser(string | array | Collection $tags, $profile_username) :
return $output;
}
function linkify($value, $protocols = array('http', 'mail'), array $attributes = array()) {
function linkify($value, $protocols = array('http', 'mail'), array $attributes = array()) : array|string|null {
// Link attributes
$attr = '';
foreach ($attributes as $key => $val) {
@ -90,7 +90,7 @@ function linkify($value, $protocols = array('http', 'mail'), array $attributes =
}, $value);
}
function formatBytes($size, $precision = 2) {
function formatBytes($size, $precision = 2) : string {
$base = log($size, 1024);
$suffixes = ['B', 'KB', 'MB', 'GB', 'TB'];
@ -118,7 +118,7 @@ function friendlyDateDifference(DateTime $lesser, DateTime $greater) : string {
foreach ($parts as $part => $value) {
if ($value !== 0) {
$pluralizer = ($value === 1 ? '' : 's');
$friendly .= "${value} ${part}${pluralizer} ";
$friendly .= "{$value} {$part}{$pluralizer} ";
}
}
@ -148,7 +148,7 @@ function truncate(string $input, int $maxWords, int $maxChars) : string {
return $result . ($input == $result ? '' : '[...]');
}
function embedView($paste_id, $p_title, $content, $title) {
function embedView($paste_id, $p_title, $content, $title) : bool {
$stats = false;
if ($content) {
// Build the output
@ -216,7 +216,7 @@ function embedView($paste_id, $p_title, $content, $title) {
return $stats;
}
function addToSitemap(Paste $paste, $priority, $changefreq) {
function addToSitemap(Paste $paste, $priority, $changefreq) : void {
$c_date = date('Y-m-d');
$site_data = file_get_contents("sitemap.xml");
$site_data = str_replace("</urlset>", "", $site_data);

View file

@ -80,6 +80,7 @@ const globalSetup = () => {
main.id = '';
}
// CAPTCHA refresh
const captchaContainer = $('.captcha_container');
if (captchaContainer) {
@ -88,14 +89,27 @@ const globalSetup = () => {
if (refreshElement && imageElement) {
refreshElement.addEventListener('click', () => {
imageElement.src = imageElement.src.split('?')[0] + '?rand=' + Math.random();
let src = imageElement.src;
if (src.indexOf('&refresh') !== -1) {
// yeah, it's kinda cancerous. fuck off.
src = src.split('&rand=')[0];
} else {
src += '&refresh';
}
imageElement.src = src + '&rand=' + Math.random();
});
}
}
Array.prototype.forEach.call($('.js-hidden'), (elem) => {
toggleEl(elem);
});
const hiddenElements = $$('.js-hidden');
if (hiddenElements) {
Array.prototype.forEach.call(hiddenElements, (elem) => {
toggleEl(elem);
});
}
}
export { globalSetup };

View file

@ -488,6 +488,7 @@ const globalSetup = () => {
main.id = '';
}
// CAPTCHA refresh
const captchaContainer = $('.captcha_container');
if (captchaContainer) {
@ -496,14 +497,27 @@ const globalSetup = () => {
if (refreshElement && imageElement) {
refreshElement.addEventListener('click', () => {
imageElement.src = imageElement.src.split('?')[0] + '?rand=' + Math.random();
let src = imageElement.src;
if (src.indexOf('&refresh') !== -1) {
// yeah, it's kinda cancerous. fuck off.
src = src.split('&rand=')[0];
} else {
src += '&refresh';
}
imageElement.src = src + '&rand=' + Math.random();
});
}
}
Array.prototype.forEach.call($('.js-hidden'), (elem) => {
toggleEl(elem);
});
const hiddenElements = $$('.js-hidden');
if (hiddenElements) {
Array.prototype.forEach.call(hiddenElements, (elem) => {
toggleEl(elem);
});
}
};
whenReady(() => {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -219,6 +219,7 @@ const globalSetup = () => {
main.id = '';
}
// CAPTCHA refresh
const captchaContainer = $('.captcha_container');
if (captchaContainer) {
@ -227,14 +228,27 @@ const globalSetup = () => {
if (refreshElement && imageElement) {
refreshElement.addEventListener('click', () => {
imageElement.src = imageElement.src.split('?')[0] + '?rand=' + Math.random();
let src = imageElement.src;
if (src.indexOf('&refresh') !== -1) {
// yeah, it's kinda cancerous. fuck off.
src = src.split('&rand=')[0];
} else {
src += '&refresh';
}
imageElement.src = src + '&rand=' + Math.random();
});
}
}
Array.prototype.forEach.call($('.js-hidden'), (elem) => {
toggleEl(elem);
});
const hiddenElements = $$('.js-hidden');
if (hiddenElements) {
Array.prototype.forEach.call(hiddenElements, (elem) => {
toggleEl(elem);
});
}
};
whenReady(globalSetup);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -488,6 +488,7 @@ const globalSetup = () => {
main.id = '';
}
// CAPTCHA refresh
const captchaContainer = $('.captcha_container');
if (captchaContainer) {
@ -496,14 +497,27 @@ const globalSetup = () => {
if (refreshElement && imageElement) {
refreshElement.addEventListener('click', () => {
imageElement.src = imageElement.src.split('?')[0] + '?rand=' + Math.random();
let src = imageElement.src;
if (src.indexOf('&refresh') !== -1) {
// yeah, it's kinda cancerous. fuck off.
src = src.split('&rand=')[0];
} else {
src += '&refresh';
}
imageElement.src = src + '&rand=' + Math.random();
});
}
}
Array.prototype.forEach.call($('.js-hidden'), (elem) => {
toggleEl(elem);
});
const hiddenElements = $$('.js-hidden');
if (hiddenElements) {
Array.prototype.forEach.call(hiddenElements, (elem) => {
toggleEl(elem);
});
}
};
const getUserInfo = () => {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -8,6 +8,10 @@ if (empty($_GET['t'])) {
die('Invalid token provided.');
}
if (isset($_GET['refresh'])) {
setupCaptcha();
}
$captcha_token = 'captcha/' . md5($_GET['t']);
$captcha_code = $redis->get($captcha_token);

View file

@ -31,7 +31,7 @@ function verifyCaptcha() : string|bool {
* Anything unhandled means to expire never.
* @return string|null Expiry time, or NULL if expires never.
*/
function calculatePasteExpiry(string $expiry) {
function calculatePasteExpiry(string $expiry) : ?string {
// used to use mktime
if ($expiry === 'self') {
return 'SELF';

View file

@ -2,6 +2,7 @@
/** @noinspection PhpDefineCanBeReplacedWithConstInspection */
define('IN_PONEPASTE', 1);
require_once(__DIR__ . '/../includes/common.php');
require_once(__DIR__ . '/../includes/captcha.php');
use PonePaste\Helpers\SessionHelper;
use PonePaste\Models\User;
@ -100,7 +101,7 @@ if (isset($_POST['forgot'])) {
$username = trim($_POST['username']);
$password = pp_password_hash($_POST['password']);
if ($captcha_config['enabled'] && !checkCaptcha($_POST['captcha_token'], trim($_POST['captcha_answer']))) {
if ($captcha_enabled && !checkCaptcha($_POST['captcha_token'], trim($_POST['captcha_answer']))) {
$error = 'Incorrect CAPTCHA.';
} elseif (empty($_POST['password']) || empty($_POST['username'])) {
$error = 'All fields must be filled out.';
@ -118,7 +119,6 @@ if (isset($_POST['forgot'])) {
'username' => $username,
'password' => $password,
'recovery_code_hash' => pp_password_hash($recovery_code),
'date' => $date,
'ip' => $ip
]);
$user->save();

View file

@ -11,7 +11,7 @@ function isRequesterLikelyBot() : bool {
return str_contains(strtolower($_SERVER['HTTP_USER_AGENT']), 'bot');
}
function rawView($content, $p_code) {
function rawView($content, $p_code) : void {
if ($p_code) {
header('Content-Type: text/plain');
echo $content;
@ -192,6 +192,7 @@ if ($paste_code === "pastedown") {
$p_content = $parsedown->text($p_content);
} else {
Highlighter::registerLanguage('green', __DIR__ . '/../config/green.lang.json');
Highlighter::registerLanguage('plaintext', __DIR__ . '/../vendor/scrivo/highlight.php/Highlight/languages/plaintext.json');
$hl = new Highlighter(false);
$highlighted = $hl->highlight($paste_code == 'text' ? 'plaintext' : $paste_code, $p_content)->value;
$lines = HighlightUtilities\splitCodeIntoArray($highlighted);

View file

@ -211,13 +211,14 @@ $flashes = getFlashes();
</div>
<div class="field">
<div class="captcha_container">
<img src="/captcha?t=<?= setupCaptcha() ?>" alt="CAPTCHA Image" />
<img src="/captcha?t=<?= $captcha_token = setupCaptcha() ?>" alt="CAPTCHA Image" />
<span id="captcha_refresh" style="height: 100%;">
<a href="javascript:void(0)">
<i class="fa fa-refresh" style="height: 100%;"></i>
</a>
</span>
<input type="text" class="input" name="scode" placeholder="Enter the CAPTCHA" />
<input type="hidden" name="captcha_token" value="<?= $captcha_token ?>" />
<input type="text" class="input" name="captcha_answer" placeholder="Enter the CAPTCHA" />
<p class="is-size-6 has-text-grey-light has-text-left mt-2">and press "Enter"</p>
</div>
</div>

View file

@ -100,11 +100,17 @@
</div>
<div class="field">
<div class="notification">
<span class="tags are-large"><img src="<?= $_SESSION['captcha']['image_src'] ?>" alt="CAPTCHA" class="imagever" /></span>
<input type="text" class="input" name="scode" value=""
placeholder="Enter the CAPTCHA">
<p class="is-size-6 has-text-grey-light has-text-left mt-2">and
press"Enter"</p>
<div class="captcha_container">
<img src="/captcha?t=<?= $captcha_token = setupCaptcha() ?>" alt="CAPTCHA Image" />
<span id="captcha_refresh" style="height: 100%;">
<a href="javascript:void(0)">
<i class="fa fa-refresh" style="height: 100%;"></i>
</a>
</span>
<input type="hidden" name="captcha_token" value="<?= $captcha_token ?>" />
<input type="text" class="input" name="captcha_answer" placeholder="Enter the CAPTCHA" />
<p class="is-size-6 has-text-grey-light has-text-left mt-2">and press "Enter"</p>
</div>
</div>
</div>
<div class="field">

View file

@ -296,13 +296,14 @@
<?php if ($captcha_enabled && $current_user === null): ?>
<div class="is-one-quarter">
<div class="captcha_container">
<img src="/captcha?t=<?= setupCaptcha() ?>" alt="CAPTCHA Image" />
<img src="/captcha?t=<?= $captcha_token = setupCaptcha() ?>" alt="CAPTCHA Image" />
<span id="captcha_refresh" style="height: 100%;">
<a href="javascript:void(0)">
<i class="fa fa-refresh" style="height: 100%;"></i>
</a>
</span>
<input type="text" class="input" name="scode" placeholder="Enter the CAPTCHA" />
<input type="hidden" name="captcha_token" value="<?= $captcha_token ?>" />
<input type="text" class="input" name="captcha_answer" placeholder="Enter the CAPTCHA" />
<p class="is-size-6 has-text-grey-light has-text-left mt-2">and press "Enter"</p>
</div>
</div>

View file

@ -22,12 +22,10 @@
1000 => '[HorseWriter] Have more than 1000 total views'
];
function outputBadges(array $badgeCandidates, int $actualValue, string $imagePrefix) {
function outputBadges(array $badgeCandidates, int $actualValue, string $imagePrefix) : void {
foreach ($badgeCandidates as $threshold => $badgeTitle) {
if ($actualValue >= $threshold) {
echo "<img src=\"/img/badges/${imagePrefix}_${threshold}.png\" title='$badgeTitle' alt='$badgeTitle' style='margin: 5px;' />";
echo "<img src=\"/img/badges/{$imagePrefix}_{$threshold}.png\" title='$badgeTitle' alt='$badgeTitle' style='margin: 5px;' />";
break;
}
}

View file

@ -208,14 +208,7 @@ $selectedloader = "$bg[$i]"; // set variable equal to which random filename was
<?php if ($totalpastes !== 0 && ($current_user === null || $current_user->id !== $paste_owner_id)) { ?>
<hr>
<label class="label">More from this Author </label>
<?php
foreach ($recommended_pastes as $paste) {
$title = Trim($row['title']);
$titlehov = ($row['title']);
$long_title = pp_html_escape($row['title']);
$title = pp_html_escape(truncate($row['title'], 24, 60));
?>
<?php foreach ($recommended_pastes as $paste) { ?>
<p class="no-margin">
<header class="bd-category-header my-1">
<a href="<?= urlForPaste($paste) ?>" title="<?= pp_html_escape($paste->title) ?>">
@ -397,12 +390,14 @@ $selectedloader = "$bg[$i]"; // set variable equal to which random filename was
var grace2kb = graceRemain / 1000;
var graceDisplay = roundToTwo(grace2kb);
var element = document.getElementById('charNum');
if (graceRemain < 0) {
document.getElementById("charNum").innerHTML = '<b>File Size: </b><span style="color: red;">File Size limit reached</span>';
} else if ((charRemain < 0)) {
document.getElementById("charNum").innerHTML = '<b>File Size: </b><span style="color: orange;">' + graceDisplay + '/24Kb Grace Limit</span>';
element.innerHTML = '<b>File Size: </b><span style="color: red;">File Size limit reached</span>';
} else if (charRemain < 0) {
element.innerHTML = '<b>File Size: </b><span style="color: orange;">' + graceDisplay + '/24Kb Grace Limit</span>';
} else {
document.getElementById("charNum").innerHTML = '<b>File Size: </b><span style="color: green;">' + charDisplay + '/1000Kb</span>';
element.innerHTML = '<b>File Size: </b><span style="color: green;">' + charDisplay + '/1000Kb</span>';
}
}
</script>

18
vendor/autoload.php vendored
View file

@ -2,6 +2,24 @@
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, $err);
} elseif (!headers_sent()) {
echo $err;
}
}
trigger_error(
$err,
E_USER_ERROR
);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit5bf95489f4eff2c10ec062bf7ba377da::getLoader();

5
vendor/bin/carbon vendored
View file

@ -108,7 +108,10 @@ if (PHP_VERSION_ID < 80000) {
}
}
if (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) {
if (
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
) {
include("phpvfscomposer://" . __DIR__ . '/..'.'/nesbot/carbon/bin/carbon');
exit(0);
}

445
vendor/brick/math/CHANGELOG.md vendored Normal file
View file

@ -0,0 +1,445 @@
# Changelog
All notable changes to this project will be documented in this file.
## [0.11.0](https://github.com/brick/math/releases/tag/0.11.0) - 2023-01-16
💥 **Breaking changes**
- Minimum PHP version is now 8.0
- Methods accepting a union of types are now strongly typed<sup>*</sup>
- `MathException` now extends `Exception` instead of `RuntimeException`
<sup>* You may now run into type errors if you were passing `Stringable` objects to `of()` or any of the methods
internally calling `of()`, with `strict_types` enabled. You can fix this by casting `Stringable` objects to `string`
first.</sup>
## [0.10.2](https://github.com/brick/math/releases/tag/0.10.2) - 2022-08-11
👌 **Improvements**
- `BigRational::toFloat()` now simplifies the fraction before performing division (#73) thanks to @olsavmic
## [0.10.1](https://github.com/brick/math/releases/tag/0.10.1) - 2022-08-02
✨ **New features**
- `BigInteger::gcdMultiple()` returns the GCD of multiple `BigInteger` numbers
## [0.10.0](https://github.com/brick/math/releases/tag/0.10.0) - 2022-06-18
💥 **Breaking changes**
- Minimum PHP version is now 7.4
## [0.9.3](https://github.com/brick/math/releases/tag/0.9.3) - 2021-08-15
🚀 **Compatibility with PHP 8.1**
- Support for custom object serialization; this removes a warning on PHP 8.1 due to the `Serializable` interface being deprecated (#60) thanks @TRowbotham
## [0.9.2](https://github.com/brick/math/releases/tag/0.9.2) - 2021-01-20
🐛 **Bug fix**
- Incorrect results could be returned when using the BCMath calculator, with a default scale set with `bcscale()`, on PHP >= 7.2 (#55).
## [0.9.1](https://github.com/brick/math/releases/tag/0.9.1) - 2020-08-19
✨ **New features**
- `BigInteger::not()` returns the bitwise `NOT` value
🐛 **Bug fixes**
- `BigInteger::toBytes()` could return an incorrect binary representation for some numbers
- The bitwise operations `and()`, `or()`, `xor()` on `BigInteger` could return an incorrect result when the GMP extension is not available
## [0.9.0](https://github.com/brick/math/releases/tag/0.9.0) - 2020-08-18
👌 **Improvements**
- `BigNumber::of()` now accepts `.123` and `123.` formats, both of which return a `BigDecimal`
💥 **Breaking changes**
- Deprecated method `BigInteger::powerMod()` has been removed - use `modPow()` instead
- Deprecated method `BigInteger::parse()` has been removed - use `fromBase()` instead
## [0.8.17](https://github.com/brick/math/releases/tag/0.8.17) - 2020-08-19
🐛 **Bug fix**
- `BigInteger::toBytes()` could return an incorrect binary representation for some numbers
- The bitwise operations `and()`, `or()`, `xor()` on `BigInteger` could return an incorrect result when the GMP extension is not available
## [0.8.16](https://github.com/brick/math/releases/tag/0.8.16) - 2020-08-18
🚑 **Critical fix**
- This version reintroduces the deprecated `BigInteger::parse()` method, that has been removed by mistake in version `0.8.9` and should have lasted for the whole `0.8` release cycle.
✨ **New features**
- `BigInteger::modInverse()` calculates a modular multiplicative inverse
- `BigInteger::fromBytes()` creates a `BigInteger` from a byte string
- `BigInteger::toBytes()` converts a `BigInteger` to a byte string
- `BigInteger::randomBits()` creates a pseudo-random `BigInteger` of a given bit length
- `BigInteger::randomRange()` creates a pseudo-random `BigInteger` between two bounds
💩 **Deprecations**
- `BigInteger::powerMod()` is now deprecated in favour of `modPow()`
## [0.8.15](https://github.com/brick/math/releases/tag/0.8.15) - 2020-04-15
🐛 **Fixes**
- added missing `ext-json` requirement, due to `BigNumber` implementing `JsonSerializable`
⚡️ **Optimizations**
- additional optimization in `BigInteger::remainder()`
## [0.8.14](https://github.com/brick/math/releases/tag/0.8.14) - 2020-02-18
✨ **New features**
- `BigInteger::getLowestSetBit()` returns the index of the rightmost one bit
## [0.8.13](https://github.com/brick/math/releases/tag/0.8.13) - 2020-02-16
✨ **New features**
- `BigInteger::isEven()` tests whether the number is even
- `BigInteger::isOdd()` tests whether the number is odd
- `BigInteger::testBit()` tests if a bit is set
- `BigInteger::getBitLength()` returns the number of bits in the minimal representation of the number
## [0.8.12](https://github.com/brick/math/releases/tag/0.8.12) - 2020-02-03
🛠️ **Maintenance release**
Classes are now annotated for better static analysis with [psalm](https://psalm.dev/).
This is a maintenance release: no bug fixes, no new features, no breaking changes.
## [0.8.11](https://github.com/brick/math/releases/tag/0.8.11) - 2020-01-23
✨ **New feature**
`BigInteger::powerMod()` performs a power-with-modulo operation. Useful for crypto.
## [0.8.10](https://github.com/brick/math/releases/tag/0.8.10) - 2020-01-21
✨ **New feature**
`BigInteger::mod()` returns the **modulo** of two numbers. The *modulo* differs from the *remainder* when the signs of the operands are different.
## [0.8.9](https://github.com/brick/math/releases/tag/0.8.9) - 2020-01-08
⚡️ **Performance improvements**
A few additional optimizations in `BigInteger` and `BigDecimal` when one of the operands can be returned as is. Thanks to @tomtomsen in #24.
## [0.8.8](https://github.com/brick/math/releases/tag/0.8.8) - 2019-04-25
🐛 **Bug fixes**
- `BigInteger::toBase()` could return an empty string for zero values (BCMath & Native calculators only, GMP calculator unaffected)
✨ **New features**
- `BigInteger::toArbitraryBase()` converts a number to an arbitrary base, using a custom alphabet
- `BigInteger::fromArbitraryBase()` converts a string in an arbitrary base, using a custom alphabet, back to a number
These methods can be used as the foundation to convert strings between different bases/alphabets, using BigInteger as an intermediate representation.
💩 **Deprecations**
- `BigInteger::parse()` is now deprecated in favour of `fromBase()`
`BigInteger::fromBase()` works the same way as `parse()`, with 2 minor differences:
- the `$base` parameter is required, it does not default to `10`
- it throws a `NumberFormatException` instead of an `InvalidArgumentException` when the number is malformed
## [0.8.7](https://github.com/brick/math/releases/tag/0.8.7) - 2019-04-20
**Improvements**
- Safer conversion from `float` when using custom locales
- **Much faster** `NativeCalculator` implementation 🚀
You can expect **at least a 3x performance improvement** for common arithmetic operations when using the library on systems without GMP or BCMath; it gets exponentially faster on multiplications with a high number of digits. This is due to calculations now being performed on whole blocks of digits (the block size depending on the platform, 32-bit or 64-bit) instead of digit-by-digit as before.
## [0.8.6](https://github.com/brick/math/releases/tag/0.8.6) - 2019-04-11
**New method**
`BigNumber::sum()` returns the sum of one or more numbers.
## [0.8.5](https://github.com/brick/math/releases/tag/0.8.5) - 2019-02-12
**Bug fix**: `of()` factory methods could fail when passing a `float` in environments using a `LC_NUMERIC` locale with a decimal separator other than `'.'` (#20).
Thanks @manowark 👍
## [0.8.4](https://github.com/brick/math/releases/tag/0.8.4) - 2018-12-07
**New method**
`BigDecimal::sqrt()` calculates the square root of a decimal number, to a given scale.
## [0.8.3](https://github.com/brick/math/releases/tag/0.8.3) - 2018-12-06
**New method**
`BigInteger::sqrt()` calculates the square root of a number (thanks @peter279k).
**New exception**
`NegativeNumberException` is thrown when calling `sqrt()` on a negative number.
## [0.8.2](https://github.com/brick/math/releases/tag/0.8.2) - 2018-11-08
**Performance update**
- Further improvement of `toInt()` performance
- `NativeCalculator` can now perform some multiplications more efficiently
## [0.8.1](https://github.com/brick/math/releases/tag/0.8.1) - 2018-11-07
Performance optimization of `toInt()` methods.
## [0.8.0](https://github.com/brick/math/releases/tag/0.8.0) - 2018-10-13
**Breaking changes**
The following deprecated methods have been removed. Use the new method name instead:
| Method removed | Replacement method |
| --- | --- |
| `BigDecimal::getIntegral()` | `BigDecimal::getIntegralPart()` |
| `BigDecimal::getFraction()` | `BigDecimal::getFractionalPart()` |
---
**New features**
`BigInteger` has been augmented with 5 new methods for bitwise operations:
| New method | Description |
| --- | --- |
| `and()` | performs a bitwise `AND` operation on two numbers |
| `or()` | performs a bitwise `OR` operation on two numbers |
| `xor()` | performs a bitwise `XOR` operation on two numbers |
| `shiftedLeft()` | returns the number shifted left by a number of bits |
| `shiftedRight()` | returns the number shifted right by a number of bits |
Thanks to @DASPRiD 👍
## [0.7.3](https://github.com/brick/math/releases/tag/0.7.3) - 2018-08-20
**New method:** `BigDecimal::hasNonZeroFractionalPart()`
**Renamed/deprecated methods:**
- `BigDecimal::getIntegral()` has been renamed to `getIntegralPart()` and is now deprecated
- `BigDecimal::getFraction()` has been renamed to `getFractionalPart()` and is now deprecated
## [0.7.2](https://github.com/brick/math/releases/tag/0.7.2) - 2018-07-21
**Performance update**
`BigInteger::parse()` and `toBase()` now use GMP's built-in base conversion features when available.
## [0.7.1](https://github.com/brick/math/releases/tag/0.7.1) - 2018-03-01
This is a maintenance release, no code has been changed.
- When installed with `--no-dev`, the autoloader does not autoload tests anymore
- Tests and other files unnecessary for production are excluded from the dist package
This will help make installations more compact.
## [0.7.0](https://github.com/brick/math/releases/tag/0.7.0) - 2017-10-02
Methods renamed:
- `BigNumber:sign()` has been renamed to `getSign()`
- `BigDecimal::unscaledValue()` has been renamed to `getUnscaledValue()`
- `BigDecimal::scale()` has been renamed to `getScale()`
- `BigDecimal::integral()` has been renamed to `getIntegral()`
- `BigDecimal::fraction()` has been renamed to `getFraction()`
- `BigRational::numerator()` has been renamed to `getNumerator()`
- `BigRational::denominator()` has been renamed to `getDenominator()`
Classes renamed:
- `ArithmeticException` has been renamed to `MathException`
## [0.6.2](https://github.com/brick/math/releases/tag/0.6.2) - 2017-10-02
The base class for all exceptions is now `MathException`.
`ArithmeticException` has been deprecated, and will be removed in 0.7.0.
## [0.6.1](https://github.com/brick/math/releases/tag/0.6.1) - 2017-10-02
A number of methods have been renamed:
- `BigNumber:sign()` is deprecated; use `getSign()` instead
- `BigDecimal::unscaledValue()` is deprecated; use `getUnscaledValue()` instead
- `BigDecimal::scale()` is deprecated; use `getScale()` instead
- `BigDecimal::integral()` is deprecated; use `getIntegral()` instead
- `BigDecimal::fraction()` is deprecated; use `getFraction()` instead
- `BigRational::numerator()` is deprecated; use `getNumerator()` instead
- `BigRational::denominator()` is deprecated; use `getDenominator()` instead
The old methods will be removed in version 0.7.0.
## [0.6.0](https://github.com/brick/math/releases/tag/0.6.0) - 2017-08-25
- Minimum PHP version is now [7.1](https://gophp71.org/); for PHP 5.6 and PHP 7.0 support, use version `0.5`
- Deprecated method `BigDecimal::withScale()` has been removed; use `toScale()` instead
- Method `BigNumber::toInteger()` has been renamed to `toInt()`
## [0.5.4](https://github.com/brick/math/releases/tag/0.5.4) - 2016-10-17
`BigNumber` classes now implement [JsonSerializable](http://php.net/manual/en/class.jsonserializable.php).
The JSON output is always a string.
## [0.5.3](https://github.com/brick/math/releases/tag/0.5.3) - 2016-03-31
This is a bugfix release. Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6.
## [0.5.2](https://github.com/brick/math/releases/tag/0.5.2) - 2015-08-06
The `$scale` parameter of `BigDecimal::dividedBy()` is now optional again.
## [0.5.1](https://github.com/brick/math/releases/tag/0.5.1) - 2015-07-05
**New method: `BigNumber::toScale()`**
This allows to convert any `BigNumber` to a `BigDecimal` with a given scale, using rounding if necessary.
## [0.5.0](https://github.com/brick/math/releases/tag/0.5.0) - 2015-07-04
**New features**
- Common `BigNumber` interface for all classes, with the following methods:
- `sign()` and derived methods (`isZero()`, `isPositive()`, ...)
- `compareTo()` and derived methods (`isEqualTo()`, `isGreaterThan()`, ...) that work across different `BigNumber` types
- `toBigInteger()`, `toBigDecimal()`, `toBigRational`() conversion methods
- `toInteger()` and `toFloat()` conversion methods to native types
- Unified `of()` behaviour: every class now accepts any type of number, provided that it can be safely converted to the current type
- New method: `BigDecimal::exactlyDividedBy()`; this method automatically computes the scale of the result, provided that the division yields a finite number of digits
- New methods: `BigRational::quotient()` and `remainder()`
- Fine-grained exceptions: `DivisionByZeroException`, `RoundingNecessaryException`, `NumberFormatException`
- Factory methods `zero()`, `one()` and `ten()` available in all classes
- Rounding mode reintroduced in `BigInteger::dividedBy()`
This release also comes with many performance improvements.
---
**Breaking changes**
- `BigInteger`:
- `getSign()` is renamed to `sign()`
- `toString()` is renamed to `toBase()`
- `BigInteger::dividedBy()` now throws an exception by default if the remainder is not zero; use `quotient()` to get the previous behaviour
- `BigDecimal`:
- `getSign()` is renamed to `sign()`
- `getUnscaledValue()` is renamed to `unscaledValue()`
- `getScale()` is renamed to `scale()`
- `getIntegral()` is renamed to `integral()`
- `getFraction()` is renamed to `fraction()`
- `divideAndRemainder()` is renamed to `quotientAndRemainder()`
- `dividedBy()` now takes a **mandatory** `$scale` parameter **before** the rounding mode
- `toBigInteger()` does not accept a `$roundingMode` parameter anymore
- `toBigRational()` does not simplify the fraction anymore; explicitly add `->simplified()` to get the previous behaviour
- `BigRational`:
- `getSign()` is renamed to `sign()`
- `getNumerator()` is renamed to `numerator()`
- `getDenominator()` is renamed to `denominator()`
- `of()` is renamed to `nd()`, while `parse()` is renamed to `of()`
- Miscellaneous:
- `ArithmeticException` is moved to an `Exception\` sub-namespace
- `of()` factory methods now throw `NumberFormatException` instead of `InvalidArgumentException`
## [0.4.3](https://github.com/brick/math/releases/tag/0.4.3) - 2016-03-31
Backport of two bug fixes from the 0.5 branch:
- `BigInteger::parse()` did not always throw `InvalidArgumentException` as expected
- Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6.
## [0.4.2](https://github.com/brick/math/releases/tag/0.4.2) - 2015-06-16
New method: `BigDecimal::stripTrailingZeros()`
## [0.4.1](https://github.com/brick/math/releases/tag/0.4.1) - 2015-06-12
Introducing a `BigRational` class, to perform calculations on fractions of any size.
## [0.4.0](https://github.com/brick/math/releases/tag/0.4.0) - 2015-06-12
Rounding modes have been removed from `BigInteger`, and are now a concept specific to `BigDecimal`.
`BigInteger::dividedBy()` now always returns the quotient of the division.
## [0.3.5](https://github.com/brick/math/releases/tag/0.3.5) - 2016-03-31
Backport of two bug fixes from the 0.5 branch:
- `BigInteger::parse()` did not always throw `InvalidArgumentException` as expected
- Dividing by a negative power of 1 with the same scale as the dividend could trigger an incorrect optimization which resulted in a wrong result. See #6.
## [0.3.4](https://github.com/brick/math/releases/tag/0.3.4) - 2015-06-11
New methods:
- `BigInteger::remainder()` returns the remainder of a division only
- `BigInteger::gcd()` returns the greatest common divisor of two numbers
## [0.3.3](https://github.com/brick/math/releases/tag/0.3.3) - 2015-06-07
Fix `toString()` not handling negative numbers.
## [0.3.2](https://github.com/brick/math/releases/tag/0.3.2) - 2015-06-07
`BigInteger` and `BigDecimal` now have a `getSign()` method that returns:
- `-1` if the number is negative
- `0` if the number is zero
- `1` if the number is positive
## [0.3.1](https://github.com/brick/math/releases/tag/0.3.1) - 2015-06-05
Minor performance improvements
## [0.3.0](https://github.com/brick/math/releases/tag/0.3.0) - 2015-06-04
The `$roundingMode` and `$scale` parameters have been swapped in `BigDecimal::dividedBy()`.
## [0.2.2](https://github.com/brick/math/releases/tag/0.2.2) - 2015-06-04
Stronger immutability guarantee for `BigInteger` and `BigDecimal`.
So far, it would have been possible to break immutability of these classes by calling the `unserialize()` internal function. This release fixes that.
## [0.2.1](https://github.com/brick/math/releases/tag/0.2.1) - 2015-06-02
Added `BigDecimal::divideAndRemainder()`
## [0.2.0](https://github.com/brick/math/releases/tag/0.2.0) - 2015-05-22
- `min()` and `max()` do not accept an `array` anymore, but a variable number of parameters
- **minimum PHP version is now 5.6**
- continuous integration with PHP 7
## [0.1.1](https://github.com/brick/math/releases/tag/0.1.1) - 2014-09-01
- Added `BigInteger::power()`
- Added HHVM support
## [0.1.0](https://github.com/brick/math/releases/tag/0.1.0) - 2014-08-31
First beta release.

20
vendor/brick/math/LICENSE vendored Normal file
View file

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2013-present Benjamin Morel
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.

34
vendor/brick/math/composer.json vendored Normal file
View file

@ -0,0 +1,34 @@
{
"name": "brick/math",
"description": "Arbitrary-precision arithmetic library",
"type": "library",
"keywords": [
"Brick",
"Math",
"Arbitrary-precision",
"Arithmetic",
"BigInteger",
"BigDecimal",
"BigRational",
"Bignum"
],
"license": "MIT",
"require": {
"php": "^8.0"
},
"require-dev": {
"phpunit/phpunit": "^9.0",
"php-coveralls/php-coveralls": "^2.2",
"vimeo/psalm": "5.0.0"
},
"autoload": {
"psr-4": {
"Brick\\Math\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Brick\\Math\\Tests\\": "tests/"
}
}
}

786
vendor/brick/math/src/BigDecimal.php vendored Normal file
View file

@ -0,0 +1,786 @@
<?php
declare(strict_types=1);
namespace Brick\Math;
use Brick\Math\Exception\DivisionByZeroException;
use Brick\Math\Exception\MathException;
use Brick\Math\Exception\NegativeNumberException;
use Brick\Math\Internal\Calculator;
/**
* Immutable, arbitrary-precision signed decimal numbers.
*
* @psalm-immutable
*/
final class BigDecimal extends BigNumber
{
/**
* The unscaled value of this decimal number.
*
* This is a string of digits with an optional leading minus sign.
* No leading zero must be present.
* No leading minus sign must be present if the value is 0.
*/
private string $value;
/**
* The scale (number of digits after the decimal point) of this decimal number.
*
* This must be zero or more.
*/
private int $scale;
/**
* Protected constructor. Use a factory method to obtain an instance.
*
* @param string $value The unscaled value, validated.
* @param int $scale The scale, validated.
*/
protected function __construct(string $value, int $scale = 0)
{
$this->value = $value;
$this->scale = $scale;
}
/**
* Creates a BigDecimal of the given value.
*
* @throws MathException If the value cannot be converted to a BigDecimal.
*
* @psalm-pure
*/
public static function of(BigNumber|int|float|string $value) : BigDecimal
{
return parent::of($value)->toBigDecimal();
}
/**
* Creates a BigDecimal from an unscaled value and a scale.
*
* Example: `(12345, 3)` will result in the BigDecimal `12.345`.
*
* @param BigNumber|int|float|string $value The unscaled value. Must be convertible to a BigInteger.
* @param int $scale The scale of the number, positive or zero.
*
* @throws \InvalidArgumentException If the scale is negative.
*
* @psalm-pure
*/
public static function ofUnscaledValue(BigNumber|int|float|string $value, int $scale = 0) : BigDecimal
{
if ($scale < 0) {
throw new \InvalidArgumentException('The scale cannot be negative.');
}
return new BigDecimal((string) BigInteger::of($value), $scale);
}
/**
* Returns a BigDecimal representing zero, with a scale of zero.
*
* @psalm-pure
*/
public static function zero() : BigDecimal
{
/**
* @psalm-suppress ImpureStaticVariable
* @var BigDecimal|null $zero
*/
static $zero;
if ($zero === null) {
$zero = new BigDecimal('0');
}
return $zero;
}
/**
* Returns a BigDecimal representing one, with a scale of zero.
*
* @psalm-pure
*/
public static function one() : BigDecimal
{
/**
* @psalm-suppress ImpureStaticVariable
* @var BigDecimal|null $one
*/
static $one;
if ($one === null) {
$one = new BigDecimal('1');
}
return $one;
}
/**
* Returns a BigDecimal representing ten, with a scale of zero.
*
* @psalm-pure
*/
public static function ten() : BigDecimal
{
/**
* @psalm-suppress ImpureStaticVariable
* @var BigDecimal|null $ten
*/
static $ten;
if ($ten === null) {
$ten = new BigDecimal('10');
}
return $ten;
}
/**
* Returns the sum of this number and the given one.
*
* The result has a scale of `max($this->scale, $that->scale)`.
*
* @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigDecimal.
*
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
*/
public function plus(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
if ($that->value === '0' && $that->scale <= $this->scale) {
return $this;
}
if ($this->value === '0' && $this->scale <= $that->scale) {
return $that;
}
[$a, $b] = $this->scaleValues($this, $that);
$value = Calculator::get()->add($a, $b);
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
return new BigDecimal($value, $scale);
}
/**
* Returns the difference of this number and the given one.
*
* The result has a scale of `max($this->scale, $that->scale)`.
*
* @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigDecimal.
*
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
*/
public function minus(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
if ($that->value === '0' && $that->scale <= $this->scale) {
return $this;
}
[$a, $b] = $this->scaleValues($this, $that);
$value = Calculator::get()->sub($a, $b);
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
return new BigDecimal($value, $scale);
}
/**
* Returns the product of this number and the given one.
*
* The result has a scale of `$this->scale + $that->scale`.
*
* @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigDecimal.
*
* @throws MathException If the multiplier is not a valid number, or is not convertible to a BigDecimal.
*/
public function multipliedBy(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
if ($that->value === '1' && $that->scale === 0) {
return $this;
}
if ($this->value === '1' && $this->scale === 0) {
return $that;
}
$value = Calculator::get()->mul($this->value, $that->value);
$scale = $this->scale + $that->scale;
return new BigDecimal($value, $scale);
}
/**
* Returns the result of the division of this number by the given one, at the given scale.
*
* @param BigNumber|int|float|string $that The divisor.
* @param int|null $scale The desired scale, or null to use the scale of this number.
* @param int $roundingMode An optional rounding mode.
*
* @throws \InvalidArgumentException If the scale or rounding mode is invalid.
* @throws MathException If the number is invalid, is zero, or rounding was necessary.
*/
public function dividedBy(BigNumber|int|float|string $that, ?int $scale = null, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
{
$that = BigDecimal::of($that);
if ($that->isZero()) {
throw DivisionByZeroException::divisionByZero();
}
if ($scale === null) {
$scale = $this->scale;
} elseif ($scale < 0) {
throw new \InvalidArgumentException('Scale cannot be negative.');
}
if ($that->value === '1' && $that->scale === 0 && $scale === $this->scale) {
return $this;
}
$p = $this->valueWithMinScale($that->scale + $scale);
$q = $that->valueWithMinScale($this->scale - $scale);
$result = Calculator::get()->divRound($p, $q, $roundingMode);
return new BigDecimal($result, $scale);
}
/**
* Returns the exact result of the division of this number by the given one.
*
* The scale of the result is automatically calculated to fit all the fraction digits.
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
*
* @throws MathException If the divisor is not a valid number, is not convertible to a BigDecimal, is zero,
* or the result yields an infinite number of digits.
*/
public function exactlyDividedBy(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
if ($that->value === '0') {
throw DivisionByZeroException::divisionByZero();
}
[, $b] = $this->scaleValues($this, $that);
$d = \rtrim($b, '0');
$scale = \strlen($b) - \strlen($d);
$calculator = Calculator::get();
foreach ([5, 2] as $prime) {
for (;;) {
$lastDigit = (int) $d[-1];
if ($lastDigit % $prime !== 0) {
break;
}
$d = $calculator->divQ($d, (string) $prime);
$scale++;
}
}
return $this->dividedBy($that, $scale)->stripTrailingZeros();
}
/**
* Returns this number exponentiated to the given value.
*
* The result has a scale of `$this->scale * $exponent`.
*
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
*/
public function power(int $exponent) : BigDecimal
{
if ($exponent === 0) {
return BigDecimal::one();
}
if ($exponent === 1) {
return $this;
}
if ($exponent < 0 || $exponent > Calculator::MAX_POWER) {
throw new \InvalidArgumentException(\sprintf(
'The exponent %d is not in the range 0 to %d.',
$exponent,
Calculator::MAX_POWER
));
}
return new BigDecimal(Calculator::get()->pow($this->value, $exponent), $this->scale * $exponent);
}
/**
* Returns the quotient of the division of this number by this given one.
*
* The quotient has a scale of `0`.
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
*
* @throws MathException If the divisor is not a valid decimal number, or is zero.
*/
public function quotient(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
if ($that->isZero()) {
throw DivisionByZeroException::divisionByZero();
}
$p = $this->valueWithMinScale($that->scale);
$q = $that->valueWithMinScale($this->scale);
$quotient = Calculator::get()->divQ($p, $q);
return new BigDecimal($quotient, 0);
}
/**
* Returns the remainder of the division of this number by this given one.
*
* The remainder has a scale of `max($this->scale, $that->scale)`.
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
*
* @throws MathException If the divisor is not a valid decimal number, or is zero.
*/
public function remainder(BigNumber|int|float|string $that) : BigDecimal
{
$that = BigDecimal::of($that);
if ($that->isZero()) {
throw DivisionByZeroException::divisionByZero();
}
$p = $this->valueWithMinScale($that->scale);
$q = $that->valueWithMinScale($this->scale);
$remainder = Calculator::get()->divR($p, $q);
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
return new BigDecimal($remainder, $scale);
}
/**
* Returns the quotient and remainder of the division of this number by the given one.
*
* The quotient has a scale of `0`, and the remainder has a scale of `max($this->scale, $that->scale)`.
*
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
*
* @return BigDecimal[] An array containing the quotient and the remainder.
*
* @throws MathException If the divisor is not a valid decimal number, or is zero.
*/
public function quotientAndRemainder(BigNumber|int|float|string $that) : array
{
$that = BigDecimal::of($that);
if ($that->isZero()) {
throw DivisionByZeroException::divisionByZero();
}
$p = $this->valueWithMinScale($that->scale);
$q = $that->valueWithMinScale($this->scale);
[$quotient, $remainder] = Calculator::get()->divQR($p, $q);
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
$quotient = new BigDecimal($quotient, 0);
$remainder = new BigDecimal($remainder, $scale);
return [$quotient, $remainder];
}
/**
* Returns the square root of this number, rounded down to the given number of decimals.
*
* @throws \InvalidArgumentException If the scale is negative.
* @throws NegativeNumberException If this number is negative.
*/
public function sqrt(int $scale) : BigDecimal
{
if ($scale < 0) {
throw new \InvalidArgumentException('Scale cannot be negative.');
}
if ($this->value === '0') {
return new BigDecimal('0', $scale);
}
if ($this->value[0] === '-') {
throw new NegativeNumberException('Cannot calculate the square root of a negative number.');
}
$value = $this->value;
$addDigits = 2 * $scale - $this->scale;
if ($addDigits > 0) {
// add zeros
$value .= \str_repeat('0', $addDigits);
} elseif ($addDigits < 0) {
// trim digits
if (-$addDigits >= \strlen($this->value)) {
// requesting a scale too low, will always yield a zero result
return new BigDecimal('0', $scale);
}
$value = \substr($value, 0, $addDigits);
}
$value = Calculator::get()->sqrt($value);
return new BigDecimal($value, $scale);
}
/**
* Returns a copy of this BigDecimal with the decimal point moved $n places to the left.
*/
public function withPointMovedLeft(int $n) : BigDecimal
{
if ($n === 0) {
return $this;
}
if ($n < 0) {
return $this->withPointMovedRight(-$n);
}
return new BigDecimal($this->value, $this->scale + $n);
}
/**
* Returns a copy of this BigDecimal with the decimal point moved $n places to the right.
*/
public function withPointMovedRight(int $n) : BigDecimal
{
if ($n === 0) {
return $this;
}
if ($n < 0) {
return $this->withPointMovedLeft(-$n);
}
$value = $this->value;
$scale = $this->scale - $n;
if ($scale < 0) {
if ($value !== '0') {
$value .= \str_repeat('0', -$scale);
}
$scale = 0;
}
return new BigDecimal($value, $scale);
}
/**
* Returns a copy of this BigDecimal with any trailing zeros removed from the fractional part.
*/
public function stripTrailingZeros() : BigDecimal
{
if ($this->scale === 0) {
return $this;
}
$trimmedValue = \rtrim($this->value, '0');
if ($trimmedValue === '') {
return BigDecimal::zero();
}
$trimmableZeros = \strlen($this->value) - \strlen($trimmedValue);
if ($trimmableZeros === 0) {
return $this;
}
if ($trimmableZeros > $this->scale) {
$trimmableZeros = $this->scale;
}
$value = \substr($this->value, 0, -$trimmableZeros);
$scale = $this->scale - $trimmableZeros;
return new BigDecimal($value, $scale);
}
/**
* Returns the absolute value of this number.
*/
public function abs() : BigDecimal
{
return $this->isNegative() ? $this->negated() : $this;
}
/**
* Returns the negated value of this number.
*/
public function negated() : BigDecimal
{
return new BigDecimal(Calculator::get()->neg($this->value), $this->scale);
}
public function compareTo(BigNumber|int|float|string $that) : int
{
$that = BigNumber::of($that);
if ($that instanceof BigInteger) {
$that = $that->toBigDecimal();
}
if ($that instanceof BigDecimal) {
[$a, $b] = $this->scaleValues($this, $that);
return Calculator::get()->cmp($a, $b);
}
return - $that->compareTo($this);
}
public function getSign() : int
{
return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1);
}
public function getUnscaledValue() : BigInteger
{
return self::newBigInteger($this->value);
}
public function getScale() : int
{
return $this->scale;
}
/**
* Returns a string representing the integral part of this decimal number.
*
* Example: `-123.456` => `-123`.
*/
public function getIntegralPart() : string
{
if ($this->scale === 0) {
return $this->value;
}
$value = $this->getUnscaledValueWithLeadingZeros();
return \substr($value, 0, -$this->scale);
}
/**
* Returns a string representing the fractional part of this decimal number.
*
* If the scale is zero, an empty string is returned.
*
* Examples: `-123.456` => '456', `123` => ''.
*/
public function getFractionalPart() : string
{
if ($this->scale === 0) {
return '';
}
$value = $this->getUnscaledValueWithLeadingZeros();
return \substr($value, -$this->scale);
}
/**
* Returns whether this decimal number has a non-zero fractional part.
*/
public function hasNonZeroFractionalPart() : bool
{
return $this->getFractionalPart() !== \str_repeat('0', $this->scale);
}
public function toBigInteger() : BigInteger
{
$zeroScaleDecimal = $this->scale === 0 ? $this : $this->dividedBy(1, 0);
return self::newBigInteger($zeroScaleDecimal->value);
}
public function toBigDecimal() : BigDecimal
{
return $this;
}
public function toBigRational() : BigRational
{
$numerator = self::newBigInteger($this->value);
$denominator = self::newBigInteger('1' . \str_repeat('0', $this->scale));
return self::newBigRational($numerator, $denominator, false);
}
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
{
if ($scale === $this->scale) {
return $this;
}
return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode);
}
public function toInt() : int
{
return $this->toBigInteger()->toInt();
}
public function toFloat() : float
{
return (float) (string) $this;
}
public function __toString() : string
{
if ($this->scale === 0) {
return $this->value;
}
$value = $this->getUnscaledValueWithLeadingZeros();
return \substr($value, 0, -$this->scale) . '.' . \substr($value, -$this->scale);
}
/**
* This method is required for serializing the object and SHOULD NOT be accessed directly.
*
* @internal
*
* @return array{value: string, scale: int}
*/
public function __serialize(): array
{
return ['value' => $this->value, 'scale' => $this->scale];
}
/**
* This method is only here to allow unserializing the object and cannot be accessed directly.
*
* @internal
* @psalm-suppress RedundantPropertyInitializationCheck
*
* @param array{value: string, scale: int} $data
*
* @throws \LogicException
*/
public function __unserialize(array $data): void
{
if (isset($this->value)) {
throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
}
$this->value = $data['value'];
$this->scale = $data['scale'];
}
/**
* This method is required by interface Serializable and SHOULD NOT be accessed directly.
*
* @internal
*/
public function serialize() : string
{
return $this->value . ':' . $this->scale;
}
/**
* This method is only here to implement interface Serializable and cannot be accessed directly.
*
* @internal
* @psalm-suppress RedundantPropertyInitializationCheck
*
* @throws \LogicException
*/
public function unserialize($value) : void
{
if (isset($this->value)) {
throw new \LogicException('unserialize() is an internal function, it must not be called directly.');
}
[$value, $scale] = \explode(':', $value);
$this->value = $value;
$this->scale = (int) $scale;
}
/**
* Puts the internal values of the given decimal numbers on the same scale.
*
* @return array{string, string} The scaled integer values of $x and $y.
*/
private function scaleValues(BigDecimal $x, BigDecimal $y) : array
{
$a = $x->value;
$b = $y->value;
if ($b !== '0' && $x->scale > $y->scale) {
$b .= \str_repeat('0', $x->scale - $y->scale);
} elseif ($a !== '0' && $x->scale < $y->scale) {
$a .= \str_repeat('0', $y->scale - $x->scale);
}
return [$a, $b];
}
private function valueWithMinScale(int $scale) : string
{
$value = $this->value;
if ($this->value !== '0' && $scale > $this->scale) {
$value .= \str_repeat('0', $scale - $this->scale);
}
return $value;
}
/**
* Adds leading zeros if necessary to the unscaled value to represent the full decimal number.
*/
private function getUnscaledValueWithLeadingZeros() : string
{
$value = $this->value;
$targetLength = $this->scale + 1;
$negative = ($value[0] === '-');
$length = \strlen($value);
if ($negative) {
$length--;
}
if ($length >= $targetLength) {
return $this->value;
}
if ($negative) {
$value = \substr($value, 1);
}
$value = \str_pad($value, $targetLength, '0', STR_PAD_LEFT);
if ($negative) {
$value = '-' . $value;
}
return $value;
}
}

1079
vendor/brick/math/src/BigInteger.php vendored Normal file

File diff suppressed because it is too large Load diff

512
vendor/brick/math/src/BigNumber.php vendored Normal file
View file

@ -0,0 +1,512 @@
<?php
declare(strict_types=1);
namespace Brick\Math;
use Brick\Math\Exception\DivisionByZeroException;
use Brick\Math\Exception\MathException;
use Brick\Math\Exception\NumberFormatException;
use Brick\Math\Exception\RoundingNecessaryException;
/**
* Common interface for arbitrary-precision rational numbers.
*
* @psalm-immutable
*/
abstract class BigNumber implements \Serializable, \JsonSerializable
{
/**
* The regular expression used to parse integer, decimal and rational numbers.
*/
private const PARSE_REGEXP =
'/^' .
'(?<sign>[\-\+])?' .
'(?:' .
'(?:' .
'(?<integral>[0-9]+)?' .
'(?<point>\.)?' .
'(?<fractional>[0-9]+)?' .
'(?:[eE](?<exponent>[\-\+]?[0-9]+))?' .
')|(?:' .
'(?<numerator>[0-9]+)' .
'\/?' .
'(?<denominator>[0-9]+)' .
')' .
')' .
'$/';
/**
* Creates a BigNumber of the given value.
*
* The concrete return type is dependent on the given value, with the following rules:
*
* - BigNumber instances are returned as is
* - integer numbers are returned as BigInteger
* - floating point numbers are converted to a string then parsed as such
* - strings containing a `/` character are returned as BigRational
* - strings containing a `.` character or using an exponential notation are returned as BigDecimal
* - strings containing only digits with an optional leading `+` or `-` sign are returned as BigInteger
*
* @throws NumberFormatException If the format of the number is not valid.
* @throws DivisionByZeroException If the value represents a rational number with a denominator of zero.
*
* @psalm-pure
*/
public static function of(BigNumber|int|float|string $value) : BigNumber
{
if ($value instanceof BigNumber) {
return $value;
}
if (\is_int($value)) {
return new BigInteger((string) $value);
}
$value = \is_float($value) ? self::floatToString($value) : $value;
$throw = static function() use ($value) : void {
throw new NumberFormatException(\sprintf(
'The given value "%s" does not represent a valid number.',
$value
));
};
if (\preg_match(self::PARSE_REGEXP, $value, $matches) !== 1) {
$throw();
}
$getMatch = static fn(string $value): ?string => (($matches[$value] ?? '') !== '') ? $matches[$value] : null;
$sign = $getMatch('sign');
$numerator = $getMatch('numerator');
$denominator = $getMatch('denominator');
if ($numerator !== null) {
assert($denominator !== null);
if ($sign !== null) {
$numerator = $sign . $numerator;
}
$numerator = self::cleanUp($numerator);
$denominator = self::cleanUp($denominator);
if ($denominator === '0') {
throw DivisionByZeroException::denominatorMustNotBeZero();
}
return new BigRational(
new BigInteger($numerator),
new BigInteger($denominator),
false
);
}
$point = $getMatch('point');
$integral = $getMatch('integral');
$fractional = $getMatch('fractional');
$exponent = $getMatch('exponent');
if ($integral === null && $fractional === null) {
$throw();
}
if ($integral === null) {
$integral = '0';
}
if ($point !== null || $exponent !== null) {
$fractional = ($fractional ?? '');
$exponent = ($exponent !== null) ? (int) $exponent : 0;
if ($exponent === PHP_INT_MIN || $exponent === PHP_INT_MAX) {
throw new NumberFormatException('Exponent too large.');
}
$unscaledValue = self::cleanUp(($sign ?? ''). $integral . $fractional);
$scale = \strlen($fractional) - $exponent;
if ($scale < 0) {
if ($unscaledValue !== '0') {
$unscaledValue .= \str_repeat('0', - $scale);
}
$scale = 0;
}
return new BigDecimal($unscaledValue, $scale);
}
$integral = self::cleanUp(($sign ?? '') . $integral);
return new BigInteger($integral);
}
/**
* Safely converts float to string, avoiding locale-dependent issues.
*
* @see https://github.com/brick/math/pull/20
*
* @psalm-pure
* @psalm-suppress ImpureFunctionCall
*/
private static function floatToString(float $float) : string
{
$currentLocale = \setlocale(LC_NUMERIC, '0');
\setlocale(LC_NUMERIC, 'C');
$result = (string) $float;
\setlocale(LC_NUMERIC, $currentLocale);
return $result;
}
/**
* Proxy method to access BigInteger's protected constructor from sibling classes.
*
* @internal
* @psalm-pure
*/
protected function newBigInteger(string $value) : BigInteger
{
return new BigInteger($value);
}
/**
* Proxy method to access BigDecimal's protected constructor from sibling classes.
*
* @internal
* @psalm-pure
*/
protected function newBigDecimal(string $value, int $scale = 0) : BigDecimal
{
return new BigDecimal($value, $scale);
}
/**
* Proxy method to access BigRational's protected constructor from sibling classes.
*
* @internal
* @psalm-pure
*/
protected function newBigRational(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator) : BigRational
{
return new BigRational($numerator, $denominator, $checkDenominator);
}
/**
* Returns the minimum of the given values.
*
* @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible
* to an instance of the class this method is called on.
*
* @throws \InvalidArgumentException If no values are given.
* @throws MathException If an argument is not valid.
*
* @psalm-suppress LessSpecificReturnStatement
* @psalm-suppress MoreSpecificReturnType
* @psalm-pure
*/
public static function min(BigNumber|int|float|string ...$values) : static
{
$min = null;
foreach ($values as $value) {
$value = static::of($value);
if ($min === null || $value->isLessThan($min)) {
$min = $value;
}
}
if ($min === null) {
throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
}
return $min;
}
/**
* Returns the maximum of the given values.
*
* @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible
* to an instance of the class this method is called on.
*
* @throws \InvalidArgumentException If no values are given.
* @throws MathException If an argument is not valid.
*
* @psalm-suppress LessSpecificReturnStatement
* @psalm-suppress MoreSpecificReturnType
* @psalm-pure
*/
public static function max(BigNumber|int|float|string ...$values) : static
{
$max = null;
foreach ($values as $value) {
$value = static::of($value);
if ($max === null || $value->isGreaterThan($max)) {
$max = $value;
}
}
if ($max === null) {
throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
}
return $max;
}
/**
* Returns the sum of the given values.
*
* @param BigNumber|int|float|string ...$values The numbers to add. All the numbers need to be convertible
* to an instance of the class this method is called on.
*
* @throws \InvalidArgumentException If no values are given.
* @throws MathException If an argument is not valid.
*
* @psalm-pure
*/
public static function sum(BigNumber|int|float|string ...$values) : static
{
/** @var static|null $sum */
$sum = null;
foreach ($values as $value) {
$value = static::of($value);
$sum = $sum === null ? $value : self::add($sum, $value);
}
if ($sum === null) {
throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
}
return $sum;
}
/**
* Adds two BigNumber instances in the correct order to avoid a RoundingNecessaryException.
*
* @todo This could be better resolved by creating an abstract protected method in BigNumber, and leaving to
* concrete classes the responsibility to perform the addition themselves or delegate it to the given number,
* depending on their ability to perform the operation. This will also require a version bump because we're
* potentially breaking custom BigNumber implementations (if any...)
*
* @psalm-pure
*/
private static function add(BigNumber $a, BigNumber $b) : BigNumber
{
if ($a instanceof BigRational) {
return $a->plus($b);
}
if ($b instanceof BigRational) {
return $b->plus($a);
}
if ($a instanceof BigDecimal) {
return $a->plus($b);
}
if ($b instanceof BigDecimal) {
return $b->plus($a);
}
/** @var BigInteger $a */
return $a->plus($b);
}
/**
* Removes optional leading zeros and + sign from the given number.
*
* @param string $number The number, validated as a non-empty string of digits with optional leading sign.
*
* @psalm-pure
*/
private static function cleanUp(string $number) : string
{
$firstChar = $number[0];
if ($firstChar === '+' || $firstChar === '-') {
$number = \substr($number, 1);
}
$number = \ltrim($number, '0');
if ($number === '') {
return '0';
}
if ($firstChar === '-') {
return '-' . $number;
}
return $number;
}
/**
* Checks if this number is equal to the given one.
*/
public function isEqualTo(BigNumber|int|float|string $that) : bool
{
return $this->compareTo($that) === 0;
}
/**
* Checks if this number is strictly lower than the given one.
*/
public function isLessThan(BigNumber|int|float|string $that) : bool
{
return $this->compareTo($that) < 0;
}
/**
* Checks if this number is lower than or equal to the given one.
*/
public function isLessThanOrEqualTo(BigNumber|int|float|string $that) : bool
{
return $this->compareTo($that) <= 0;
}
/**
* Checks if this number is strictly greater than the given one.
*/
public function isGreaterThan(BigNumber|int|float|string $that) : bool
{
return $this->compareTo($that) > 0;
}
/**
* Checks if this number is greater than or equal to the given one.
*/
public function isGreaterThanOrEqualTo(BigNumber|int|float|string $that) : bool
{
return $this->compareTo($that) >= 0;
}
/**
* Checks if this number equals zero.
*/
public function isZero() : bool
{
return $this->getSign() === 0;
}
/**
* Checks if this number is strictly negative.
*/
public function isNegative() : bool
{
return $this->getSign() < 0;
}
/**
* Checks if this number is negative or zero.
*/
public function isNegativeOrZero() : bool
{
return $this->getSign() <= 0;
}
/**
* Checks if this number is strictly positive.
*/
public function isPositive() : bool
{
return $this->getSign() > 0;
}
/**
* Checks if this number is positive or zero.
*/
public function isPositiveOrZero() : bool
{
return $this->getSign() >= 0;
}
/**
* Returns the sign of this number.
*
* @return int -1 if the number is negative, 0 if zero, 1 if positive.
*/
abstract public function getSign() : int;
/**
* Compares this number to the given one.
*
* @return int [-1,0,1] If `$this` is lower than, equal to, or greater than `$that`.
*
* @throws MathException If the number is not valid.
*/
abstract public function compareTo(BigNumber|int|float|string $that) : int;
/**
* Converts this number to a BigInteger.
*
* @throws RoundingNecessaryException If this number cannot be converted to a BigInteger without rounding.
*/
abstract public function toBigInteger() : BigInteger;
/**
* Converts this number to a BigDecimal.
*
* @throws RoundingNecessaryException If this number cannot be converted to a BigDecimal without rounding.
*/
abstract public function toBigDecimal() : BigDecimal;
/**
* Converts this number to a BigRational.
*/
abstract public function toBigRational() : BigRational;
/**
* Converts this number to a BigDecimal with the given scale, using rounding if necessary.
*
* @param int $scale The scale of the resulting `BigDecimal`.
* @param int $roundingMode A `RoundingMode` constant.
*
* @throws RoundingNecessaryException If this number cannot be converted to the given scale without rounding.
* This only applies when RoundingMode::UNNECESSARY is used.
*/
abstract public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal;
/**
* Returns the exact value of this number as a native integer.
*
* If this number cannot be converted to a native integer without losing precision, an exception is thrown.
* Note that the acceptable range for an integer depends on the platform and differs for 32-bit and 64-bit.
*
* @throws MathException If this number cannot be exactly converted to a native integer.
*/
abstract public function toInt() : int;
/**
* Returns an approximation of this number as a floating-point value.
*
* Note that this method can discard information as the precision of a floating-point value
* is inherently limited.
*
* If the number is greater than the largest representable floating point number, positive infinity is returned.
* If the number is less than the smallest representable floating point number, negative infinity is returned.
*/
abstract public function toFloat() : float;
/**
* Returns a string representation of this number.
*
* The output of this method can be parsed by the `of()` factory method;
* this will yield an object equal to this one, without any information loss.
*/
abstract public function __toString() : string;
public function jsonSerialize() : string
{
return $this->__toString();
}
}

445
vendor/brick/math/src/BigRational.php vendored Normal file
View file

@ -0,0 +1,445 @@
<?php
declare(strict_types=1);
namespace Brick\Math;
use Brick\Math\Exception\DivisionByZeroException;
use Brick\Math\Exception\MathException;
use Brick\Math\Exception\NumberFormatException;
use Brick\Math\Exception\RoundingNecessaryException;
/**
* An arbitrarily large rational number.
*
* This class is immutable.
*
* @psalm-immutable
*/
final class BigRational extends BigNumber
{
/**
* The numerator.
*/
private BigInteger $numerator;
/**
* The denominator. Always strictly positive.
*/
private BigInteger $denominator;
/**
* Protected constructor. Use a factory method to obtain an instance.
*
* @param BigInteger $numerator The numerator.
* @param BigInteger $denominator The denominator.
* @param bool $checkDenominator Whether to check the denominator for negative and zero.
*
* @throws DivisionByZeroException If the denominator is zero.
*/
protected function __construct(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator)
{
if ($checkDenominator) {
if ($denominator->isZero()) {
throw DivisionByZeroException::denominatorMustNotBeZero();
}
if ($denominator->isNegative()) {
$numerator = $numerator->negated();
$denominator = $denominator->negated();
}
}
$this->numerator = $numerator;
$this->denominator = $denominator;
}
/**
* Creates a BigRational of the given value.
*
* @throws MathException If the value cannot be converted to a BigRational.
*
* @psalm-pure
*/
public static function of(BigNumber|int|float|string $value) : BigRational
{
return parent::of($value)->toBigRational();
}
/**
* Creates a BigRational out of a numerator and a denominator.
*
* If the denominator is negative, the signs of both the numerator and the denominator
* will be inverted to ensure that the denominator is always positive.
*
* @param BigNumber|int|float|string $numerator The numerator. Must be convertible to a BigInteger.
* @param BigNumber|int|float|string $denominator The denominator. Must be convertible to a BigInteger.
*
* @throws NumberFormatException If an argument does not represent a valid number.
* @throws RoundingNecessaryException If an argument represents a non-integer number.
* @throws DivisionByZeroException If the denominator is zero.
*
* @psalm-pure
*/
public static function nd(
BigNumber|int|float|string $numerator,
BigNumber|int|float|string $denominator,
) : BigRational {
$numerator = BigInteger::of($numerator);
$denominator = BigInteger::of($denominator);
return new BigRational($numerator, $denominator, true);
}
/**
* Returns a BigRational representing zero.
*
* @psalm-pure
*/
public static function zero() : BigRational
{
/**
* @psalm-suppress ImpureStaticVariable
* @var BigRational|null $zero
*/
static $zero;
if ($zero === null) {
$zero = new BigRational(BigInteger::zero(), BigInteger::one(), false);
}
return $zero;
}
/**
* Returns a BigRational representing one.
*
* @psalm-pure
*/
public static function one() : BigRational
{
/**
* @psalm-suppress ImpureStaticVariable
* @var BigRational|null $one
*/
static $one;
if ($one === null) {
$one = new BigRational(BigInteger::one(), BigInteger::one(), false);
}
return $one;
}
/**
* Returns a BigRational representing ten.
*
* @psalm-pure
*/
public static function ten() : BigRational
{
/**
* @psalm-suppress ImpureStaticVariable
* @var BigRational|null $ten
*/
static $ten;
if ($ten === null) {
$ten = new BigRational(BigInteger::ten(), BigInteger::one(), false);
}
return $ten;
}
public function getNumerator() : BigInteger
{
return $this->numerator;
}
public function getDenominator() : BigInteger
{
return $this->denominator;
}
/**
* Returns the quotient of the division of the numerator by the denominator.
*/
public function quotient() : BigInteger
{
return $this->numerator->quotient($this->denominator);
}
/**
* Returns the remainder of the division of the numerator by the denominator.
*/
public function remainder() : BigInteger
{
return $this->numerator->remainder($this->denominator);
}
/**
* Returns the quotient and remainder of the division of the numerator by the denominator.
*
* @return BigInteger[]
*/
public function quotientAndRemainder() : array
{
return $this->numerator->quotientAndRemainder($this->denominator);
}
/**
* Returns the sum of this number and the given one.
*
* @param BigNumber|int|float|string $that The number to add.
*
* @throws MathException If the number is not valid.
*/
public function plus(BigNumber|int|float|string $that) : BigRational
{
$that = BigRational::of($that);
$numerator = $this->numerator->multipliedBy($that->denominator);
$numerator = $numerator->plus($that->numerator->multipliedBy($this->denominator));
$denominator = $this->denominator->multipliedBy($that->denominator);
return new BigRational($numerator, $denominator, false);
}
/**
* Returns the difference of this number and the given one.
*
* @param BigNumber|int|float|string $that The number to subtract.
*
* @throws MathException If the number is not valid.
*/
public function minus(BigNumber|int|float|string $that) : BigRational
{
$that = BigRational::of($that);
$numerator = $this->numerator->multipliedBy($that->denominator);
$numerator = $numerator->minus($that->numerator->multipliedBy($this->denominator));
$denominator = $this->denominator->multipliedBy($that->denominator);
return new BigRational($numerator, $denominator, false);
}
/**
* Returns the product of this number and the given one.
*
* @param BigNumber|int|float|string $that The multiplier.
*
* @throws MathException If the multiplier is not a valid number.
*/
public function multipliedBy(BigNumber|int|float|string $that) : BigRational
{
$that = BigRational::of($that);
$numerator = $this->numerator->multipliedBy($that->numerator);
$denominator = $this->denominator->multipliedBy($that->denominator);
return new BigRational($numerator, $denominator, false);
}
/**
* Returns the result of the division of this number by the given one.
*
* @param BigNumber|int|float|string $that The divisor.
*
* @throws MathException If the divisor is not a valid number, or is zero.
*/
public function dividedBy(BigNumber|int|float|string $that) : BigRational
{
$that = BigRational::of($that);
$numerator = $this->numerator->multipliedBy($that->denominator);
$denominator = $this->denominator->multipliedBy($that->numerator);
return new BigRational($numerator, $denominator, true);
}
/**
* Returns this number exponentiated to the given value.
*
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
*/
public function power(int $exponent) : BigRational
{
if ($exponent === 0) {
$one = BigInteger::one();
return new BigRational($one, $one, false);
}
if ($exponent === 1) {
return $this;
}
return new BigRational(
$this->numerator->power($exponent),
$this->denominator->power($exponent),
false
);
}
/**
* Returns the reciprocal of this BigRational.
*
* The reciprocal has the numerator and denominator swapped.
*
* @throws DivisionByZeroException If the numerator is zero.
*/
public function reciprocal() : BigRational
{
return new BigRational($this->denominator, $this->numerator, true);
}
/**
* Returns the absolute value of this BigRational.
*/
public function abs() : BigRational
{
return new BigRational($this->numerator->abs(), $this->denominator, false);
}
/**
* Returns the negated value of this BigRational.
*/
public function negated() : BigRational
{
return new BigRational($this->numerator->negated(), $this->denominator, false);
}
/**
* Returns the simplified value of this BigRational.
*/
public function simplified() : BigRational
{
$gcd = $this->numerator->gcd($this->denominator);
$numerator = $this->numerator->quotient($gcd);
$denominator = $this->denominator->quotient($gcd);
return new BigRational($numerator, $denominator, false);
}
public function compareTo(BigNumber|int|float|string $that) : int
{
return $this->minus($that)->getSign();
}
public function getSign() : int
{
return $this->numerator->getSign();
}
public function toBigInteger() : BigInteger
{
$simplified = $this->simplified();
if (! $simplified->denominator->isEqualTo(1)) {
throw new RoundingNecessaryException('This rational number cannot be represented as an integer value without rounding.');
}
return $simplified->numerator;
}
public function toBigDecimal() : BigDecimal
{
return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator);
}
public function toBigRational() : BigRational
{
return $this;
}
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
{
return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
}
public function toInt() : int
{
return $this->toBigInteger()->toInt();
}
public function toFloat() : float
{
$simplified = $this->simplified();
return $simplified->numerator->toFloat() / $simplified->denominator->toFloat();
}
public function __toString() : string
{
$numerator = (string) $this->numerator;
$denominator = (string) $this->denominator;
if ($denominator === '1') {
return $numerator;
}
return $this->numerator . '/' . $this->denominator;
}
/**
* This method is required for serializing the object and SHOULD NOT be accessed directly.
*
* @internal
*
* @return array{numerator: BigInteger, denominator: BigInteger}
*/
public function __serialize(): array
{
return ['numerator' => $this->numerator, 'denominator' => $this->denominator];
}
/**
* This method is only here to allow unserializing the object and cannot be accessed directly.
*
* @internal
* @psalm-suppress RedundantPropertyInitializationCheck
*
* @param array{numerator: BigInteger, denominator: BigInteger} $data
*
* @throws \LogicException
*/
public function __unserialize(array $data): void
{
if (isset($this->numerator)) {
throw new \LogicException('__unserialize() is an internal function, it must not be called directly.');
}
$this->numerator = $data['numerator'];
$this->denominator = $data['denominator'];
}
/**
* This method is required by interface Serializable and SHOULD NOT be accessed directly.
*
* @internal
*/
public function serialize() : string
{
return $this->numerator . '/' . $this->denominator;
}
/**
* This method is only here to implement interface Serializable and cannot be accessed directly.
*
* @internal
* @psalm-suppress RedundantPropertyInitializationCheck
*
* @throws \LogicException
*/
public function unserialize($value) : void
{
if (isset($this->numerator)) {
throw new \LogicException('unserialize() is an internal function, it must not be called directly.');
}
[$numerator, $denominator] = \explode('/', $value);
$this->numerator = BigInteger::of($numerator);
$this->denominator = BigInteger::of($denominator);
}
}

View file

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Exception;
/**
* Exception thrown when a division by zero occurs.
*/
class DivisionByZeroException extends MathException
{
/**
* @psalm-pure
*/
public static function divisionByZero() : DivisionByZeroException
{
return new self('Division by zero.');
}
/**
* @psalm-pure
*/
public static function modulusMustNotBeZero() : DivisionByZeroException
{
return new self('The modulus must not be zero.');
}
/**
* @psalm-pure
*/
public static function denominatorMustNotBeZero() : DivisionByZeroException
{
return new self('The denominator of a rational number cannot be zero.');
}
}

View file

@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Exception;
use Brick\Math\BigInteger;
/**
* Exception thrown when an integer overflow occurs.
*/
class IntegerOverflowException extends MathException
{
/**
* @psalm-pure
*/
public static function toIntOverflow(BigInteger $value) : IntegerOverflowException
{
$message = '%s is out of range %d to %d and cannot be represented as an integer.';
return new self(\sprintf($message, (string) $value, PHP_INT_MIN, PHP_INT_MAX));
}
}

View file

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Exception;
/**
* Base class for all math exceptions.
*/
class MathException extends \Exception
{
}

View file

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Exception;
/**
* Exception thrown when attempting to perform an unsupported operation, such as a square root, on a negative number.
*/
class NegativeNumberException extends MathException
{
}

View file

@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Exception;
/**
* Exception thrown when attempting to create a number from a string with an invalid format.
*/
class NumberFormatException extends MathException
{
/**
* @param string $char The failing character.
*
* @psalm-pure
*/
public static function charNotInAlphabet(string $char) : self
{
$ord = \ord($char);
if ($ord < 32 || $ord > 126) {
$char = \strtoupper(\dechex($ord));
if ($ord < 10) {
$char = '0' . $char;
}
} else {
$char = '"' . $char . '"';
}
return new self(sprintf('Char %s is not a valid character in the given alphabet.', $char));
}
}

View file

@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Exception;
/**
* Exception thrown when a number cannot be represented at the requested scale without rounding.
*/
class RoundingNecessaryException extends MathException
{
/**
* @psalm-pure
*/
public static function roundingNecessary() : RoundingNecessaryException
{
return new self('Rounding is necessary to represent the result of the operation at this scale.');
}
}

View file

@ -0,0 +1,676 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Internal;
use Brick\Math\Exception\RoundingNecessaryException;
use Brick\Math\RoundingMode;
/**
* Performs basic operations on arbitrary size integers.
*
* Unless otherwise specified, all parameters must be validated as non-empty strings of digits,
* without leading zero, and with an optional leading minus sign if the number is not zero.
*
* Any other parameter format will lead to undefined behaviour.
* All methods must return strings respecting this format, unless specified otherwise.
*
* @internal
*
* @psalm-immutable
*/
abstract class Calculator
{
/**
* The maximum exponent value allowed for the pow() method.
*/
public const MAX_POWER = 1000000;
/**
* The alphabet for converting from and to base 2 to 36, lowercase.
*/
public const ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz';
/**
* The Calculator instance in use.
*/
private static ?Calculator $instance = null;
/**
* Sets the Calculator instance to use.
*
* An instance is typically set only in unit tests: the autodetect is usually the best option.
*
* @param Calculator|null $calculator The calculator instance, or NULL to revert to autodetect.
*/
final public static function set(?Calculator $calculator) : void
{
self::$instance = $calculator;
}
/**
* Returns the Calculator instance to use.
*
* If none has been explicitly set, the fastest available implementation will be returned.
*
* @psalm-pure
* @psalm-suppress ImpureStaticProperty
*/
final public static function get() : Calculator
{
if (self::$instance === null) {
/** @psalm-suppress ImpureMethodCall */
self::$instance = self::detect();
}
return self::$instance;
}
/**
* Returns the fastest available Calculator implementation.
*
* @codeCoverageIgnore
*/
private static function detect() : Calculator
{
if (\extension_loaded('gmp')) {
return new Calculator\GmpCalculator();
}
if (\extension_loaded('bcmath')) {
return new Calculator\BcMathCalculator();
}
return new Calculator\NativeCalculator();
}
/**
* Extracts the sign & digits of the operands.
*
* @return array{bool, bool, string, string} Whether $a and $b are negative, followed by their digits.
*/
final protected function init(string $a, string $b) : array
{
return [
$aNeg = ($a[0] === '-'),
$bNeg = ($b[0] === '-'),
$aNeg ? \substr($a, 1) : $a,
$bNeg ? \substr($b, 1) : $b,
];
}
/**
* Returns the absolute value of a number.
*/
final public function abs(string $n) : string
{
return ($n[0] === '-') ? \substr($n, 1) : $n;
}
/**
* Negates a number.
*/
final public function neg(string $n) : string
{
if ($n === '0') {
return '0';
}
if ($n[0] === '-') {
return \substr($n, 1);
}
return '-' . $n;
}
/**
* Compares two numbers.
*
* @return int [-1, 0, 1] If the first number is less than, equal to, or greater than the second number.
*/
final public function cmp(string $a, string $b) : int
{
[$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
if ($aNeg && ! $bNeg) {
return -1;
}
if ($bNeg && ! $aNeg) {
return 1;
}
$aLen = \strlen($aDig);
$bLen = \strlen($bDig);
if ($aLen < $bLen) {
$result = -1;
} elseif ($aLen > $bLen) {
$result = 1;
} else {
$result = $aDig <=> $bDig;
}
return $aNeg ? -$result : $result;
}
/**
* Adds two numbers.
*/
abstract public function add(string $a, string $b) : string;
/**
* Subtracts two numbers.
*/
abstract public function sub(string $a, string $b) : string;
/**
* Multiplies two numbers.
*/
abstract public function mul(string $a, string $b) : string;
/**
* Returns the quotient of the division of two numbers.
*
* @param string $a The dividend.
* @param string $b The divisor, must not be zero.
*
* @return string The quotient.
*/
abstract public function divQ(string $a, string $b) : string;
/**
* Returns the remainder of the division of two numbers.
*
* @param string $a The dividend.
* @param string $b The divisor, must not be zero.
*
* @return string The remainder.
*/
abstract public function divR(string $a, string $b) : string;
/**
* Returns the quotient and remainder of the division of two numbers.
*
* @param string $a The dividend.
* @param string $b The divisor, must not be zero.
*
* @return array{string, string} An array containing the quotient and remainder.
*/
abstract public function divQR(string $a, string $b) : array;
/**
* Exponentiates a number.
*
* @param string $a The base number.
* @param int $e The exponent, validated as an integer between 0 and MAX_POWER.
*
* @return string The power.
*/
abstract public function pow(string $a, int $e) : string;
/**
* @param string $b The modulus; must not be zero.
*/
public function mod(string $a, string $b) : string
{
return $this->divR($this->add($this->divR($a, $b), $b), $b);
}
/**
* Returns the modular multiplicative inverse of $x modulo $m.
*
* If $x has no multiplicative inverse mod m, this method must return null.
*
* This method can be overridden by the concrete implementation if the underlying library has built-in support.
*
* @param string $m The modulus; must not be negative or zero.
*/
public function modInverse(string $x, string $m) : ?string
{
if ($m === '1') {
return '0';
}
$modVal = $x;
if ($x[0] === '-' || ($this->cmp($this->abs($x), $m) >= 0)) {
$modVal = $this->mod($x, $m);
}
[$g, $x] = $this->gcdExtended($modVal, $m);
if ($g !== '1') {
return null;
}
return $this->mod($this->add($this->mod($x, $m), $m), $m);
}
/**
* Raises a number into power with modulo.
*
* @param string $base The base number; must be positive or zero.
* @param string $exp The exponent; must be positive or zero.
* @param string $mod The modulus; must be strictly positive.
*/
abstract public function modPow(string $base, string $exp, string $mod) : string;
/**
* Returns the greatest common divisor of the two numbers.
*
* This method can be overridden by the concrete implementation if the underlying library
* has built-in support for GCD calculations.
*
* @return string The GCD, always positive, or zero if both arguments are zero.
*/
public function gcd(string $a, string $b) : string
{
if ($a === '0') {
return $this->abs($b);
}
if ($b === '0') {
return $this->abs($a);
}
return $this->gcd($b, $this->divR($a, $b));
}
/**
* @return array{string, string, string} GCD, X, Y
*/
private function gcdExtended(string $a, string $b) : array
{
if ($a === '0') {
return [$b, '0', '1'];
}
[$gcd, $x1, $y1] = $this->gcdExtended($this->mod($b, $a), $a);
$x = $this->sub($y1, $this->mul($this->divQ($b, $a), $x1));
$y = $x1;
return [$gcd, $x, $y];
}
/**
* Returns the square root of the given number, rounded down.
*
* The result is the largest x such that n.
* The input MUST NOT be negative.
*/
abstract public function sqrt(string $n) : string;
/**
* Converts a number from an arbitrary base.
*
* This method can be overridden by the concrete implementation if the underlying library
* has built-in support for base conversion.
*
* @param string $number The number, positive or zero, non-empty, case-insensitively validated for the given base.
* @param int $base The base of the number, validated from 2 to 36.
*
* @return string The converted number, following the Calculator conventions.
*/
public function fromBase(string $number, int $base) : string
{
return $this->fromArbitraryBase(\strtolower($number), self::ALPHABET, $base);
}
/**
* Converts a number to an arbitrary base.
*
* This method can be overridden by the concrete implementation if the underlying library
* has built-in support for base conversion.
*
* @param string $number The number to convert, following the Calculator conventions.
* @param int $base The base to convert to, validated from 2 to 36.
*
* @return string The converted number, lowercase.
*/
public function toBase(string $number, int $base) : string
{
$negative = ($number[0] === '-');
if ($negative) {
$number = \substr($number, 1);
}
$number = $this->toArbitraryBase($number, self::ALPHABET, $base);
if ($negative) {
return '-' . $number;
}
return $number;
}
/**
* Converts a non-negative number in an arbitrary base using a custom alphabet, to base 10.
*
* @param string $number The number to convert, validated as a non-empty string,
* containing only chars in the given alphabet/base.
* @param string $alphabet The alphabet that contains every digit, validated as 2 chars minimum.
* @param int $base The base of the number, validated from 2 to alphabet length.
*
* @return string The number in base 10, following the Calculator conventions.
*/
final public function fromArbitraryBase(string $number, string $alphabet, int $base) : string
{
// remove leading "zeros"
$number = \ltrim($number, $alphabet[0]);
if ($number === '') {
return '0';
}
// optimize for "one"
if ($number === $alphabet[1]) {
return '1';
}
$result = '0';
$power = '1';
$base = (string) $base;
for ($i = \strlen($number) - 1; $i >= 0; $i--) {
$index = \strpos($alphabet, $number[$i]);
if ($index !== 0) {
$result = $this->add($result, ($index === 1)
? $power
: $this->mul($power, (string) $index)
);
}
if ($i !== 0) {
$power = $this->mul($power, $base);
}
}
return $result;
}
/**
* Converts a non-negative number to an arbitrary base using a custom alphabet.
*
* @param string $number The number to convert, positive or zero, following the Calculator conventions.
* @param string $alphabet The alphabet that contains every digit, validated as 2 chars minimum.
* @param int $base The base to convert to, validated from 2 to alphabet length.
*
* @return string The converted number in the given alphabet.
*/
final public function toArbitraryBase(string $number, string $alphabet, int $base) : string
{
if ($number === '0') {
return $alphabet[0];
}
$base = (string) $base;
$result = '';
while ($number !== '0') {
[$number, $remainder] = $this->divQR($number, $base);
$remainder = (int) $remainder;
$result .= $alphabet[$remainder];
}
return \strrev($result);
}
/**
* Performs a rounded division.
*
* Rounding is performed when the remainder of the division is not zero.
*
* @param string $a The dividend.
* @param string $b The divisor, must not be zero.
* @param int $roundingMode The rounding mode.
*
* @throws \InvalidArgumentException If the rounding mode is invalid.
* @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary.
*
* @psalm-suppress ImpureFunctionCall
*/
final public function divRound(string $a, string $b, int $roundingMode) : string
{
[$quotient, $remainder] = $this->divQR($a, $b);
$hasDiscardedFraction = ($remainder !== '0');
$isPositiveOrZero = ($a[0] === '-') === ($b[0] === '-');
$discardedFractionSign = function() use ($remainder, $b) : int {
$r = $this->abs($this->mul($remainder, '2'));
$b = $this->abs($b);
return $this->cmp($r, $b);
};
$increment = false;
switch ($roundingMode) {
case RoundingMode::UNNECESSARY:
if ($hasDiscardedFraction) {
throw RoundingNecessaryException::roundingNecessary();
}
break;
case RoundingMode::UP:
$increment = $hasDiscardedFraction;
break;
case RoundingMode::DOWN:
break;
case RoundingMode::CEILING:
$increment = $hasDiscardedFraction && $isPositiveOrZero;
break;
case RoundingMode::FLOOR:
$increment = $hasDiscardedFraction && ! $isPositiveOrZero;
break;
case RoundingMode::HALF_UP:
$increment = $discardedFractionSign() >= 0;
break;
case RoundingMode::HALF_DOWN:
$increment = $discardedFractionSign() > 0;
break;
case RoundingMode::HALF_CEILING:
$increment = $isPositiveOrZero ? $discardedFractionSign() >= 0 : $discardedFractionSign() > 0;
break;
case RoundingMode::HALF_FLOOR:
$increment = $isPositiveOrZero ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
break;
case RoundingMode::HALF_EVEN:
$lastDigit = (int) $quotient[-1];
$lastDigitIsEven = ($lastDigit % 2 === 0);
$increment = $lastDigitIsEven ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
break;
default:
throw new \InvalidArgumentException('Invalid rounding mode.');
}
if ($increment) {
return $this->add($quotient, $isPositiveOrZero ? '1' : '-1');
}
return $quotient;
}
/**
* Calculates bitwise AND of two numbers.
*
* This method can be overridden by the concrete implementation if the underlying library
* has built-in support for bitwise operations.
*/
public function and(string $a, string $b) : string
{
return $this->bitwise('and', $a, $b);
}
/**
* Calculates bitwise OR of two numbers.
*
* This method can be overridden by the concrete implementation if the underlying library
* has built-in support for bitwise operations.
*/
public function or(string $a, string $b) : string
{
return $this->bitwise('or', $a, $b);
}
/**
* Calculates bitwise XOR of two numbers.
*
* This method can be overridden by the concrete implementation if the underlying library
* has built-in support for bitwise operations.
*/
public function xor(string $a, string $b) : string
{
return $this->bitwise('xor', $a, $b);
}
/**
* Performs a bitwise operation on a decimal number.
*
* @param 'and'|'or'|'xor' $operator The operator to use.
* @param string $a The left operand.
* @param string $b The right operand.
*/
private function bitwise(string $operator, string $a, string $b) : string
{
[$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
$aBin = $this->toBinary($aDig);
$bBin = $this->toBinary($bDig);
$aLen = \strlen($aBin);
$bLen = \strlen($bBin);
if ($aLen > $bLen) {
$bBin = \str_repeat("\x00", $aLen - $bLen) . $bBin;
} elseif ($bLen > $aLen) {
$aBin = \str_repeat("\x00", $bLen - $aLen) . $aBin;
}
if ($aNeg) {
$aBin = $this->twosComplement($aBin);
}
if ($bNeg) {
$bBin = $this->twosComplement($bBin);
}
switch ($operator) {
case 'and':
$value = $aBin & $bBin;
$negative = ($aNeg and $bNeg);
break;
case 'or':
$value = $aBin | $bBin;
$negative = ($aNeg or $bNeg);
break;
case 'xor':
$value = $aBin ^ $bBin;
$negative = ($aNeg xor $bNeg);
break;
// @codeCoverageIgnoreStart
default:
throw new \InvalidArgumentException('Invalid bitwise operator.');
// @codeCoverageIgnoreEnd
}
if ($negative) {
$value = $this->twosComplement($value);
}
$result = $this->toDecimal($value);
return $negative ? $this->neg($result) : $result;
}
/**
* @param string $number A positive, binary number.
*/
private function twosComplement(string $number) : string
{
$xor = \str_repeat("\xff", \strlen($number));
$number ^= $xor;
for ($i = \strlen($number) - 1; $i >= 0; $i--) {
$byte = \ord($number[$i]);
if (++$byte !== 256) {
$number[$i] = \chr($byte);
break;
}
$number[$i] = "\x00";
if ($i === 0) {
$number = "\x01" . $number;
}
}
return $number;
}
/**
* Converts a decimal number to a binary string.
*
* @param string $number The number to convert, positive or zero, only digits.
*/
private function toBinary(string $number) : string
{
$result = '';
while ($number !== '0') {
[$number, $remainder] = $this->divQR($number, '256');
$result .= \chr((int) $remainder);
}
return \strrev($result);
}
/**
* Returns the positive decimal representation of a binary number.
*
* @param string $bytes The bytes representing the number.
*/
private function toDecimal(string $bytes) : string
{
$result = '0';
$power = '1';
for ($i = \strlen($bytes) - 1; $i >= 0; $i--) {
$index = \ord($bytes[$i]);
if ($index !== 0) {
$result = $this->add($result, ($index === 1)
? $power
: $this->mul($power, (string) $index)
);
}
if ($i !== 0) {
$power = $this->mul($power, '256');
}
}
return $result;
}
}

View file

@ -0,0 +1,75 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Internal\Calculator;
use Brick\Math\Internal\Calculator;
/**
* Calculator implementation built around the bcmath library.
*
* @internal
*
* @psalm-immutable
*/
class BcMathCalculator extends Calculator
{
public function add(string $a, string $b) : string
{
return \bcadd($a, $b, 0);
}
public function sub(string $a, string $b) : string
{
return \bcsub($a, $b, 0);
}
public function mul(string $a, string $b) : string
{
return \bcmul($a, $b, 0);
}
public function divQ(string $a, string $b) : string
{
return \bcdiv($a, $b, 0);
}
/**
* @psalm-suppress InvalidNullableReturnType
* @psalm-suppress NullableReturnStatement
*/
public function divR(string $a, string $b) : string
{
return \bcmod($a, $b, 0);
}
public function divQR(string $a, string $b) : array
{
$q = \bcdiv($a, $b, 0);
$r = \bcmod($a, $b, 0);
assert($r !== null);
return [$q, $r];
}
public function pow(string $a, int $e) : string
{
return \bcpow($a, (string) $e, 0);
}
public function modPow(string $base, string $exp, string $mod) : string
{
return \bcpowmod($base, $exp, $mod, 0);
}
/**
* @psalm-suppress InvalidNullableReturnType
* @psalm-suppress NullableReturnStatement
*/
public function sqrt(string $n) : string
{
return \bcsqrt($n, 0);
}
}

View file

@ -0,0 +1,108 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Internal\Calculator;
use Brick\Math\Internal\Calculator;
/**
* Calculator implementation built around the GMP library.
*
* @internal
*
* @psalm-immutable
*/
class GmpCalculator extends Calculator
{
public function add(string $a, string $b) : string
{
return \gmp_strval(\gmp_add($a, $b));
}
public function sub(string $a, string $b) : string
{
return \gmp_strval(\gmp_sub($a, $b));
}
public function mul(string $a, string $b) : string
{
return \gmp_strval(\gmp_mul($a, $b));
}
public function divQ(string $a, string $b) : string
{
return \gmp_strval(\gmp_div_q($a, $b));
}
public function divR(string $a, string $b) : string
{
return \gmp_strval(\gmp_div_r($a, $b));
}
public function divQR(string $a, string $b) : array
{
[$q, $r] = \gmp_div_qr($a, $b);
return [
\gmp_strval($q),
\gmp_strval($r)
];
}
public function pow(string $a, int $e) : string
{
return \gmp_strval(\gmp_pow($a, $e));
}
public function modInverse(string $x, string $m) : ?string
{
$result = \gmp_invert($x, $m);
if ($result === false) {
return null;
}
return \gmp_strval($result);
}
public function modPow(string $base, string $exp, string $mod) : string
{
return \gmp_strval(\gmp_powm($base, $exp, $mod));
}
public function gcd(string $a, string $b) : string
{
return \gmp_strval(\gmp_gcd($a, $b));
}
public function fromBase(string $number, int $base) : string
{
return \gmp_strval(\gmp_init($number, $base));
}
public function toBase(string $number, int $base) : string
{
return \gmp_strval($number, $base);
}
public function and(string $a, string $b) : string
{
return \gmp_strval(\gmp_and($a, $b));
}
public function or(string $a, string $b) : string
{
return \gmp_strval(\gmp_or($a, $b));
}
public function xor(string $a, string $b) : string
{
return \gmp_strval(\gmp_xor($a, $b));
}
public function sqrt(string $n) : string
{
return \gmp_strval(\gmp_sqrt($n));
}
}

View file

@ -0,0 +1,581 @@
<?php
declare(strict_types=1);
namespace Brick\Math\Internal\Calculator;
use Brick\Math\Internal\Calculator;
/**
* Calculator implementation using only native PHP code.
*
* @internal
*
* @psalm-immutable
*/
class NativeCalculator extends Calculator
{
/**
* The max number of digits the platform can natively add, subtract, multiply or divide without overflow.
* For multiplication, this represents the max sum of the lengths of both operands.
*
* In addition, it is assumed that an extra digit can hold a carry (1) without overflowing.
* Example: 32-bit: max number 1,999,999,999 (9 digits + carry)
* 64-bit: max number 1,999,999,999,999,999,999 (18 digits + carry)
*/
private int $maxDigits;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
switch (PHP_INT_SIZE) {
case 4:
$this->maxDigits = 9;
break;
case 8:
$this->maxDigits = 18;
break;
default:
throw new \RuntimeException('The platform is not 32-bit or 64-bit as expected.');
}
}
public function add(string $a, string $b) : string
{
/**
* @psalm-var numeric-string $a
* @psalm-var numeric-string $b
*/
$result = $a + $b;
if (is_int($result)) {
return (string) $result;
}
if ($a === '0') {
return $b;
}
if ($b === '0') {
return $a;
}
[$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
$result = $aNeg === $bNeg ? $this->doAdd($aDig, $bDig) : $this->doSub($aDig, $bDig);
if ($aNeg) {
$result = $this->neg($result);
}
return $result;
}
public function sub(string $a, string $b) : string
{
return $this->add($a, $this->neg($b));
}
public function mul(string $a, string $b) : string
{
/**
* @psalm-var numeric-string $a
* @psalm-var numeric-string $b
*/
$result = $a * $b;
if (is_int($result)) {
return (string) $result;
}
if ($a === '0' || $b === '0') {
return '0';
}
if ($a === '1') {
return $b;
}
if ($b === '1') {
return $a;
}
if ($a === '-1') {
return $this->neg($b);
}
if ($b === '-1') {
return $this->neg($a);
}
[$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
$result = $this->doMul($aDig, $bDig);
if ($aNeg !== $bNeg) {
$result = $this->neg($result);
}
return $result;
}
public function divQ(string $a, string $b) : string
{
return $this->divQR($a, $b)[0];
}
public function divR(string $a, string $b): string
{
return $this->divQR($a, $b)[1];
}
public function divQR(string $a, string $b) : array
{
if ($a === '0') {
return ['0', '0'];
}
if ($a === $b) {
return ['1', '0'];
}
if ($b === '1') {
return [$a, '0'];
}
if ($b === '-1') {
return [$this->neg($a), '0'];
}
/** @psalm-var numeric-string $a */
$na = $a * 1; // cast to number
if (is_int($na)) {
/** @psalm-var numeric-string $b */
$nb = $b * 1;
if (is_int($nb)) {
// the only division that may overflow is PHP_INT_MIN / -1,
// which cannot happen here as we've already handled a divisor of -1 above.
$r = $na % $nb;
$q = ($na - $r) / $nb;
assert(is_int($q));
return [
(string) $q,
(string) $r
];
}
}
[$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
[$q, $r] = $this->doDiv($aDig, $bDig);
if ($aNeg !== $bNeg) {
$q = $this->neg($q);
}
if ($aNeg) {
$r = $this->neg($r);
}
return [$q, $r];
}
public function pow(string $a, int $e) : string
{
if ($e === 0) {
return '1';
}
if ($e === 1) {
return $a;
}
$odd = $e % 2;
$e -= $odd;
$aa = $this->mul($a, $a);
/** @psalm-suppress PossiblyInvalidArgument We're sure that $e / 2 is an int now */
$result = $this->pow($aa, $e / 2);
if ($odd === 1) {
$result = $this->mul($result, $a);
}
return $result;
}
/**
* Algorithm from: https://www.geeksforgeeks.org/modular-exponentiation-power-in-modular-arithmetic/
*/
public function modPow(string $base, string $exp, string $mod) : string
{
// special case: the algorithm below fails with 0 power 0 mod 1 (returns 1 instead of 0)
if ($base === '0' && $exp === '0' && $mod === '1') {
return '0';
}
// special case: the algorithm below fails with power 0 mod 1 (returns 1 instead of 0)
if ($exp === '0' && $mod === '1') {
return '0';
}
$x = $base;
$res = '1';
// numbers are positive, so we can use remainder instead of modulo
$x = $this->divR($x, $mod);
while ($exp !== '0') {
if (in_array($exp[-1], ['1', '3', '5', '7', '9'])) { // odd
$res = $this->divR($this->mul($res, $x), $mod);
}
$exp = $this->divQ($exp, '2');
$x = $this->divR($this->mul($x, $x), $mod);
}
return $res;
}
/**
* Adapted from https://cp-algorithms.com/num_methods/roots_newton.html
*/
public function sqrt(string $n) : string
{
if ($n === '0') {
return '0';
}
// initial approximation
$x = \str_repeat('9', \intdiv(\strlen($n), 2) ?: 1);
$decreased = false;
for (;;) {
$nx = $this->divQ($this->add($x, $this->divQ($n, $x)), '2');
if ($x === $nx || $this->cmp($nx, $x) > 0 && $decreased) {
break;
}
$decreased = $this->cmp($nx, $x) < 0;
$x = $nx;
}
return $x;
}
/**
* Performs the addition of two non-signed large integers.
*/
private function doAdd(string $a, string $b) : string
{
[$a, $b, $length] = $this->pad($a, $b);
$carry = 0;
$result = '';
for ($i = $length - $this->maxDigits;; $i -= $this->maxDigits) {
$blockLength = $this->maxDigits;
if ($i < 0) {
$blockLength += $i;
/** @psalm-suppress LoopInvalidation */
$i = 0;
}
/** @psalm-var numeric-string $blockA */
$blockA = \substr($a, $i, $blockLength);
/** @psalm-var numeric-string $blockB */
$blockB = \substr($b, $i, $blockLength);
$sum = (string) ($blockA + $blockB + $carry);
$sumLength = \strlen($sum);
if ($sumLength > $blockLength) {
$sum = \substr($sum, 1);
$carry = 1;
} else {
if ($sumLength < $blockLength) {
$sum = \str_repeat('0', $blockLength - $sumLength) . $sum;
}
$carry = 0;
}
$result = $sum . $result;
if ($i === 0) {
break;
}
}
if ($carry === 1) {
$result = '1' . $result;
}
return $result;
}
/**
* Performs the subtraction of two non-signed large integers.
*/
private function doSub(string $a, string $b) : string
{
if ($a === $b) {
return '0';
}
// Ensure that we always subtract to a positive result: biggest minus smallest.
$cmp = $this->doCmp($a, $b);
$invert = ($cmp === -1);
if ($invert) {
$c = $a;
$a = $b;
$b = $c;
}
[$a, $b, $length] = $this->pad($a, $b);
$carry = 0;
$result = '';
$complement = 10 ** $this->maxDigits;
for ($i = $length - $this->maxDigits;; $i -= $this->maxDigits) {
$blockLength = $this->maxDigits;
if ($i < 0) {
$blockLength += $i;
/** @psalm-suppress LoopInvalidation */
$i = 0;
}
/** @psalm-var numeric-string $blockA */
$blockA = \substr($a, $i, $blockLength);
/** @psalm-var numeric-string $blockB */
$blockB = \substr($b, $i, $blockLength);
$sum = $blockA - $blockB - $carry;
if ($sum < 0) {
$sum += $complement;
$carry = 1;
} else {
$carry = 0;
}
$sum = (string) $sum;
$sumLength = \strlen($sum);
if ($sumLength < $blockLength) {
$sum = \str_repeat('0', $blockLength - $sumLength) . $sum;
}
$result = $sum . $result;
if ($i === 0) {
break;
}
}
// Carry cannot be 1 when the loop ends, as a > b
assert($carry === 0);
$result = \ltrim($result, '0');
if ($invert) {
$result = $this->neg($result);
}
return $result;
}
/**
* Performs the multiplication of two non-signed large integers.
*/
private function doMul(string $a, string $b) : string
{
$x = \strlen($a);
$y = \strlen($b);
$maxDigits = \intdiv($this->maxDigits, 2);
$complement = 10 ** $maxDigits;
$result = '0';
for ($i = $x - $maxDigits;; $i -= $maxDigits) {
$blockALength = $maxDigits;
if ($i < 0) {
$blockALength += $i;
/** @psalm-suppress LoopInvalidation */
$i = 0;
}
$blockA = (int) \substr($a, $i, $blockALength);
$line = '';
$carry = 0;
for ($j = $y - $maxDigits;; $j -= $maxDigits) {
$blockBLength = $maxDigits;
if ($j < 0) {
$blockBLength += $j;
/** @psalm-suppress LoopInvalidation */
$j = 0;
}
$blockB = (int) \substr($b, $j, $blockBLength);
$mul = $blockA * $blockB + $carry;
$value = $mul % $complement;
$carry = ($mul - $value) / $complement;
$value = (string) $value;
$value = \str_pad($value, $maxDigits, '0', STR_PAD_LEFT);
$line = $value . $line;
if ($j === 0) {
break;
}
}
if ($carry !== 0) {
$line = $carry . $line;
}
$line = \ltrim($line, '0');
if ($line !== '') {
$line .= \str_repeat('0', $x - $blockALength - $i);
$result = $this->add($result, $line);
}
if ($i === 0) {
break;
}
}
return $result;
}
/**
* Performs the division of two non-signed large integers.
*
* @return string[] The quotient and remainder.
*/
private function doDiv(string $a, string $b) : array
{
$cmp = $this->doCmp($a, $b);
if ($cmp === -1) {
return ['0', $a];
}
$x = \strlen($a);
$y = \strlen($b);
// we now know that a >= b && x >= y
$q = '0'; // quotient
$r = $a; // remainder
$z = $y; // focus length, always $y or $y+1
for (;;) {
$focus = \substr($a, 0, $z);
$cmp = $this->doCmp($focus, $b);
if ($cmp === -1) {
if ($z === $x) { // remainder < dividend
break;
}
$z++;
}
$zeros = \str_repeat('0', $x - $z);
$q = $this->add($q, '1' . $zeros);
$a = $this->sub($a, $b . $zeros);
$r = $a;
if ($r === '0') { // remainder == 0
break;
}
$x = \strlen($a);
if ($x < $y) { // remainder < dividend
break;
}
$z = $y;
}
return [$q, $r];
}
/**
* Compares two non-signed large numbers.
*
* @return int [-1, 0, 1]
*/
private function doCmp(string $a, string $b) : int
{
$x = \strlen($a);
$y = \strlen($b);
$cmp = $x <=> $y;
if ($cmp !== 0) {
return $cmp;
}
return \strcmp($a, $b) <=> 0; // enforce [-1, 0, 1]
}
/**
* Pads the left of one of the given numbers with zeros if necessary to make both numbers the same length.
*
* The numbers must only consist of digits, without leading minus sign.
*
* @return array{string, string, int}
*/
private function pad(string $a, string $b) : array
{
$x = \strlen($a);
$y = \strlen($b);
if ($x > $y) {
$b = \str_repeat('0', $x - $y) . $b;
return [$a, $b, $x];
}
if ($x < $y) {
$a = \str_repeat('0', $y - $x) . $a;
return [$a, $b, $y];
}
return [$a, $b, $x];
}
}

107
vendor/brick/math/src/RoundingMode.php vendored Normal file
View file

@ -0,0 +1,107 @@
<?php
declare(strict_types=1);
namespace Brick\Math;
/**
* Specifies a rounding behavior for numerical operations capable of discarding precision.
*
* Each rounding mode indicates how the least significant returned digit of a rounded result
* is to be calculated. If fewer digits are returned than the digits needed to represent the
* exact numerical result, the discarded digits will be referred to as the discarded fraction
* regardless the digits' contribution to the value of the number. In other words, considered
* as a numerical value, the discarded fraction could have an absolute value greater than one.
*/
final class RoundingMode
{
/**
* Private constructor. This class is not instantiable.
*
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* Asserts that the requested operation has an exact result, hence no rounding is necessary.
*
* If this rounding mode is specified on an operation that yields a result that
* cannot be represented at the requested scale, a RoundingNecessaryException is thrown.
*/
public const UNNECESSARY = 0;
/**
* Rounds away from zero.
*
* Always increments the digit prior to a nonzero discarded fraction.
* Note that this rounding mode never decreases the magnitude of the calculated value.
*/
public const UP = 1;
/**
* Rounds towards zero.
*
* Never increments the digit prior to a discarded fraction (i.e., truncates).
* Note that this rounding mode never increases the magnitude of the calculated value.
*/
public const DOWN = 2;
/**
* Rounds towards positive infinity.
*
* If the result is positive, behaves as for UP; if negative, behaves as for DOWN.
* Note that this rounding mode never decreases the calculated value.
*/
public const CEILING = 3;
/**
* Rounds towards negative infinity.
*
* If the result is positive, behave as for DOWN; if negative, behave as for UP.
* Note that this rounding mode never increases the calculated value.
*/
public const FLOOR = 4;
/**
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.
*
* Behaves as for UP if the discarded fraction is >= 0.5; otherwise, behaves as for DOWN.
* Note that this is the rounding mode commonly taught at school.
*/
public const HALF_UP = 5;
/**
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
*
* Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves as for DOWN.
*/
public const HALF_DOWN = 6;
/**
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards positive infinity.
*
* If the result is positive, behaves as for HALF_UP; if negative, behaves as for HALF_DOWN.
*/
public const HALF_CEILING = 7;
/**
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards negative infinity.
*
* If the result is positive, behaves as for HALF_DOWN; if negative, behaves as for HALF_UP.
*/
public const HALF_FLOOR = 8;
/**
* Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor.
*
* Behaves as for HALF_UP if the digit to the left of the discarded fraction is odd;
* behaves as for HALF_DOWN if it's even.
*
* Note that this is the rounding mode that statistically minimizes
* cumulative error when applied repeatedly over a sequence of calculations.
* It is sometimes known as "Banker's rounding", and is chiefly used in the USA.
*/
public const HALF_EVEN = 9;
}

View file

@ -42,6 +42,9 @@ namespace Composer\Autoload;
*/
class ClassLoader
{
/** @var \Closure(string):void */
private static $includeFile;
/** @var ?string */
private $vendorDir;
@ -106,6 +109,7 @@ class ClassLoader
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
self::initializeIncludeClosure();
}
/**
@ -425,7 +429,8 @@ class ClassLoader
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
$includeFile = self::$includeFile;
$includeFile($file);
return true;
}
@ -555,18 +560,26 @@ class ClassLoader
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
* @private
*/
function includeFile($file)
{
include $file;
/**
* @return void
*/
private static function initializeIncludeClosure()
{
if (self::$includeFile !== null) {
return;
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
*/
self::$includeFile = \Closure::bind(static function($file) {
include $file;
}, null, null);
}
}

View file

@ -21,12 +21,14 @@ use Composer\Semver\VersionParser;
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
*
* To require its presence, you can require `composer-runtime-api ^2.0`
*
* @final
*/
class InstalledVersions
{
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
*/
private static $installed;
@ -37,7 +39,7 @@ class InstalledVersions
/**
* @var array[]
* @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static $installedByVendor = array();
@ -241,7 +243,7 @@ class InstalledVersions
/**
* @return array
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
*/
public static function getRootPackage()
{
@ -255,7 +257,7 @@ class InstalledVersions
*
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
* @return array[]
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
*/
public static function getRawData()
{
@ -278,7 +280,7 @@ class InstalledVersions
* Returns the raw data of all installed.php which are currently loaded for custom implementations
*
* @return array[]
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
public static function getAllRawData()
{
@ -301,7 +303,7 @@ class InstalledVersions
* @param array[] $data A vendor/composer/installed.php data set
* @return void
*
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
*/
public static function reload($data)
{
@ -311,7 +313,7 @@ class InstalledVersions
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static function getInstalled()
{

View file

@ -2,7 +2,7 @@
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(

View file

@ -2,18 +2,19 @@
// autoload_files.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'60799491728b879e74601d83e38b2cad' => $vendorDir . '/illuminate/collections/helpers.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
'60799491728b879e74601d83e38b2cad' => $vendorDir . '/illuminate/collections/helpers.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
'72579e7bd17821bb1321b87411366eae' => $vendorDir . '/illuminate/support/helpers.php',
'b6ec61354e97f32c0ae683041c78392a' => $vendorDir . '/scrivo/highlight.php/HighlightUtilities/functions.php',
);

View file

@ -2,7 +2,7 @@
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(

View file

@ -2,7 +2,7 @@
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
@ -20,10 +20,11 @@ return array(
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'PonePaste\\' => array($baseDir . '/includes'),
'Illuminate\\Support\\' => array($vendorDir . '/illuminate/collections', $vendorDir . '/illuminate/conditionable', $vendorDir . '/illuminate/macroable', $vendorDir . '/illuminate/support'),
'Illuminate\\Support\\' => array($vendorDir . '/illuminate/macroable', $vendorDir . '/illuminate/conditionable', $vendorDir . '/illuminate/collections', $vendorDir . '/illuminate/support'),
'Illuminate\\Database\\' => array($vendorDir . '/illuminate/database'),
'Illuminate\\Contracts\\' => array($vendorDir . '/illuminate/contracts'),
'Illuminate\\Container\\' => array($vendorDir . '/illuminate/container'),
'Doctrine\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib/Doctrine/Inflector'),
'Carbon\\' => array($vendorDir . '/nesbot/carbon/src/Carbon'),
'Brick\\Math\\' => array($vendorDir . '/brick/math/src'),
);

View file

@ -25,56 +25,26 @@ class ComposerAutoloaderInit5bf95489f4eff2c10ec062bf7ba377da
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit5bf95489f4eff2c10ec062bf7ba377da', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit5bf95489f4eff2c10ec062bf7ba377da', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit5bf95489f4eff2c10ec062bf7ba377da::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit5bf95489f4eff2c10ec062bf7ba377da::getInitializer($loader));
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit5bf95489f4eff2c10ec062bf7ba377da::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire5bf95489f4eff2c10ec062bf7ba377da($fileIdentifier, $file);
$filesToLoad = \Composer\Autoload\ComposerStaticInit5bf95489f4eff2c10ec062bf7ba377da::$files;
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
require $file;
}
}, null, null);
foreach ($filesToLoad as $fileIdentifier => $file) {
$requireFile($fileIdentifier, $file);
}
return $loader;
}
}
/**
* @param string $fileIdentifier
* @param string $file
* @return void
*/
function composerRequire5bf95489f4eff2c10ec062bf7ba377da($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
require $file;
}
}

View file

@ -8,13 +8,14 @@ class ComposerStaticInit5bf95489f4eff2c10ec062bf7ba377da
{
public static $files = array (
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'60799491728b879e74601d83e38b2cad' => __DIR__ . '/..' . '/illuminate/collections/helpers.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
'60799491728b879e74601d83e38b2cad' => __DIR__ . '/..' . '/illuminate/collections/helpers.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
'72579e7bd17821bb1321b87411366eae' => __DIR__ . '/..' . '/illuminate/support/helpers.php',
'b6ec61354e97f32c0ae683041c78392a' => __DIR__ . '/..' . '/scrivo/highlight.php/HighlightUtilities/functions.php',
);
@ -58,6 +59,10 @@ class ComposerStaticInit5bf95489f4eff2c10ec062bf7ba377da
array (
'Carbon\\' => 7,
),
'B' =>
array (
'Brick\\Math\\' => 11,
),
);
public static $prefixDirsPsr4 = array (
@ -119,9 +124,9 @@ class ComposerStaticInit5bf95489f4eff2c10ec062bf7ba377da
),
'Illuminate\\Support\\' =>
array (
0 => __DIR__ . '/..' . '/illuminate/collections',
0 => __DIR__ . '/..' . '/illuminate/macroable',
1 => __DIR__ . '/..' . '/illuminate/conditionable',
2 => __DIR__ . '/..' . '/illuminate/macroable',
2 => __DIR__ . '/..' . '/illuminate/collections',
3 => __DIR__ . '/..' . '/illuminate/support',
),
'Illuminate\\Database\\' =>
@ -144,6 +149,10 @@ class ComposerStaticInit5bf95489f4eff2c10ec062bf7ba377da
array (
0 => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon',
),
'Brick\\Math\\' =>
array (
0 => __DIR__ . '/..' . '/brick/math/src',
),
);
public static $prefixesPsr0 = array (

View file

@ -1,32 +1,90 @@
{
"packages": [
{
"name": "doctrine/inflector",
"version": "2.0.4",
"version_normalized": "2.0.4.0",
"name": "brick/math",
"version": "0.11.0",
"version_normalized": "0.11.0.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
"reference": "8b7ff3e4b7de6b2c84da85637b59fd2880ecaa89"
"url": "https://github.com/brick/math.git",
"reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/8b7ff3e4b7de6b2c84da85637b59fd2880ecaa89",
"reference": "8b7ff3e4b7de6b2c84da85637b59fd2880ecaa89",
"url": "https://api.github.com/repos/brick/math/zipball/0ad82ce168c82ba30d1c01ec86116ab52f589478",
"reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478",
"shasum": ""
},
"require": {
"php": "^8.0"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.2",
"phpunit/phpunit": "^9.0",
"vimeo/psalm": "5.0.0"
},
"time": "2023-01-15T23:15:59+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Brick\\Math\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Arbitrary-precision arithmetic library",
"keywords": [
"Arbitrary-precision",
"BigInteger",
"BigRational",
"arithmetic",
"bigdecimal",
"bignum",
"brick",
"math"
],
"support": {
"issues": "https://github.com/brick/math/issues",
"source": "https://github.com/brick/math/tree/0.11.0"
},
"funding": [
{
"url": "https://github.com/BenMorel",
"type": "github"
}
],
"install-path": "../brick/math"
},
{
"name": "doctrine/inflector",
"version": "2.0.6",
"version_normalized": "2.0.6.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
"reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/d9d313a36c872fd6ee06d9a6cbcf713eaa40f024",
"reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^8.2",
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"phpstan/phpstan-strict-rules": "^0.12",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
"vimeo/psalm": "^4.10"
"doctrine/coding-standard": "^10",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpstan/phpstan-strict-rules": "^1.3",
"phpunit/phpunit": "^8.5 || ^9.5",
"vimeo/psalm": "^4.25"
},
"time": "2021-10-22T20:16:43+00:00",
"time": "2022-10-20T09:10:12+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -76,7 +134,7 @@
],
"support": {
"issues": "https://github.com/doctrine/inflector/issues",
"source": "https://github.com/doctrine/inflector/tree/2.0.4"
"source": "https://github.com/doctrine/inflector/tree/2.0.6"
},
"funding": [
{
@ -149,17 +207,17 @@
},
{
"name": "illuminate/collections",
"version": "v9.4.1",
"version_normalized": "9.4.1.0",
"version": "v9.52.4",
"version_normalized": "9.52.4.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/collections.git",
"reference": "22c4bb17f4e6c6fb470b5957e8232b1b5baf76b0"
"reference": "0168d0e44ea0c4fe5451fe08cde7049b9e9f9741"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/collections/zipball/22c4bb17f4e6c6fb470b5957e8232b1b5baf76b0",
"reference": "22c4bb17f4e6c6fb470b5957e8232b1b5baf76b0",
"url": "https://api.github.com/repos/illuminate/collections/zipball/0168d0e44ea0c4fe5451fe08cde7049b9e9f9741",
"reference": "0168d0e44ea0c4fe5451fe08cde7049b9e9f9741",
"shasum": ""
},
"require": {
@ -171,7 +229,7 @@
"suggest": {
"symfony/var-dumper": "Required to use the dump method (^6.0)."
},
"time": "2022-03-07T15:02:25+00:00",
"time": "2023-02-22T11:32:27+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -207,23 +265,23 @@
},
{
"name": "illuminate/conditionable",
"version": "v9.4.1",
"version_normalized": "9.4.1.0",
"version": "v9.52.4",
"version_normalized": "9.52.4.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/conditionable.git",
"reference": "56b4ba1166c264064bf63896f498a2bee320d16a"
"reference": "bea24daa0fa84b7e7b0d5b84f62c71b7e2dc3364"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/conditionable/zipball/56b4ba1166c264064bf63896f498a2bee320d16a",
"reference": "56b4ba1166c264064bf63896f498a2bee320d16a",
"url": "https://api.github.com/repos/illuminate/conditionable/zipball/bea24daa0fa84b7e7b0d5b84f62c71b7e2dc3364",
"reference": "bea24daa0fa84b7e7b0d5b84f62c71b7e2dc3364",
"shasum": ""
},
"require": {
"php": "^8.0.2"
},
"time": "2022-02-28T16:37:46+00:00",
"time": "2023-02-01T21:42:32+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -256,17 +314,17 @@
},
{
"name": "illuminate/container",
"version": "v9.4.1",
"version_normalized": "9.4.1.0",
"version": "v9.52.4",
"version_normalized": "9.52.4.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/container.git",
"reference": "66f9049b19fb34e74134c6eeff92a442cee068e5"
"reference": "1641dda2d0750b68bb1264a3b37ff3973f2e6265"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/container/zipball/66f9049b19fb34e74134c6eeff92a442cee068e5",
"reference": "66f9049b19fb34e74134c6eeff92a442cee068e5",
"url": "https://api.github.com/repos/illuminate/container/zipball/1641dda2d0750b68bb1264a3b37ff3973f2e6265",
"reference": "1641dda2d0750b68bb1264a3b37ff3973f2e6265",
"shasum": ""
},
"require": {
@ -277,7 +335,7 @@
"provide": {
"psr/container-implementation": "1.1|2.0"
},
"time": "2022-03-03T14:08:19+00:00",
"time": "2023-01-24T16:54:18+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -310,17 +368,17 @@
},
{
"name": "illuminate/contracts",
"version": "v9.4.1",
"version_normalized": "9.4.1.0",
"version": "v9.52.4",
"version_normalized": "9.52.4.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/contracts.git",
"reference": "ce68106c575410c71f92ac1c91c5d95c561033bc"
"reference": "44f65d723b13823baa02ff69751a5948bde60c22"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/ce68106c575410c71f92ac1c91c5d95c561033bc",
"reference": "ce68106c575410c71f92ac1c91c5d95c561033bc",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/44f65d723b13823baa02ff69751a5948bde60c22",
"reference": "44f65d723b13823baa02ff69751a5948bde60c22",
"shasum": ""
},
"require": {
@ -328,7 +386,7 @@
"psr/container": "^1.1.1|^2.0.1",
"psr/simple-cache": "^1.0|^2.0|^3.0"
},
"time": "2022-03-04T18:18:32+00:00",
"time": "2023-02-08T14:36:30+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -361,39 +419,41 @@
},
{
"name": "illuminate/database",
"version": "v9.4.1",
"version_normalized": "9.4.1.0",
"version": "v9.52.4",
"version_normalized": "9.52.4.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/database.git",
"reference": "0fffd6ba91eb58330cbf7331c77ea38c2a16b5d9"
"reference": "fc7e9cf5d4c7c4c0a2800c0d345cc9985fb1b040"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/database/zipball/0fffd6ba91eb58330cbf7331c77ea38c2a16b5d9",
"reference": "0fffd6ba91eb58330cbf7331c77ea38c2a16b5d9",
"url": "https://api.github.com/repos/illuminate/database/zipball/fc7e9cf5d4c7c4c0a2800c0d345cc9985fb1b040",
"reference": "fc7e9cf5d4c7c4c0a2800c0d345cc9985fb1b040",
"shasum": ""
},
"require": {
"ext-json": "*",
"brick/math": "^0.9.3|^0.10.2|^0.11",
"ext-pdo": "*",
"illuminate/collections": "^9.0",
"illuminate/container": "^9.0",
"illuminate/contracts": "^9.0",
"illuminate/macroable": "^9.0",
"illuminate/support": "^9.0",
"php": "^8.0.2",
"symfony/console": "^6.0"
"symfony/console": "^6.0.9"
},
"suggest": {
"doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.13.3|^3.1.4).",
"fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).",
"ext-filter": "Required to use the Postgres database driver.",
"fakerphp/faker": "Required to use the eloquent factory builder (^1.21).",
"illuminate/console": "Required to use the database commands (^9.0).",
"illuminate/events": "Required to use the observers with Eloquent (^9.0).",
"illuminate/filesystem": "Required to use the migrations (^9.0).",
"illuminate/pagination": "Required to paginate the result set (^9.0).",
"symfony/finder": "Required to use Eloquent model factories (^6.0)."
},
"time": "2022-03-07T01:28:38+00:00",
"time": "2023-02-12T20:16:50+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -432,23 +492,23 @@
},
{
"name": "illuminate/macroable",
"version": "v9.4.1",
"version_normalized": "9.4.1.0",
"version": "v9.52.4",
"version_normalized": "9.52.4.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/macroable.git",
"reference": "25a2c6dac2b7541ecbadef952702e84ae15f5354"
"reference": "e3bfaf6401742a9c6abca61b9b10e998e5b6449a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/macroable/zipball/25a2c6dac2b7541ecbadef952702e84ae15f5354",
"reference": "25a2c6dac2b7541ecbadef952702e84ae15f5354",
"url": "https://api.github.com/repos/illuminate/macroable/zipball/e3bfaf6401742a9c6abca61b9b10e998e5b6449a",
"reference": "e3bfaf6401742a9c6abca61b9b10e998e5b6449a",
"shasum": ""
},
"require": {
"php": "^8.0.2"
},
"time": "2022-02-01T14:44:21+00:00",
"time": "2022-08-09T13:29:29+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -481,28 +541,29 @@
},
{
"name": "illuminate/support",
"version": "v9.4.1",
"version_normalized": "9.4.1.0",
"version": "v9.52.4",
"version_normalized": "9.52.4.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/support.git",
"reference": "568ed7a21a75e0bd9ca641b6c4a626872ee26d6f"
"reference": "63dcb4523ccdfc01cdf5be17791f07cc20982a1e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/support/zipball/568ed7a21a75e0bd9ca641b6c4a626872ee26d6f",
"reference": "568ed7a21a75e0bd9ca641b6c4a626872ee26d6f",
"url": "https://api.github.com/repos/illuminate/support/zipball/63dcb4523ccdfc01cdf5be17791f07cc20982a1e",
"reference": "63dcb4523ccdfc01cdf5be17791f07cc20982a1e",
"shasum": ""
},
"require": {
"doctrine/inflector": "^2.0",
"ext-json": "*",
"ext-ctype": "*",
"ext-filter": "*",
"ext-mbstring": "*",
"illuminate/collections": "^9.0",
"illuminate/conditionable": "^9.0",
"illuminate/contracts": "^9.0",
"illuminate/macroable": "^9.0",
"nesbot/carbon": "^2.53.1",
"nesbot/carbon": "^2.62.1",
"php": "^8.0.2",
"voku/portable-ascii": "^2.0"
},
@ -512,12 +573,13 @@
"suggest": {
"illuminate/filesystem": "Required to use the composer class (^9.0).",
"league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.0.2).",
"ramsey/uuid": "Required to use Str::uuid() (^4.2.2).",
"ramsey/uuid": "Required to use Str::uuid() (^4.7).",
"symfony/process": "Required to use the composer class (^6.0).",
"symfony/uid": "Required to use Str::ulid() (^6.0).",
"symfony/var-dumper": "Required to use the dd function (^6.0).",
"vlucas/phpdotenv": "Required to use the Env class and env helper (^5.4.1)."
},
"time": "2022-03-08T14:39:38+00:00",
"time": "2023-02-13T16:54:43+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -553,17 +615,17 @@
},
{
"name": "nesbot/carbon",
"version": "2.57.0",
"version_normalized": "2.57.0.0",
"version": "2.66.0",
"version_normalized": "2.66.0.0",
"source": {
"type": "git",
"url": "https://github.com/briannesbitt/Carbon.git",
"reference": "4a54375c21eea4811dbd1149fe6b246517554e78"
"reference": "496712849902241f04902033b0441b269effe001"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4a54375c21eea4811dbd1149fe6b246517554e78",
"reference": "4a54375c21eea4811dbd1149fe6b246517554e78",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/496712849902241f04902033b0441b269effe001",
"reference": "496712849902241f04902033b0441b269effe001",
"shasum": ""
},
"require": {
@ -574,17 +636,19 @@
"symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0"
},
"require-dev": {
"doctrine/dbal": "^2.0 || ^3.0",
"doctrine/dbal": "^2.0 || ^3.1.4",
"doctrine/orm": "^2.7",
"friendsofphp/php-cs-fixer": "^3.0",
"kylekatarnls/multi-tester": "^2.0",
"ondrejmirtes/better-reflection": "*",
"phpmd/phpmd": "^2.9",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12.54 || ^1.0",
"phpunit/phpunit": "^7.5.20 || ^8.5.14",
"phpstan/phpstan": "^0.12.99 || ^1.7.14",
"phpunit/php-file-iterator": "^2.0.5 || ^3.0.6",
"phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20",
"squizlabs/php_codesniffer": "^3.4"
},
"time": "2022-02-13T18:13:33+00:00",
"time": "2023-01-29T18:53:47+00:00",
"bin": [
"bin/carbon"
],
@ -640,11 +704,15 @@
},
"funding": [
{
"url": "https://opencollective.com/Carbon",
"type": "open_collective"
"url": "https://github.com/sponsors/kylekatarnls",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/nesbot/carbon",
"url": "https://opencollective.com/Carbon#sponsor",
"type": "opencollective"
},
{
"url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme",
"type": "tidelift"
}
],
@ -843,21 +911,22 @@
},
{
"name": "symfony/console",
"version": "v6.0.5",
"version_normalized": "6.0.5.0",
"version": "v6.2.5",
"version_normalized": "6.2.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "3bebf4108b9e07492a2a4057d207aa5a77d146b1"
"reference": "3e294254f2191762c1d137aed4b94e966965e985"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/3bebf4108b9e07492a2a4057d207aa5a77d146b1",
"reference": "3bebf4108b9e07492a2a4057d207aa5a77d146b1",
"url": "https://api.github.com/repos/symfony/console/zipball/3e294254f2191762c1d137aed4b94e966965e985",
"reference": "3e294254f2191762c1d137aed4b94e966965e985",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"php": ">=8.1",
"symfony/deprecation-contracts": "^2.1|^3",
"symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^1.1|^2|^3",
"symfony/string": "^5.4|^6.0"
@ -887,7 +956,7 @@
"symfony/lock": "",
"symfony/process": ""
},
"time": "2022-02-25T10:48:52+00:00",
"time": "2023-01-01T08:38:09+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -921,7 +990,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v6.0.5"
"source": "https://github.com/symfony/console/tree/v6.2.5"
},
"funding": [
{
@ -940,18 +1009,88 @@
"install-path": "../symfony/console"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"name": "symfony/deprecation-contracts",
"version": "v3.2.0",
"version_normalized": "3.2.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "30885182c981ab175d4d034db0f6f469898070ab"
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab",
"reference": "30885182c981ab175d4d034db0f6f469898070ab",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/1ee04c65529dea5d8744774d474e7cbd2f1206d3",
"reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"time": "2022-11-25T10:21:52+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.3-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"install-path": "../symfony/deprecation-contracts"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.27.0",
"version_normalized": "1.27.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"shasum": ""
},
"require": {
@ -963,11 +1102,11 @@
"suggest": {
"ext-ctype": "For best performance"
},
"time": "2021-10-20T20:35:02+00:00",
"time": "2022-11-03T14:55:06+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1006,7 +1145,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
},
"funding": [
{
@ -1026,17 +1165,17 @@
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"version": "v1.27.0",
"version_normalized": "1.27.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "81b86b50cf841a64252b439e738e97f4a34e2783"
"reference": "511a08c03c1960e08a883f4cffcacd219b758354"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783",
"reference": "81b86b50cf841a64252b439e738e97f4a34e2783",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354",
"shasum": ""
},
"require": {
@ -1045,11 +1184,11 @@
"suggest": {
"ext-intl": "For best performance"
},
"time": "2021-11-23T21:10:46+00:00",
"time": "2022-11-03T14:55:06+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1090,7 +1229,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
},
"funding": [
{
@ -1110,17 +1249,17 @@
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"version": "v1.27.0",
"version_normalized": "1.27.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"shasum": ""
},
"require": {
@ -1129,11 +1268,11 @@
"suggest": {
"ext-intl": "For best performance"
},
"time": "2021-02-19T12:13:01+00:00",
"time": "2022-11-03T14:55:06+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1177,7 +1316,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
},
"funding": [
{
@ -1197,17 +1336,17 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"version": "v1.27.0",
"version_normalized": "1.27.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825"
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825",
"reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"shasum": ""
},
"require": {
@ -1219,11 +1358,11 @@
"suggest": {
"ext-mbstring": "For best performance"
},
"time": "2021-11-30T18:21:41+00:00",
"time": "2022-11-03T14:55:06+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1263,7 +1402,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
},
"funding": [
{
@ -1283,27 +1422,27 @@
},
{
"name": "symfony/polyfill-php80",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"version": "v1.27.0",
"version_normalized": "1.27.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c"
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c",
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"time": "2022-03-04T08:16:47+00:00",
"time": "2022-11-03T14:55:06+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1349,7 +1488,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
},
"funding": [
{
@ -1369,21 +1508,21 @@
},
{
"name": "symfony/service-contracts",
"version": "v3.0.0",
"version_normalized": "3.0.0.0",
"version": "v3.2.0",
"version_normalized": "3.2.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "36715ebf9fb9db73db0cb24263c79077c6fe8603"
"reference": "aac98028c69df04ee77eb69b96b86ee51fbf4b75"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/36715ebf9fb9db73db0cb24263c79077c6fe8603",
"reference": "36715ebf9fb9db73db0cb24263c79077c6fe8603",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/aac98028c69df04ee77eb69b96b86ee51fbf4b75",
"reference": "aac98028c69df04ee77eb69b96b86ee51fbf4b75",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"php": ">=8.1",
"psr/container": "^2.0"
},
"conflict": {
@ -1392,11 +1531,11 @@
"suggest": {
"symfony/service-implementation": ""
},
"time": "2021-11-04T17:53:12+00:00",
"time": "2022-11-25T10:21:52+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.0-dev"
"dev-main": "3.3-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -1407,7 +1546,10 @@
"autoload": {
"psr-4": {
"Symfony\\Contracts\\Service\\": ""
}
},
"exclude-from-classmap": [
"/Test/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@ -1434,7 +1576,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v3.0.0"
"source": "https://github.com/symfony/service-contracts/tree/v3.2.0"
},
"funding": [
{
@ -1454,21 +1596,21 @@
},
{
"name": "symfony/string",
"version": "v6.0.3",
"version_normalized": "6.0.3.0",
"version": "v6.2.5",
"version_normalized": "6.2.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "522144f0c4c004c80d56fa47e40e17028e2eefc2"
"reference": "b2dac0fa27b1ac0f9c0c0b23b43977f12308d0b0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/522144f0c4c004c80d56fa47e40e17028e2eefc2",
"reference": "522144f0c4c004c80d56fa47e40e17028e2eefc2",
"url": "https://api.github.com/repos/symfony/string/zipball/b2dac0fa27b1ac0f9c0c0b23b43977f12308d0b0",
"reference": "b2dac0fa27b1ac0f9c0c0b23b43977f12308d0b0",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"php": ">=8.1",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
@ -1480,10 +1622,11 @@
"require-dev": {
"symfony/error-handler": "^5.4|^6.0",
"symfony/http-client": "^5.4|^6.0",
"symfony/intl": "^6.2",
"symfony/translation-contracts": "^2.0|^3.0",
"symfony/var-exporter": "^5.4|^6.0"
},
"time": "2022-01-02T09:55:41+00:00",
"time": "2023-01-01T08:38:09+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -1522,7 +1665,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v6.0.3"
"source": "https://github.com/symfony/string/tree/v6.2.5"
},
"funding": [
{
@ -1542,21 +1685,21 @@
},
{
"name": "symfony/translation",
"version": "v6.0.6",
"version_normalized": "6.0.6.0",
"version": "v6.2.5",
"version_normalized": "6.2.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "f6639cb9b5e0c57fe31e3263b900a77eedb0c908"
"reference": "60556925a703cfbc1581cde3b3f35b0bb0ea904c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/f6639cb9b5e0c57fe31e3263b900a77eedb0c908",
"reference": "f6639cb9b5e0c57fe31e3263b900a77eedb0c908",
"url": "https://api.github.com/repos/symfony/translation/zipball/60556925a703cfbc1581cde3b3f35b0bb0ea904c",
"reference": "60556925a703cfbc1581cde3b3f35b0bb0ea904c",
"shasum": ""
},
"require": {
"php": ">=8.0.2",
"php": ">=8.1",
"symfony/polyfill-mbstring": "~1.0",
"symfony/translation-contracts": "^2.3|^3.0"
},
@ -1572,6 +1715,7 @@
"symfony/translation-implementation": "2.3|3.0"
},
"require-dev": {
"nikic/php-parser": "^4.13",
"psr/log": "^1|^2|^3",
"symfony/config": "^5.4|^6.0",
"symfony/console": "^5.4|^6.0",
@ -1581,15 +1725,17 @@
"symfony/http-kernel": "^5.4|^6.0",
"symfony/intl": "^5.4|^6.0",
"symfony/polyfill-intl-icu": "^1.21",
"symfony/routing": "^5.4|^6.0",
"symfony/service-contracts": "^1.1.2|^2|^3",
"symfony/yaml": "^5.4|^6.0"
},
"suggest": {
"nikic/php-parser": "To use PhpAstExtractor",
"psr/log-implementation": "To use logging capability in translator",
"symfony/config": "",
"symfony/yaml": ""
},
"time": "2022-03-02T12:58:14+00:00",
"time": "2023-01-05T07:00:27+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -1620,7 +1766,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/translation/tree/v6.0.6"
"source": "https://github.com/symfony/translation/tree/v6.2.5"
},
"funding": [
{
@ -1640,30 +1786,30 @@
},
{
"name": "symfony/translation-contracts",
"version": "v3.0.0",
"version_normalized": "3.0.0.0",
"version": "v3.2.0",
"version_normalized": "3.2.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation-contracts.git",
"reference": "1b6ea5a7442af5a12dba3dbd6d71034b5b234e77"
"reference": "68cce71402305a015f8c1589bfada1280dc64fe7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/1b6ea5a7442af5a12dba3dbd6d71034b5b234e77",
"reference": "1b6ea5a7442af5a12dba3dbd6d71034b5b234e77",
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/68cce71402305a015f8c1589bfada1280dc64fe7",
"reference": "68cce71402305a015f8c1589bfada1280dc64fe7",
"shasum": ""
},
"require": {
"php": ">=8.0.2"
"php": ">=8.1"
},
"suggest": {
"symfony/translation-implementation": ""
},
"time": "2021-09-07T12:43:40+00:00",
"time": "2022-11-25T10:21:52+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.0-dev"
"dev-main": "3.3-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -1674,7 +1820,10 @@
"autoload": {
"psr-4": {
"Symfony\\Contracts\\Translation\\": ""
}
},
"exclude-from-classmap": [
"/Test/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@ -1701,7 +1850,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/translation-contracts/tree/v3.0.0"
"source": "https://github.com/symfony/translation-contracts/tree/v3.2.0"
},
"funding": [
{

View file

@ -1,121 +1,130 @@
<?php return array(
'root' => array(
'name' => 'aftercase/ponepaste',
'pretty_version' => 'dev-main',
'version' => 'dev-main',
'reference' => '8914700af7493ab2f4da22d60e13d47c410057ab',
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '6f1363aafe558eeabeb9ac6985892803b5bd14f7',
'name' => 'aftercase/ponepaste',
'dev' => true,
),
'versions' => array(
'aftercase/ponepaste' => array(
'pretty_version' => 'dev-main',
'version' => 'dev-main',
'reference' => '8914700af7493ab2f4da22d60e13d47c410057ab',
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '6f1363aafe558eeabeb9ac6985892803b5bd14f7',
'dev_requirement' => false,
),
'brick/math' => array(
'pretty_version' => '0.11.0',
'version' => '0.11.0.0',
'reference' => '0ad82ce168c82ba30d1c01ec86116ab52f589478',
'type' => 'library',
'install_path' => __DIR__ . '/../brick/math',
'aliases' => array(),
'dev_requirement' => false,
),
'doctrine/inflector' => array(
'pretty_version' => '2.0.4',
'version' => '2.0.4.0',
'pretty_version' => '2.0.6',
'version' => '2.0.6.0',
'reference' => 'd9d313a36c872fd6ee06d9a6cbcf713eaa40f024',
'type' => 'library',
'install_path' => __DIR__ . '/../doctrine/inflector',
'aliases' => array(),
'reference' => '8b7ff3e4b7de6b2c84da85637b59fd2880ecaa89',
'dev_requirement' => false,
),
'erusev/parsedown' => array(
'pretty_version' => '1.7.4',
'version' => '1.7.4.0',
'reference' => 'cb17b6477dfff935958ba01325f2e8a2bfa6dab3',
'type' => 'library',
'install_path' => __DIR__ . '/../erusev/parsedown',
'aliases' => array(),
'reference' => 'cb17b6477dfff935958ba01325f2e8a2bfa6dab3',
'dev_requirement' => false,
),
'illuminate/collections' => array(
'pretty_version' => 'v9.4.1',
'version' => '9.4.1.0',
'pretty_version' => 'v9.52.4',
'version' => '9.52.4.0',
'reference' => '0168d0e44ea0c4fe5451fe08cde7049b9e9f9741',
'type' => 'library',
'install_path' => __DIR__ . '/../illuminate/collections',
'aliases' => array(),
'reference' => '22c4bb17f4e6c6fb470b5957e8232b1b5baf76b0',
'dev_requirement' => false,
),
'illuminate/conditionable' => array(
'pretty_version' => 'v9.4.1',
'version' => '9.4.1.0',
'pretty_version' => 'v9.52.4',
'version' => '9.52.4.0',
'reference' => 'bea24daa0fa84b7e7b0d5b84f62c71b7e2dc3364',
'type' => 'library',
'install_path' => __DIR__ . '/../illuminate/conditionable',
'aliases' => array(),
'reference' => '56b4ba1166c264064bf63896f498a2bee320d16a',
'dev_requirement' => false,
),
'illuminate/container' => array(
'pretty_version' => 'v9.4.1',
'version' => '9.4.1.0',
'pretty_version' => 'v9.52.4',
'version' => '9.52.4.0',
'reference' => '1641dda2d0750b68bb1264a3b37ff3973f2e6265',
'type' => 'library',
'install_path' => __DIR__ . '/../illuminate/container',
'aliases' => array(),
'reference' => '66f9049b19fb34e74134c6eeff92a442cee068e5',
'dev_requirement' => false,
),
'illuminate/contracts' => array(
'pretty_version' => 'v9.4.1',
'version' => '9.4.1.0',
'pretty_version' => 'v9.52.4',
'version' => '9.52.4.0',
'reference' => '44f65d723b13823baa02ff69751a5948bde60c22',
'type' => 'library',
'install_path' => __DIR__ . '/../illuminate/contracts',
'aliases' => array(),
'reference' => 'ce68106c575410c71f92ac1c91c5d95c561033bc',
'dev_requirement' => false,
),
'illuminate/database' => array(
'pretty_version' => 'v9.4.1',
'version' => '9.4.1.0',
'pretty_version' => 'v9.52.4',
'version' => '9.52.4.0',
'reference' => 'fc7e9cf5d4c7c4c0a2800c0d345cc9985fb1b040',
'type' => 'library',
'install_path' => __DIR__ . '/../illuminate/database',
'aliases' => array(),
'reference' => '0fffd6ba91eb58330cbf7331c77ea38c2a16b5d9',
'dev_requirement' => false,
),
'illuminate/macroable' => array(
'pretty_version' => 'v9.4.1',
'version' => '9.4.1.0',
'pretty_version' => 'v9.52.4',
'version' => '9.52.4.0',
'reference' => 'e3bfaf6401742a9c6abca61b9b10e998e5b6449a',
'type' => 'library',
'install_path' => __DIR__ . '/../illuminate/macroable',
'aliases' => array(),
'reference' => '25a2c6dac2b7541ecbadef952702e84ae15f5354',
'dev_requirement' => false,
),
'illuminate/support' => array(
'pretty_version' => 'v9.4.1',
'version' => '9.4.1.0',
'pretty_version' => 'v9.52.4',
'version' => '9.52.4.0',
'reference' => '63dcb4523ccdfc01cdf5be17791f07cc20982a1e',
'type' => 'library',
'install_path' => __DIR__ . '/../illuminate/support',
'aliases' => array(),
'reference' => '568ed7a21a75e0bd9ca641b6c4a626872ee26d6f',
'dev_requirement' => false,
),
'nesbot/carbon' => array(
'pretty_version' => '2.57.0',
'version' => '2.57.0.0',
'pretty_version' => '2.66.0',
'version' => '2.66.0.0',
'reference' => '496712849902241f04902033b0441b269effe001',
'type' => 'library',
'install_path' => __DIR__ . '/../nesbot/carbon',
'aliases' => array(),
'reference' => '4a54375c21eea4811dbd1149fe6b246517554e78',
'dev_requirement' => false,
),
'psr/container' => array(
'pretty_version' => '2.0.2',
'version' => '2.0.2.0',
'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/container',
'aliases' => array(),
'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963',
'dev_requirement' => false,
),
'psr/container-implementation' => array(
@ -133,109 +142,118 @@
'psr/simple-cache' => array(
'pretty_version' => '3.0.0',
'version' => '3.0.0.0',
'reference' => '764e0b3939f5ca87cb904f570ef9be2d78a07865',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/simple-cache',
'aliases' => array(),
'reference' => '764e0b3939f5ca87cb904f570ef9be2d78a07865',
'dev_requirement' => false,
),
'scrivo/highlight.php' => array(
'pretty_version' => 'v9.18.1.9',
'version' => '9.18.1.9',
'reference' => 'd45585504777e6194a91dffc7270ca39833787f8',
'type' => 'library',
'install_path' => __DIR__ . '/../scrivo/highlight.php',
'aliases' => array(),
'reference' => 'd45585504777e6194a91dffc7270ca39833787f8',
'dev_requirement' => false,
),
'symfony/console' => array(
'pretty_version' => 'v6.0.5',
'version' => '6.0.5.0',
'pretty_version' => 'v6.2.5',
'version' => '6.2.5.0',
'reference' => '3e294254f2191762c1d137aed4b94e966965e985',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/console',
'aliases' => array(),
'reference' => '3bebf4108b9e07492a2a4057d207aa5a77d146b1',
'dev_requirement' => false,
),
'symfony/deprecation-contracts' => array(
'pretty_version' => 'v3.2.0',
'version' => '3.2.0.0',
'reference' => '1ee04c65529dea5d8744774d474e7cbd2f1206d3',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-ctype' => array(
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'pretty_version' => 'v1.27.0',
'version' => '1.27.0.0',
'reference' => '5bbc823adecdae860bb64756d639ecfec17b050a',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
'aliases' => array(),
'reference' => '30885182c981ab175d4d034db0f6f469898070ab',
'dev_requirement' => false,
),
'symfony/polyfill-intl-grapheme' => array(
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'pretty_version' => 'v1.27.0',
'version' => '1.27.0.0',
'reference' => '511a08c03c1960e08a883f4cffcacd219b758354',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme',
'aliases' => array(),
'reference' => '81b86b50cf841a64252b439e738e97f4a34e2783',
'dev_requirement' => false,
),
'symfony/polyfill-intl-normalizer' => array(
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'pretty_version' => 'v1.27.0',
'version' => '1.27.0.0',
'reference' => '19bd1e4fcd5b91116f14d8533c57831ed00571b6',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer',
'aliases' => array(),
'reference' => '8590a5f561694770bdcd3f9b5c69dde6945028e8',
'dev_requirement' => false,
),
'symfony/polyfill-mbstring' => array(
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'pretty_version' => 'v1.27.0',
'version' => '1.27.0.0',
'reference' => '8ad114f6b39e2c98a8b0e3bd907732c207c2b534',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
'aliases' => array(),
'reference' => '0abb51d2f102e00a4eefcf46ba7fec406d245825',
'dev_requirement' => false,
),
'symfony/polyfill-php80' => array(
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'pretty_version' => 'v1.27.0',
'version' => '1.27.0.0',
'reference' => '7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
'aliases' => array(),
'reference' => '4407588e0d3f1f52efb65fbe92babe41f37fe50c',
'dev_requirement' => false,
),
'symfony/service-contracts' => array(
'pretty_version' => 'v3.0.0',
'version' => '3.0.0.0',
'pretty_version' => 'v3.2.0',
'version' => '3.2.0.0',
'reference' => 'aac98028c69df04ee77eb69b96b86ee51fbf4b75',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/service-contracts',
'aliases' => array(),
'reference' => '36715ebf9fb9db73db0cb24263c79077c6fe8603',
'dev_requirement' => false,
),
'symfony/string' => array(
'pretty_version' => 'v6.0.3',
'version' => '6.0.3.0',
'pretty_version' => 'v6.2.5',
'version' => '6.2.5.0',
'reference' => 'b2dac0fa27b1ac0f9c0c0b23b43977f12308d0b0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/string',
'aliases' => array(),
'reference' => '522144f0c4c004c80d56fa47e40e17028e2eefc2',
'dev_requirement' => false,
),
'symfony/translation' => array(
'pretty_version' => 'v6.0.6',
'version' => '6.0.6.0',
'pretty_version' => 'v6.2.5',
'version' => '6.2.5.0',
'reference' => '60556925a703cfbc1581cde3b3f35b0bb0ea904c',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/translation',
'aliases' => array(),
'reference' => 'f6639cb9b5e0c57fe31e3263b900a77eedb0c908',
'dev_requirement' => false,
),
'symfony/translation-contracts' => array(
'pretty_version' => 'v3.0.0',
'version' => '3.0.0.0',
'pretty_version' => 'v3.2.0',
'version' => '3.2.0.0',
'reference' => '68cce71402305a015f8c1589bfada1280dc64fe7',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/translation-contracts',
'aliases' => array(),
'reference' => '1b6ea5a7442af5a12dba3dbd6d71034b5b234e77',
'dev_requirement' => false,
),
'symfony/translation-implementation' => array(
@ -247,10 +265,10 @@
'voku/portable-ascii' => array(
'pretty_version' => '2.0.1',
'version' => '2.0.1.0',
'reference' => 'b56450eed252f6801410d810c8e1727224ae0743',
'type' => 'library',
'install_path' => __DIR__ . '/../voku/portable-ascii',
'aliases' => array(),
'reference' => 'b56450eed252f6801410d810c8e1727224ae0743',
'dev_requirement' => false,
),
),

View file

@ -4,8 +4,8 @@
$issues = array();
if (!(PHP_VERSION_ID >= 80002)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.0.2". You are running ' . PHP_VERSION . '.';
if (!(PHP_VERSION_ID >= 80100)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {

View file

@ -16,12 +16,12 @@
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^8.2",
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"phpstan/phpstan-strict-rules": "^0.12",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
"vimeo/psalm": "^4.10"
"doctrine/coding-standard": "^10",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpstan/phpstan-strict-rules": "^1.3",
"phpunit/phpunit": "^8.5 || ^9.5",
"vimeo/psalm": "^4.25"
},
"autoload": {
"psr-4": {
@ -32,5 +32,10 @@
"psr-4": {
"Doctrine\\Tests\\Inflector\\": "tests/Doctrine/Tests/Inflector"
}
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
}
}

View file

@ -11,9 +11,7 @@ use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('(s)tatuses$'), '\1\2tatus');
@ -56,12 +54,12 @@ class Inflectible
yield new Transformation(new Pattern('(f)eet$'), '\1oot');
yield new Transformation(new Pattern('(n)ews$'), '\1\2ews');
yield new Transformation(new Pattern('eaus$'), 'eau');
yield new Transformation(new Pattern('^tights$'), 'tights');
yield new Transformation(new Pattern('^shorts$'), 'shorts');
yield new Transformation(new Pattern('s$'), '');
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('(s)tatus$'), '\1\2tatuses');
@ -91,14 +89,13 @@ class Inflectible
yield new Transformation(new Pattern('$'), 's');
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('atlas'), new Word('atlases'));
yield new Substitution(new Word('axe'), new Word('axes'));
yield new Substitution(new Word('beef'), new Word('beefs'));
yield new Substitution(new Word('blouse'), new Word('blouses'));
yield new Substitution(new Word('brother'), new Word('brothers'));
yield new Substitution(new Word('cafe'), new Word('cafes'));
yield new Substitution(new Word('chateau'), new Word('chateaux'));
@ -151,6 +148,7 @@ class Inflectible
yield new Substitution(new Word('runner-up'), new Word('runners-up'));
yield new Substitution(new Word('safe'), new Word('safes'));
yield new Substitution(new Word('sex'), new Word('sexes'));
yield new Substitution(new Word('sieve'), new Word('sieves'));
yield new Substitution(new Word('soliloquy'), new Word('soliloquies'));
yield new Substitution(new Word('son-in-law'), new Word('sons-in-law'));
yield new Substitution(new Word('syllabus'), new Word('syllabi'));

View file

@ -8,9 +8,7 @@ use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
@ -30,9 +28,7 @@ final class Uninflected
yield new Pattern('utopia');
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
@ -43,9 +39,7 @@ final class Uninflected
yield new Pattern('media');
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('\w+media');
@ -64,6 +58,7 @@ final class Uninflected
yield new Pattern('butter');
yield new Pattern('cantus');
yield new Pattern('carp');
yield new Pattern('cattle');
yield new Pattern('chassis');
yield new Pattern('clippers');
yield new Pattern('clothing');
@ -111,6 +106,7 @@ final class Uninflected
yield new Pattern('jackanapes');
yield new Pattern('jeans');
yield new Pattern('jedi');
yield new Pattern('kin');
yield new Pattern('kiplingese');
yield new Pattern('knowledge');
yield new Pattern('kongoese');

View file

@ -11,9 +11,7 @@ use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('/(b|cor|ém|gemm|soupir|trav|vant|vitr)aux$/'), '\1ail');
@ -23,9 +21,7 @@ class Inflectible
yield new Transformation(new Pattern('/s$/'), '');
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('/(s|x|z)$/'), '\1');
@ -38,9 +34,7 @@ class Inflectible
yield new Transformation(new Pattern('/$/'), 's');
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('monsieur'), new Word('messieurs'));

View file

@ -8,25 +8,19 @@ use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('');

View file

@ -11,18 +11,14 @@ use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('/re$/i'), 'r');
yield new Transformation(new Pattern('/er$/i'), '');
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('/e$/i'), 'er');
@ -30,9 +26,7 @@ class Inflectible
yield new Transformation(new Pattern('/$/'), 'er');
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('konto'), new Word('konti'));

View file

@ -8,25 +8,19 @@ use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('barn');

View file

@ -11,9 +11,7 @@ use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('/^(g|)ases$/i'), '\1ás');
@ -34,9 +32,7 @@ class Inflectible
yield new Transformation(new Pattern('/([^ê])s$/i'), '\1');
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('/^(alem|c|p)ao$/i'), '\1aes');
@ -58,9 +54,7 @@ class Inflectible
yield new Transformation(new Pattern('/$/'), 's');
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('abdomen'), new Word('abdomens'));

View file

@ -8,25 +8,19 @@ use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('tórax');

View file

@ -11,9 +11,7 @@ use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('/ereses$/'), 'erés');
@ -23,9 +21,7 @@ class Inflectible
yield new Transformation(new Pattern('/s$/'), '');
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('/ú([sn])$/i'), 'u\1es');
@ -39,9 +35,7 @@ class Inflectible
yield new Transformation(new Pattern('/$/'), 's');
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('el'), new Word('los'));

View file

@ -8,25 +8,19 @@ use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('lunes');

View file

@ -11,26 +11,20 @@ use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('/l[ae]r$/i'), '');
}
/**
* @return Transformation[]
*/
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('/([eöiü][^aoıueöiü]{0,6})$/u'), '\1ler');
yield new Transformation(new Pattern('/([aoıu][^aoıueöiü]{0,6})$/u'), '\1lar');
}
/**
* @return Substitution[]
*/
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('ben'), new Word('biz'));

View file

@ -8,25 +8,19 @@ use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/**
* @return Pattern[]
*/
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('lunes');

View file

@ -1,13 +0,0 @@
includes:
- vendor/phpstan/phpstan-phpunit/extension.neon
- vendor/phpstan/phpstan-phpunit/rules.neon
- vendor/phpstan/phpstan-strict-rules/rules.neon
parameters:
level: 7
paths:
- lib
- tests
excludes_analyse:
- %rootDir%/../../../tests/Doctrine/Tests/Common/*

View file

@ -1,15 +0,0 @@
<?xml version="1.0"?>
<psalm
errorLevel="7"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
>
<projectFiles>
<directory name="lib/Doctrine/Inflector" />
<ignoreFiles>
<directory name="vendor" />
</ignoreFiles>
</projectFiles>
</psalm>

View file

@ -2,6 +2,7 @@
namespace Illuminate\Support;
use ArgumentCountError;
use ArrayAccess;
use Illuminate\Support\Traits\Macroable;
use InvalidArgumentException;
@ -25,7 +26,7 @@ class Arr
* Add an element to an array using "dot" notation if it doesn't exist.
*
* @param array $array
* @param string $key
* @param string|int|float $key
* @param mixed $value
* @return array
*/
@ -142,7 +143,7 @@ class Arr
* Get all of the given array except for a specified array of keys.
*
* @param array $array
* @param array|string $keys
* @param array|string|int|float $keys
* @return array
*/
public static function except($array, $keys)
@ -169,6 +170,10 @@ class Arr
return $array->offsetExists($key);
}
if (is_float($key)) {
$key = (string) $key;
}
return array_key_exists($key, $array);
}
@ -252,7 +257,7 @@ class Arr
* Remove one or many array items from a given array using "dot" notation.
*
* @param array $array
* @param array|string $keys
* @param array|string|int|float $keys
* @return void
*/
public static function forget(&$array, $keys)
@ -281,7 +286,7 @@ class Arr
while (count($parts) > 1) {
$part = array_shift($parts);
if (isset($array[$part]) && is_array($array[$part])) {
if (isset($array[$part]) && static::accessible($array[$part])) {
$array = &$array[$part];
} else {
continue 2;
@ -423,11 +428,38 @@ class Arr
return ! self::isAssoc($array);
}
/**
* Join all items using a string. The final items can use a separate glue string.
*
* @param array $array
* @param string $glue
* @param string $finalGlue
* @return string
*/
public static function join($array, $glue, $finalGlue = '')
{
if ($finalGlue === '') {
return implode($glue, $array);
}
if (count($array) === 0) {
return '';
}
if (count($array) === 1) {
return end($array);
}
$finalItem = array_pop($array);
return implode($glue, $array).$finalGlue.$finalItem;
}
/**
* Key an associative array by a field or using a callback.
*
* @param array $array
* @param callable|array|string
* @param callable|array|string $keyBy
* @return array
*/
public static function keyBy($array, $keyBy)
@ -435,6 +467,20 @@ class Arr
return Collection::make($array)->keyBy($keyBy)->all();
}
/**
* Prepend the key names of an associative array.
*
* @param array $array
* @param string $prependWith
* @return array
*/
public static function prependKeysWith($array, $prependWith)
{
return Collection::make($array)->mapWithKeys(function ($item, $key) use ($prependWith) {
return [$prependWith.$key => $item];
})->all();
}
/**
* Get a subset of the items from the given array.
*
@ -499,6 +545,26 @@ class Arr
return [$value, $key];
}
/**
* Run a map over each of the items in the array.
*
* @param array $array
* @param callable $callback
* @return array
*/
public static function map(array $array, callable $callback)
{
$keys = array_keys($array);
try {
$items = array_map($callback, $array, $keys);
} catch (ArgumentCountError) {
$items = array_map($callback, $array);
}
return array_combine($keys, $items);
}
/**
* Push an item onto the beginning of an array.
*
@ -522,7 +588,7 @@ class Arr
* Get a value from the array, and remove it.
*
* @param array $array
* @param string $key
* @param string|int $key
* @param mixed $default
* @return mixed
*/
@ -551,7 +617,7 @@ class Arr
*
* @param array $array
* @param int|null $number
* @param bool|false $preserveKeys
* @param bool $preserveKeys
* @return mixed
*
* @throws \InvalidArgumentException
@ -599,7 +665,7 @@ class Arr
* If no key is given to the method, the entire array will be replaced.
*
* @param array $array
* @param string|null $key
* @param string|int|null $key
* @param mixed $value
* @return array
*/
@ -665,6 +731,18 @@ class Arr
return Collection::make($array)->sortBy($callback)->all();
}
/**
* Sort the array in descending order using the given callback or "dot" notation.
*
* @param array $array
* @param callable|array|string|null $callback
* @return array
*/
public static function sortDesc($array, $callback = null)
{
return Collection::make($array)->sortByDesc($callback)->all();
}
/**
* Recursively sort an array by keys and values.
*
@ -717,6 +795,29 @@ class Arr
return implode(' ', $classes);
}
/**
* Conditionally compile styles from an array into a style list.
*
* @param array $array
* @return string
*/
public static function toCssStyles($array)
{
$styleList = static::wrap($array);
$styles = [];
foreach ($styleList as $class => $constraint) {
if (is_numeric($class)) {
$styles[] = Str::finish($constraint, ';');
} elseif ($constraint) {
$styles[] = Str::finish($class, ';');
}
}
return implode(' ', $styles);
}
/**
* Filter the array using the given callback.
*
@ -737,9 +838,7 @@ class Arr
*/
public static function whereNotNull($array)
{
return static::where($array, function ($value) {
return ! is_null($value);
});
return static::where($array, fn ($value) => ! is_null($value));
}
/**

View file

@ -84,11 +84,9 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
{
$callback = $this->valueRetriever($callback);
$items = $this->map(function ($value) use ($callback) {
return $callback($value);
})->filter(function ($value) {
return ! is_null($value);
});
$items = $this
->map(fn ($value) => $callback($value))
->filter(fn ($value) => ! is_null($value));
if ($count = $items->count()) {
return $items->sum() / $count;
@ -104,9 +102,8 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
public function median($key = null)
{
$values = (isset($key) ? $this->pluck($key) : $this)
->filter(function ($item) {
return ! is_null($item);
})->sort()->values();
->filter(fn ($item) => ! is_null($item))
->sort()->values();
$count = $values->count();
@ -141,17 +138,14 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
$counts = new static;
$collection->each(function ($value) use ($counts) {
$counts[$value] = isset($counts[$value]) ? $counts[$value] + 1 : 1;
});
$collection->each(fn ($value) => $counts[$value] = isset($counts[$value]) ? $counts[$value] + 1 : 1);
$sorted = $counts->sort();
$highestValue = $sorted->last();
return $sorted->filter(function ($value) use ($highestValue) {
return $value == $highestValue;
})->sort()->keys()->all();
return $sorted->filter(fn ($value) => $value == $highestValue)
->sort()->keys()->all();
}
/**
@ -187,6 +181,26 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
return $this->contains($this->operatorForWhere(...func_get_args()));
}
/**
* Determine if an item exists, using strict comparison.
*
* @param (callable(TValue): bool)|TValue|array-key $key
* @param TValue|null $value
* @return bool
*/
public function containsStrict($key, $value = null)
{
if (func_num_args() === 2) {
return $this->contains(fn ($item) => data_get($item, $key) === $value);
}
if ($this->useAsCallable($key)) {
return ! is_null($this->first($key));
}
return in_array($key, $this->items, true);
}
/**
* Determine if an item is not contained in the collection.
*
@ -333,14 +347,10 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
protected function duplicateComparator($strict)
{
if ($strict) {
return function ($a, $b) {
return $a === $b;
};
return fn ($a, $b) => $a === $b;
}
return function ($a, $b) {
return $a == $b;
};
return fn ($a, $b) => $a == $b;
}
/**
@ -488,7 +498,11 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
}
foreach ($groupKeys as $groupKey) {
$groupKey = is_bool($groupKey) ? (int) $groupKey : $groupKey;
$groupKey = match (true) {
is_bool($groupKey) => (int) $groupKey,
$groupKey instanceof \Stringable => (string) $groupKey,
default => $groupKey,
};
if (! array_key_exists($groupKey, $results)) {
$results[$groupKey] = new static;
@ -577,12 +591,16 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
/**
* Concatenate values of a given key as a string.
*
* @param string $value
* @param callable|string $value
* @param string|null $glue
* @return string
*/
public function implode($value, $glue = null)
{
if ($this->useAsCallable($value)) {
return implode($glue ?? '', $this->map($value)->all());
}
$first = $this->first();
if (is_array($first) || (is_object($first) && ! $first instanceof Stringable)) {
@ -603,6 +621,41 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
return new static(array_intersect($this->items, $this->getArrayableItems($items)));
}
/**
* Intersect the collection with the given items, using the callback.
*
* @param \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TValue> $items
* @param callable(TValue, TValue): int $callback
* @return static
*/
public function intersectUsing($items, callable $callback)
{
return new static(array_uintersect($this->items, $this->getArrayableItems($items), $callback));
}
/**
* Intersect the collection with the given items with additional index check.
*
* @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue> $items
* @return static
*/
public function intersectAssoc($items)
{
return new static(array_intersect_assoc($this->items, $this->getArrayableItems($items)));
}
/**
* Intersect the collection with the given items with additional index check, using the callback.
*
* @param \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TValue> $items
* @param callable(TValue, TValue): int $callback
* @return static
*/
public function intersectAssocUsing($items, callable $callback)
{
return new static(array_intersect_uassoc($this->items, $this->getArrayableItems($items), $callback));
}
/**
* Intersect the collection with the given items by key.
*
@ -693,9 +746,9 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
/**
* Get the values of a given key.
*
* @param string|array<array-key, string> $value
* @param string|int|array<array-key, string> $value
* @param string|null $key
* @return static<int, mixed>
* @return static<array-key, mixed>
*/
public function pluck($value, $key = null)
{
@ -712,11 +765,7 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
*/
public function map(callable $callback)
{
$keys = array_keys($this->items);
$items = array_map($callback, $this->items, $keys);
return new static(array_combine($keys, $items));
return new static(Arr::map($this->items, $callback));
}
/**
@ -807,7 +856,7 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
* @template TCombineValue
*
* @param \Illuminate\Contracts\Support\Arrayable<array-key, TCombineValue>|iterable<array-key, TCombineValue> $values
* @return static<TKey, TCombineValue>
* @return static<TValue, TCombineValue>
*/
public function combine($values)
{
@ -838,8 +887,8 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
$position = 0;
foreach ($this->items as $item) {
if ($position % $step === $offset) {
foreach ($this->slice($offset)->items as $item) {
if ($position % $step === 0) {
$new[] = $item;
}
@ -852,7 +901,7 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
/**
* Get the items with the specified keys.
*
* @param \Illuminate\Support\Enumerable<array-key, TKey>|array<array-key, TKey> $keys
* @param \Illuminate\Support\Enumerable<array-key, TKey>|array<array-key, TKey>|string|null $keys
* @return static
*/
public function only($keys)
@ -974,7 +1023,7 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
/**
* Get one or a specified number of items randomly from the collection.
*
* @param int|null $number
* @param (callable(self<TKey, TValue>): int)|int|null $number
* @return static<int, TValue>|TValue
*
* @throws \InvalidArgumentException
@ -985,6 +1034,10 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
return Arr::random($this->items);
}
if (is_callable($number)) {
return new static(Arr::random($this->items, $number($this)));
}
return new static(Arr::random($this->items, $number));
}
@ -1317,7 +1370,7 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
/**
* Sort the collection using the given callback.
*
* @param array<array-key, (callable(TValue, TKey): mixed)|array<array-key, string>|(callable(TValue, TKey): mixed)|string $callback
* @param array<array-key, (callable(TValue, TValue): mixed)|(callable(TValue, TKey): mixed)|string|array{string, string}>|(callable(TValue, TKey): mixed)|string $callback
* @param int $options
* @param bool $descending
* @return static
@ -1355,14 +1408,14 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
/**
* Sort the collection using multiple comparisons.
*
* @param array<array-key, (callable(TValue, TKey): mixed)|array<array-key, string> $comparisons
* @param array<array-key, (callable(TValue, TValue): mixed)|(callable(TValue, TKey): mixed)|string|array{string, string}> $comparisons
* @return static
*/
protected function sortByMany(array $comparisons = [])
{
$items = $this->items;
usort($items, function ($a, $b) use ($comparisons) {
uasort($items, function ($a, $b) use ($comparisons) {
foreach ($comparisons as $comparison) {
$comparison = Arr::wrap($comparison);
@ -1397,7 +1450,7 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
/**
* Sort the collection in descending order using the given callback.
*
* @param array<array-key, (callable(TValue, TKey): mixed)|array<array-key, string>|(callable(TValue, TKey): mixed)|string $callback
* @param array<array-key, (callable(TValue, TValue): mixed)|(callable(TValue, TKey): mixed)|string|array{string, string}>|(callable(TValue, TKey): mixed)|string $callback
* @param int $options
* @return static
*/
@ -1574,13 +1627,9 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
*/
public function zip($items)
{
$arrayableItems = array_map(function ($items) {
return $this->getArrayableItems($items);
}, func_get_args());
$arrayableItems = array_map(fn ($items) => $this->getArrayableItems($items), func_get_args());
$params = array_merge([function () {
return new static(func_get_args());
}, $this->items], $arrayableItems);
$params = array_merge([fn () => new static(func_get_args()), $this->items], $arrayableItems);
return new static(array_map(...$params));
}
@ -1622,7 +1671,7 @@ class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerabl
/**
* Count the number of items in the collection by a field or using a callback.
*
* @param (callable(TValue, TKey): mixed)|string|null $countBy
* @param (callable(TValue, TKey): array-key)|string|null $countBy
* @return static<array-key, int>
*/
public function countBy($countBy = null)

View file

@ -51,11 +51,10 @@ interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable,
/**
* Wrap the given value in a collection if applicable.
*
* @template TWrapKey of array-key
* @template TWrapValue
*
* @param iterable<TWrapKey, TWrapValue> $value
* @return static<TWrapKey, TWrapValue>
* @param iterable<array-key, TWrapValue>|TWrapValue $value
* @return static<array-key, TWrapValue>
*/
public static function wrap($value);
@ -460,8 +459,10 @@ interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable,
/**
* Filter the items, removing any items that don't match the given type(s).
*
* @param class-string|array<array-key, class-string> $type
* @return static
* @template TWhereInstanceOf
*
* @param class-string<TWhereInstanceOf>|array<array-key, class-string<TWhereInstanceOf>> $type
* @return static<TKey, TWhereInstanceOf>
*/
public function whereInstanceOf($type);
@ -678,8 +679,11 @@ interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable,
/**
* Map a collection and flatten the result by a single level.
*
* @param callable(TValue, TKey): mixed $callback
* @return static<int, mixed>
* @template TFlatMapKey of array-key
* @template TFlatMapValue
*
* @param callable(TValue, TKey): (\Illuminate\Support\Collection<TFlatMapKey, TFlatMapValue>|array<TFlatMapKey, TFlatMapValue>) $callback
* @return static<TFlatMapKey, TFlatMapValue>
*/
public function flatMap(callable $callback);
@ -717,7 +721,7 @@ interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable,
* @template TCombineValue
*
* @param \Illuminate\Contracts\Support\Arrayable<array-key, TCombineValue>|iterable<array-key, TCombineValue> $values
* @return static<TKey, TCombineValue>
* @return static<TValue, TCombineValue>
*/
public function combine($values);
@ -733,7 +737,7 @@ interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable,
* Get the min value of a given key.
*
* @param (callable(TValue):mixed)|string|null $callback
* @return TValue
* @return mixed
*/
public function min($callback = null);
@ -741,7 +745,7 @@ interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable,
* Get the max value of a given key.
*
* @param (callable(TValue):mixed)|string|null $callback
* @return TValue
* @return mixed
*/
public function max($callback = null);
@ -757,7 +761,7 @@ interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable,
/**
* Get the items with the specified keys.
*
* @param \Illuminate\Support\Enumerable<array-key, TKey>|array<array-key, TKey> $keys
* @param \Illuminate\Support\Enumerable<array-key, TKey>|array<array-key, TKey>|string $keys
* @return static
*/
public function only($keys);
@ -980,7 +984,7 @@ interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable,
/**
* Sort the collection using the given callback.
*
* @param array<array-key, (callable(TValue, TKey): mixed)|array<array-key, string>|(callable(TValue, TKey): mixed)|string $callback
* @param array<array-key, (callable(TValue, TValue): mixed)|(callable(TValue, TKey): mixed)|string|array{string, string}>|(callable(TValue, TKey): mixed)|string $callback
* @param int $options
* @param bool $descending
* @return static
@ -990,7 +994,7 @@ interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable,
/**
* Sort the collection in descending order using the given callback.
*
* @param array<array-key, (callable(TValue, TKey): mixed)|array<array-key, string>|(callable(TValue, TKey): mixed)|string $callback
* @param array<array-key, (callable(TValue, TValue): mixed)|(callable(TValue, TKey): mixed)|string|array{string, string}>|(callable(TValue, TKey): mixed)|string $callback
* @param int $options
* @return static
*/
@ -1099,7 +1103,7 @@ interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable,
/**
* Create a collection of all elements that do not pass a given truth test.
*
* @param (callable(TValue, TKey): bool)|bool $callback
* @param (callable(TValue, TKey): bool)|bool|TValue $callback
* @return static
*/
public function reject($callback = true);
@ -1163,10 +1167,10 @@ interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable,
/**
* Count the number of items in the collection by a field or using a callback.
*
* @param (callable(TValue, TKey): mixed)|string|null $countBy
* @param (callable(TValue, TKey): array-key)|string|null $countBy
* @return static<array-key, int>
*/
public function countBy($callback = null);
public function countBy($countBy = null);
/**
* Zip the collection together with one or more arrays.
@ -1198,9 +1202,9 @@ interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable,
/**
* Convert the object into something JSON serializable.
*
* @return array<TKey, mixed>
* @return mixed
*/
public function jsonSerialize(): array;
public function jsonSerialize(): mixed;
/**
* Get the collection of items as JSON.

View file

@ -236,6 +236,32 @@ class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable
return $this->contains($this->operatorForWhere(...func_get_args()));
}
/**
* Determine if an item exists, using strict comparison.
*
* @param (callable(TValue): bool)|TValue|array-key $key
* @param TValue|null $value
* @return bool
*/
public function containsStrict($key, $value = null)
{
if (func_num_args() === 2) {
return $this->contains(fn ($item) => data_get($item, $key) === $value);
}
if ($this->useAsCallable($key)) {
return ! is_null($this->first($key));
}
foreach ($this as $item) {
if ($item === $key) {
return true;
}
}
return false;
}
/**
* Determine if an item is not contained in the enumerable.
*
@ -266,7 +292,7 @@ class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable
/**
* Count the number of items in the collection by a field or using a callback.
*
* @param (callable(TValue, TKey): mixed)|string|null $countBy
* @param (callable(TValue, TKey): array-key)|string|null $countBy
* @return static<array-key, int>
*/
public function countBy($countBy = null)
@ -398,15 +424,13 @@ class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable
/**
* Run a filter over each of the items.
*
* @param (callable(TValue): bool)|null $callback
* @param (callable(TValue, TKey): bool)|null $callback
* @return static
*/
public function filter(callable $callback = null)
{
if (is_null($callback)) {
$callback = function ($value) {
return (bool) $value;
};
$callback = fn ($value) => (bool) $value;
}
return new static(function () use ($callback) {
@ -586,7 +610,7 @@ class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable
/**
* Concatenate values of a given key as a string.
*
* @param string $value
* @param callable|string $value
* @param string|null $glue
* @return string
*/
@ -606,6 +630,41 @@ class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable
return $this->passthru('intersect', func_get_args());
}
/**
* Intersect the collection with the given items, using the callback.
*
* @param \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TValue> $items
* @param callable(TValue, TValue): int $callback
* @return static
*/
public function intersectUsing()
{
return $this->passthru('intersectUsing', func_get_args());
}
/**
* Intersect the collection with the given items with additional index check.
*
* @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue> $items
* @return static
*/
public function intersectAssoc($items)
{
return $this->passthru('intersectAssoc', func_get_args());
}
/**
* Intersect the collection with the given items with additional index check, using the callback.
*
* @param \Illuminate\Contracts\Support\Arrayable<array-key, TValue>|iterable<array-key, TValue> $items
* @param callable(TValue, TValue): int $callback
* @return static
*/
public function intersectAssocUsing($items, callable $callback)
{
return $this->passthru('intersectAssocUsing', func_get_args());
}
/**
* Intersect the collection with the given items by key.
*
@ -798,7 +857,7 @@ class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable
* @template TCombineValue
*
* @param \IteratorAggregate<array-key, TCombineValue>|array<array-key, TCombineValue>|(callable(): \Generator<array-key, TCombineValue>) $values
* @return static<TKey, TCombineValue>
* @return static<TValue, TCombineValue>
*/
public function combine($values)
{
@ -848,8 +907,8 @@ class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable
return new static(function () use ($step, $offset) {
$position = 0;
foreach ($this as $item) {
if ($position % $step === $offset) {
foreach ($this->slice($offset) as $item) {
if ($position % $step === 0) {
yield $item;
}
@ -861,7 +920,7 @@ class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable
/**
* Get the items with the specified keys.
*
* @param \Illuminate\Support\Enumerable<array-key, TKey>|array<array-key, TKey> $keys
* @param \Illuminate\Support\Enumerable<array-key, TKey>|array<array-key, TKey>|string $keys
* @return static
*/
public function only($keys)
@ -1296,7 +1355,7 @@ class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable
/**
* Sort the collection using the given callback.
*
* @param array<array-key, (callable(TValue, TKey): mixed)|array<array-key, string>|(callable(TValue, TKey): mixed)|string $callback
* @param array<array-key, (callable(TValue, TValue): mixed)|(callable(TValue, TKey): mixed)|string|array{string, string}>|(callable(TValue, TKey): mixed)|string $callback
* @param int $options
* @param bool $descending
* @return static
@ -1309,7 +1368,7 @@ class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable
/**
* Sort the collection in descending order using the given callback.
*
* @param array<array-key, (callable(TValue, TKey): mixed)|array<array-key, string>|(callable(TValue, TKey): mixed)|string $callback
* @param array<array-key, (callable(TValue, TValue): mixed)|(callable(TValue, TKey): mixed)|string|array{string, string}>|(callable(TValue, TKey): mixed)|string $callback
* @param int $options
* @return static
*/
@ -1439,9 +1498,7 @@ class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable
/** @var callable(TValue, TKey): bool $callback */
$callback = $this->useAsCallable($value) ? $value : $this->equality($value);
return $this->takeUntil(function ($item, $key) use ($callback) {
return ! $callback($item, $key);
});
return $this->takeUntil(fn ($item, $key) => ! $callback($item, $key));
}
/**
@ -1610,7 +1667,15 @@ class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable
return new ArrayIterator($source);
}
return $source();
if (is_callable($source)) {
$maybeTraversable = $source();
return $maybeTraversable instanceof Traversable
? $maybeTraversable
: new ArrayIterator(Arr::wrap($maybeTraversable));
}
return new ArrayIterator((array) $source);
}
/**

View file

@ -15,6 +15,7 @@ use JsonSerializable;
use Symfony\Component\VarDumper\VarDumper;
use Traversable;
use UnexpectedValueException;
use UnitEnum;
/**
* @template TKey of array-key
@ -113,11 +114,10 @@ trait EnumeratesValues
/**
* Wrap the given value in a collection if applicable.
*
* @template TWrapKey of array-key
* @template TWrapValue
*
* @param iterable<TWrapKey, TWrapValue> $value
* @return static<TWrapKey, TWrapValue>
* @param iterable<array-key, TWrapValue>|TWrapValue $value
* @return static<array-key, TWrapValue>
*/
public static function wrap($value)
{
@ -194,34 +194,6 @@ trait EnumeratesValues
return $this->contains(...func_get_args());
}
/**
* Determine if an item exists, using strict comparison.
*
* @param (callable(TValue): bool)|TValue|array-key $key
* @param TValue|null $value
* @return bool
*/
public function containsStrict($key, $value = null)
{
if (func_num_args() === 2) {
return $this->contains(function ($item) use ($key, $value) {
return data_get($item, $key) === $value;
});
}
if ($this->useAsCallable($key)) {
return ! is_null($this->first($key));
}
foreach ($this as $item) {
if ($item === $key) {
return true;
}
}
return false;
}
/**
* Dump the items and end the script.
*
@ -311,7 +283,7 @@ trait EnumeratesValues
/**
* Get the first item by the given key value pair.
*
* @param string $key
* @param callable|string $key
* @param mixed $operator
* @param mixed $value
* @return TValue|null
@ -321,6 +293,22 @@ trait EnumeratesValues
return $this->first($this->operatorForWhere(...func_get_args()));
}
/**
* Get a single key's value from the first matching item in the collection.
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public function value($key, $default = null)
{
if ($value = $this->firstWhere($key)) {
return data_get($value, $key, $default);
}
return value($default);
}
/**
* Determine if the collection is not empty.
*
@ -369,8 +357,11 @@ trait EnumeratesValues
/**
* Map a collection and flatten the result by a single level.
*
* @param callable(TValue, TKey): mixed $callback
* @return static<int, mixed>
* @template TFlatMapKey of array-key
* @template TFlatMapValue
*
* @param callable(TValue, TKey): (\Illuminate\Support\Collection<TFlatMapKey, TFlatMapValue>|array<TFlatMapKey, TFlatMapValue>) $callback
* @return static<TFlatMapKey, TFlatMapValue>
*/
public function flatMap(callable $callback)
{
@ -387,43 +378,35 @@ trait EnumeratesValues
*/
public function mapInto($class)
{
return $this->map(function ($value, $key) use ($class) {
return new $class($value, $key);
});
return $this->map(fn ($value, $key) => new $class($value, $key));
}
/**
* Get the min value of a given key.
*
* @param (callable(TValue):mixed)|string|null $callback
* @return TValue
* @return mixed
*/
public function min($callback = null)
{
$callback = $this->valueRetriever($callback);
return $this->map(function ($value) use ($callback) {
return $callback($value);
})->filter(function ($value) {
return ! is_null($value);
})->reduce(function ($result, $value) {
return is_null($result) || $value < $result ? $value : $result;
});
return $this->map(fn ($value) => $callback($value))
->filter(fn ($value) => ! is_null($value))
->reduce(fn ($result, $value) => is_null($result) || $value < $result ? $value : $result);
}
/**
* Get the max value of a given key.
*
* @param (callable(TValue):mixed)|string|null $callback
* @return TValue
* @return mixed
*/
public function max($callback = null)
{
$callback = $this->valueRetriever($callback);
return $this->filter(function ($value) {
return ! is_null($value);
})->reduce(function ($result, $item) use ($callback) {
return $this->filter(fn ($value) => ! is_null($value))->reduce(function ($result, $item) use ($callback) {
$value = $callback($item);
return is_null($result) || $value > $result ? $value : $result;
@ -484,9 +467,7 @@ trait EnumeratesValues
? $this->identity()
: $this->valueRetriever($callback);
return $this->reduce(function ($result, $item) use ($callback) {
return $result + $callback($item);
}, 0);
return $this->reduce(fn ($result, $item) => $result + $callback($item), 0);
}
/**
@ -548,7 +529,7 @@ trait EnumeratesValues
/**
* Filter items by the given key value pair.
*
* @param string $key
* @param callable|string $key
* @param mixed $operator
* @param mixed $value
* @return static
@ -604,9 +585,7 @@ trait EnumeratesValues
{
$values = $this->getArrayableItems($values);
return $this->filter(function ($item) use ($key, $values, $strict) {
return in_array(data_get($item, $key), $values, $strict);
});
return $this->filter(fn ($item) => in_array(data_get($item, $key), $values, $strict));
}
/**
@ -642,9 +621,9 @@ trait EnumeratesValues
*/
public function whereNotBetween($key, $values)
{
return $this->filter(function ($item) use ($key, $values) {
return data_get($item, $key) < reset($values) || data_get($item, $key) > end($values);
});
return $this->filter(
fn ($item) => data_get($item, $key) < reset($values) || data_get($item, $key) > end($values)
);
}
/**
@ -659,9 +638,7 @@ trait EnumeratesValues
{
$values = $this->getArrayableItems($values);
return $this->reject(function ($item) use ($key, $values, $strict) {
return in_array(data_get($item, $key), $values, $strict);
});
return $this->reject(fn ($item) => in_array(data_get($item, $key), $values, $strict));
}
/**
@ -679,8 +656,10 @@ trait EnumeratesValues
/**
* Filter the items, removing any items that don't match the given type(s).
*
* @param class-string|array<array-key, class-string> $type
* @return static
* @template TWhereInstanceOf
*
* @param class-string<TWhereInstanceOf>|array<array-key, class-string<TWhereInstanceOf>> $type
* @return static<TKey, TWhereInstanceOf>
*/
public function whereInstanceOf($type)
{
@ -732,9 +711,7 @@ trait EnumeratesValues
public function pipeThrough($callbacks)
{
return Collection::make($callbacks)->reduce(
function ($carry, $callback) {
return $callback($carry);
},
fn ($carry, $callback) => $callback($carry),
$this,
);
}
@ -778,7 +755,7 @@ trait EnumeratesValues
if (! is_array($result)) {
throw new UnexpectedValueException(sprintf(
"%s::reduceMany expects reducer to return an array, but got a '%s' instead.",
"%s::reduceSpread expects reducer to return an array, but got a '%s' instead.",
class_basename(static::class), gettype($result)
));
}
@ -790,7 +767,7 @@ trait EnumeratesValues
/**
* Create a collection of all elements that do not pass a given truth test.
*
* @param (callable(TValue, TKey): bool)|bool $callback
* @param (callable(TValue, TKey): bool)|bool|TValue $callback
* @return static
*/
public function reject($callback = true)
@ -867,9 +844,7 @@ trait EnumeratesValues
*/
public function toArray()
{
return $this->map(function ($value) {
return $value instanceof Arrayable ? $value->toArray() : $value;
})->all();
return $this->map(fn ($value) => $value instanceof Arrayable ? $value->toArray() : $value)->all();
}
/**
@ -981,12 +956,14 @@ trait EnumeratesValues
return $items->all();
} elseif ($items instanceof Arrayable) {
return $items->toArray();
} elseif ($items instanceof Traversable) {
return iterator_to_array($items);
} elseif ($items instanceof Jsonable) {
return json_decode($items->toJson(), true);
} elseif ($items instanceof JsonSerializable) {
return (array) $items->jsonSerialize();
} elseif ($items instanceof Traversable) {
return iterator_to_array($items);
} elseif ($items instanceof UnitEnum) {
return [$items];
}
return (array) $items;
@ -995,13 +972,17 @@ trait EnumeratesValues
/**
* Get an operator checker callback.
*
* @param string $key
* @param callable|string $key
* @param string|null $operator
* @param mixed $value
* @return \Closure
*/
protected function operatorForWhere($key, $operator = null, $value = null)
{
if ($this->useAsCallable($key)) {
return $key;
}
if (func_num_args() === 1) {
$value = true;
@ -1037,6 +1018,7 @@ trait EnumeratesValues
case '>=': return $retrieved >= $value;
case '===': return $retrieved === $value;
case '!==': return $retrieved !== $value;
case '<=>': return $retrieved <=> $value;
}
};
}
@ -1064,9 +1046,7 @@ trait EnumeratesValues
return $value;
}
return function ($item) use ($value) {
return data_get($item, $value);
};
return fn ($item) => data_get($item, $value);
}
/**
@ -1077,9 +1057,7 @@ trait EnumeratesValues
*/
protected function equality($value)
{
return function ($item) use ($value) {
return $item === $value;
};
return fn ($item) => $item === $value;
}
/**
@ -1090,9 +1068,7 @@ trait EnumeratesValues
*/
protected function negate(Closure $callback)
{
return function (...$params) use ($callback) {
return ! $callback(...$params);
};
return fn (...$params) => ! $callback(...$params);
}
/**
@ -1102,8 +1078,6 @@ trait EnumeratesValues
*/
protected function identity()
{
return function ($value) {
return $value;
};
return fn ($value) => $value;
}
}

View file

@ -13,7 +13,7 @@ if (! function_exists('collect')) {
* @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>|null $value
* @return \Illuminate\Support\Collection<TKey, TValue>
*/
function collect($value = null)
function collect($value = [])
{
return new Collection($value);
}
@ -180,6 +180,7 @@ if (! function_exists('value')) {
* Return the default value of the given value.
*
* @param mixed $value
* @param mixed ...$args
* @return mixed
*/
function value($value, ...$args)

View file

@ -18,17 +18,54 @@ class HigherOrderWhenProxy
*/
protected $condition;
/**
* Indicates whether the proxy has a condition.
*
* @var bool
*/
protected $hasCondition = false;
/**
* Determine whether the condition should be negated.
*
* @var bool
*/
protected $negateConditionOnCapture;
/**
* Create a new proxy instance.
*
* @param mixed $target
* @param bool $condition
* @return void
*/
public function __construct($target, $condition)
public function __construct($target)
{
$this->target = $target;
$this->condition = $condition;
}
/**
* Set the condition on the proxy.
*
* @param bool $condition
* @return $this
*/
public function condition($condition)
{
[$this->condition, $this->hasCondition] = [$condition, true];
return $this;
}
/**
* Indicate that the condition should be negated.
*
* @return $this
*/
public function negateConditionOnCapture()
{
$this->negateConditionOnCapture = true;
return $this;
}
/**
@ -39,6 +76,12 @@ class HigherOrderWhenProxy
*/
public function __get($key)
{
if (! $this->hasCondition) {
$condition = $this->target->{$key};
return $this->condition($this->negateConditionOnCapture ? ! $condition : $condition);
}
return $this->condition
? $this->target->{$key}
: $this->target;
@ -53,6 +96,12 @@ class HigherOrderWhenProxy
*/
public function __call($method, $parameters)
{
if (! $this->hasCondition) {
$condition = $this->target->{$method}(...$parameters);
return $this->condition($this->negateConditionOnCapture ? ! $condition : $condition);
}
return $this->condition
? $this->target->{$method}(...$parameters)
: $this->target;

View file

@ -13,17 +13,21 @@ trait Conditionable
* @template TWhenParameter
* @template TWhenReturnType
*
* @param (\Closure($this): TWhenParameter)|TWhenParameter $value
* @param (\Closure($this): TWhenParameter)|TWhenParameter|null $value
* @param (callable($this, TWhenParameter): TWhenReturnType)|null $callback
* @param (callable($this, TWhenParameter): TWhenReturnType)|null $default
* @return $this|TWhenReturnType
*/
public function when($value, callable $callback = null, callable $default = null)
public function when($value = null, callable $callback = null, callable $default = null)
{
$value = $value instanceof Closure ? $value($this) : $value;
if (! $callback) {
return new HigherOrderWhenProxy($this, $value);
if (func_num_args() === 0) {
return new HigherOrderWhenProxy($this);
}
if (func_num_args() === 1) {
return (new HigherOrderWhenProxy($this))->condition($value);
}
if ($value) {
@ -41,17 +45,21 @@ trait Conditionable
* @template TUnlessParameter
* @template TUnlessReturnType
*
* @param (\Closure($this): TUnlessParameter)|TUnlessParameter $value
* @param (\Closure($this): TUnlessParameter)|TUnlessParameter|null $value
* @param (callable($this, TUnlessParameter): TUnlessReturnType)|null $callback
* @param (callable($this, TUnlessParameter): TUnlessReturnType)|null $default
* @return $this|TUnlessReturnType
*/
public function unless($value, callable $callback = null, callable $default = null)
public function unless($value = null, callable $callback = null, callable $default = null)
{
$value = $value instanceof Closure ? $value($this) : $value;
if (! $callback) {
return new HigherOrderWhenProxy($this, ! $value);
if (func_num_args() === 0) {
return (new HigherOrderWhenProxy($this))->negateConditionOnCapture();
}
if (func_num_args() === 1) {
return (new HigherOrderWhenProxy($this))->condition(! $value);
}
if (! $value) {

View file

@ -426,9 +426,7 @@ class Container implements ArrayAccess, ContainerContract
public function scopedIf($abstract, $concrete = null)
{
if (! $this->bound($abstract)) {
$this->scopedInstances[] = $abstract;
$this->singleton($abstract, $concrete);
$this->scoped($abstract, $concrete);
}
}
@ -633,9 +631,7 @@ class Container implements ArrayAccess, ContainerContract
*/
public function wrap(Closure $callback, array $parameters = [])
{
return function () use ($callback, $parameters) {
return $this->call($callback, $parameters);
};
return fn () => $this->call($callback, $parameters);
}
/**
@ -650,7 +646,25 @@ class Container implements ArrayAccess, ContainerContract
*/
public function call($callback, array $parameters = [], $defaultMethod = null)
{
return BoundMethod::call($this, $callback, $parameters, $defaultMethod);
$pushedToBuildStack = false;
if (is_array($callback) && ! in_array(
$className = (is_string($callback[0]) ? $callback[0] : get_class($callback[0])),
$this->buildStack,
true
)) {
$this->buildStack[] = $className;
$pushedToBuildStack = true;
}
$result = BoundMethod::call($this, $callback, $parameters, $defaultMethod);
if ($pushedToBuildStack) {
array_pop($this->buildStack);
}
return $result;
}
/**
@ -661,9 +675,7 @@ class Container implements ArrayAccess, ContainerContract
*/
public function factory($abstract)
{
return function () use ($abstract) {
return $this->make($abstract);
};
return fn () => $this->make($abstract);
}
/**
@ -708,7 +720,7 @@ class Container implements ArrayAccess, ContainerContract
throw $e;
}
throw new EntryNotFoundException($id, $e->getCode(), $e);
throw new EntryNotFoundException($id, is_int($e->getCode()) ? $e->getCode() : 0, $e);
}
}
@ -1008,6 +1020,10 @@ class Container implements ArrayAccess, ContainerContract
return $parameter->getDefaultValue();
}
if ($parameter->isVariadic()) {
return [];
}
$this->unresolvablePrimitive($parameter);
}
@ -1063,9 +1079,7 @@ class Container implements ArrayAccess, ContainerContract
return $this->make($className);
}
return array_map(function ($abstract) {
return $this->resolve($abstract);
}, $concrete);
return array_map(fn ($abstract) => $this->resolve($abstract), $concrete);
}
/**
@ -1426,9 +1440,7 @@ class Container implements ArrayAccess, ContainerContract
*/
public function offsetSet($key, $value): void
{
$this->bind($key, $value instanceof Closure ? $value : function () use ($value) {
return $value;
});
$this->bind($key, $value instanceof Closure ? $value : fn () => $value);
}
/**

View file

@ -91,8 +91,6 @@ class ContextualBindingBuilder implements ContextualBindingBuilderContract
*/
public function giveConfig($key, $default = null)
{
$this->give(function ($container) use ($key, $default) {
return $container->get('config')->get($key, $default);
});
$this->give(fn ($container) => $container->get('config')->get($key, $default));
}
}

View file

@ -0,0 +1,8 @@
<?php
namespace Illuminate\Contracts\Broadcasting;
interface ShouldBeUnique
{
//
}

View file

@ -10,9 +10,11 @@ interface Repository extends CacheInterface
/**
* Retrieve an item from the cache and delete it.
*
* @param string $key
* @param mixed $default
* @return mixed
* @template TCacheValue
*
* @param array|string $key
* @param TCacheValue|(\Closure(): TCacheValue) $default
* @return (TCacheValue is null ? mixed : TCacheValue)
*/
public function pull($key, $default = null);
@ -66,28 +68,34 @@ interface Repository extends CacheInterface
/**
* Get an item from the cache, or execute the given Closure and store the result.
*
* @template TCacheValue
*
* @param string $key
* @param \DateTimeInterface|\DateInterval|int|null $ttl
* @param \Closure $callback
* @return mixed
* @param \Closure(): TCacheValue $callback
* @return TCacheValue
*/
public function remember($key, $ttl, Closure $callback);
/**
* Get an item from the cache, or execute the given Closure and store the result forever.
*
* @template TCacheValue
*
* @param string $key
* @param \Closure $callback
* @return mixed
* @param \Closure(): TCacheValue $callback
* @return TCacheValue
*/
public function sear($key, Closure $callback);
/**
* Get an item from the cache, or execute the given Closure and store the result forever.
*
* @template TCacheValue
*
* @param string $key
* @param \Closure $callback
* @return mixed
* @param \Closure(): TCacheValue $callback
* @return TCacheValue
*/
public function rememberForever($key, Closure $callback);

View file

@ -0,0 +1,8 @@
<?php
namespace Illuminate\Contracts\Console;
interface Isolatable
{
//
}

View file

@ -0,0 +1,8 @@
<?php
namespace Illuminate\Contracts\Console;
interface PromptsForMissingInput
{
//
}

View file

@ -7,7 +7,7 @@ interface QueueingFactory extends Factory
/**
* Queue a cookie to send with the next response.
*
* @param array $parameters
* @param mixed ...$parameters
* @return void
*/
public function queue(...$parameters);

View file

@ -8,8 +8,7 @@ interface Castable
* Get the name of the caster class to use when casting from / to this cast target.
*
* @param array $arguments
* @return string
* @return string|\Illuminate\Contracts\Database\Eloquent\CastsAttributes|\Illuminate\Contracts\Database\Eloquent\CastsInboundAttributes
* @return class-string<CastsAttributes|CastsInboundAttributes>|CastsAttributes|CastsInboundAttributes
*/
public static function castUsing(array $arguments);
}

View file

@ -2,6 +2,10 @@
namespace Illuminate\Contracts\Database\Eloquent;
/**
* @template TGet
* @template TSet
*/
interface CastsAttributes
{
/**
@ -11,7 +15,7 @@ interface CastsAttributes
* @param string $key
* @param mixed $value
* @param array $attributes
* @return mixed
* @return TGet|null
*/
public function get($model, string $key, $value, array $attributes);
@ -20,7 +24,7 @@ interface CastsAttributes
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param mixed $value
* @param TSet|null $value
* @param array $attributes
* @return mixed
*/

View file

@ -34,6 +34,13 @@ class ModelIdentifier
*/
public $connection;
/**
* The class name of the model collection.
*
* @var string|null
*/
public $collectionClass;
/**
* Create a new model identifier.
*
@ -50,4 +57,17 @@ class ModelIdentifier
$this->relations = $relations;
$this->connection = $connection;
}
/**
* Specify the collection class that should be used when serializing / restoring collections.
*
* @param string|null $collectionClass
* @return $this
*/
public function useCollectionClass(?string $collectionClass)
{
$this->collectionClass = $collectionClass;
return $this;
}
}

View file

@ -64,7 +64,7 @@ interface Application extends Container
/**
* Get or check the current application environment.
*
* @param string|array $environments
* @param string|array ...$environments
* @return string|bool
*/
public function environment(...$environments);

View file

@ -0,0 +1,13 @@
<?php
namespace Illuminate\Contracts\Mail;
interface Attachable
{
/**
* Get an attachment instance for this entity.
*
* @return \Illuminate\Mail\Attachment
*/
public function toMailAttachment();
}

View file

@ -10,7 +10,7 @@ interface Mailable
* Send the message using the given mailer.
*
* @param \Illuminate\Contracts\Mail\Factory|\Illuminate\Contracts\Mail\Mailer $mailer
* @return void
* @return \Illuminate\Mail\SentMessage|null
*/
public function send($mailer);

View file

@ -25,7 +25,7 @@ interface Mailer
*
* @param string $text
* @param mixed $callback
* @return void
* @return \Illuminate\Mail\SentMessage|null
*/
public function raw($text, $callback);
@ -35,7 +35,7 @@ interface Mailer
* @param \Illuminate\Contracts\Mail\Mailable|string|array $view
* @param array $data
* @param \Closure|string|null $callback
* @return void
* @return \Illuminate\Mail\SentMessage|null
*/
public function send($view, array $data = [], $callback = null);
}

View file

@ -15,7 +15,7 @@ interface Paginator
/**
* Add a set of query string values to the paginator.
*
* @param array|string $key
* @param array|string|null $key
* @param string|null $value
* @return $this
*/
@ -25,7 +25,7 @@ interface Paginator
* Get / set the URL fragment to be appended to URLs.
*
* @param string|null $fragment
* @return $this|string
* @return $this|string|null
*/
public function fragment($fragment = null);

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