🚧 Did some stuff, don't remember exactly what
Signed-off-by: Luke Tainton <luke@tainton.uk>
This commit is contained in:
@@ -9,11 +9,6 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="theme-color" content="#563d7c">
|
||||
<?php
|
||||
if (!is_signed_in()) {
|
||||
echo("<meta http-equiv='refresh' content='0; url=" . $_ENV['APP_URL'] . "/login' />");
|
||||
}
|
||||
?>
|
||||
<title><?php echo( $PAGE_TITLE ); ?></title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
|
||||
@@ -2,28 +2,30 @@
|
||||
$PAGE_NAME = "Home";
|
||||
require_once __DIR__ . "/../includes/header.php";
|
||||
|
||||
// Get user's own tickets
|
||||
try {
|
||||
$user_tickets_stmt = "SELECT uuid, id, title, description, status FROM tickets WHERE created_by=:uuid";
|
||||
$user_tickets_sql = $db->prepare($user_tickets_stmt);
|
||||
$user_tickets_sql->bindParam(':uuid', $_SESSION['uuid']);
|
||||
$user_tickets_sql->execute();
|
||||
$user_tickets_sql->setFetchMode(PDO::FETCH_ASSOC);
|
||||
$user_tickets_result = $user_tickets_sql->fetchAll();
|
||||
} catch (PDOException $e) {
|
||||
echo("Error: " . $e->getMessage());
|
||||
}
|
||||
if (is_signed_in()) {
|
||||
// Get user's own tickets
|
||||
try {
|
||||
$user_tickets_stmt = "SELECT uuid, id, title, description, status FROM tickets WHERE created_by=:uuid";
|
||||
$user_tickets_sql = $db->prepare($user_tickets_stmt);
|
||||
$user_tickets_sql->bindParam(':uuid', $_SESSION['uuid']);
|
||||
$user_tickets_sql->execute();
|
||||
$user_tickets_sql->setFetchMode(PDO::FETCH_ASSOC);
|
||||
$user_tickets_result = $user_tickets_sql->fetchAll();
|
||||
} catch (PDOException $e) {
|
||||
echo("Error: " . $e->getMessage());
|
||||
}
|
||||
|
||||
// Get tickets user has subscribed to
|
||||
try {
|
||||
$sub_tickets_stmt = "SELECT ticket_uuid FROM ticket_subscribers WHERE user_uuid=:uuid";
|
||||
$sub_tickets_sql = $db->prepare($sub_tickets_stmt);
|
||||
$sub_tickets_sql->bindParam(':uuid', $_SESSION['uuid']);
|
||||
$sub_tickets_sql->execute();
|
||||
$sub_tickets_sql->setFetchMode(PDO::FETCH_ASSOC);
|
||||
$sub_tickets_result = $sub_tickets_sql->fetchAll();
|
||||
} catch (PDOException $e) {
|
||||
echo("Error: " . $e->getMessage());
|
||||
// Get tickets user has subscribed to
|
||||
try {
|
||||
$sub_tickets_stmt = "SELECT ticket_uuid FROM ticket_subscribers WHERE user_uuid=:uuid";
|
||||
$sub_tickets_sql = $db->prepare($sub_tickets_stmt);
|
||||
$sub_tickets_sql->bindParam(':uuid', $_SESSION['uuid']);
|
||||
$sub_tickets_sql->execute();
|
||||
$sub_tickets_sql->setFetchMode(PDO::FETCH_ASSOC);
|
||||
$sub_tickets_result = $sub_tickets_sql->fetchAll();
|
||||
} catch (PDOException $e) {
|
||||
echo("Error: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
function get_sub_ticket($db, $ticket_uuid) {
|
||||
@@ -71,74 +73,80 @@
|
||||
?>
|
||||
is the one-stop shop for all of your IT-related needs. Let us know how we can help you by opening a request.
|
||||
</p>
|
||||
<p>
|
||||
<a href='/new' class='btn btn-primary my-2'>Create a request</a>
|
||||
<a href='/open' class='btn btn-secondary my-2'>View existing requests</a>
|
||||
</p>
|
||||
<?php if (is_signed_in()) { ?>
|
||||
<p>
|
||||
<a href='/new' class='btn btn-primary my-2'>Create a request</a>
|
||||
<a href='/open' class='btn btn-secondary my-2'>View existing requests</a>
|
||||
</p>
|
||||
<?php } else { ?>
|
||||
<p><b>Please log in to create or view requests.</b></p>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="card mx-auto" style="width: 80%;">
|
||||
<div class="card-header">
|
||||
<span class="mdi mdi-ticket-outline"></span> My Open Requests
|
||||
</div>
|
||||
<ul class="list-group list-group-flush">
|
||||
<?php
|
||||
if (count($user_tickets_result) == 0) {
|
||||
echo("<center><b>No open tickets</b></center>");
|
||||
} else {
|
||||
foreach($user_tickets_result as $tkt) {
|
||||
?>
|
||||
<li class="list-group-item">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-10">
|
||||
<span style="display: inline;" class="text-muted">#<?php echo(sprintf("%'.05d\n", $tkt["id"])); ?> </span><span><b><?php echo($tkt['title']); ?></b></span>
|
||||
<p class="m-0"><?php echo($tkt['description']); ?></p>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<a class="btn btn-success float-right" href="view?rid=<?php echo($tkt["uuid"]); ?>" role="button">Go</a>
|
||||
<?php if (is_signed_in()) { ?>
|
||||
<section>
|
||||
<div class="card mx-auto" style="width: 80%;">
|
||||
<div class="card-header">
|
||||
<span class="mdi mdi-ticket-outline"></span> My Open Requests
|
||||
</div>
|
||||
<ul class="list-group list-group-flush">
|
||||
<?php
|
||||
if (count($user_tickets_result) == 0) {
|
||||
echo("<center><b>No open tickets</b></center>");
|
||||
} else {
|
||||
foreach($user_tickets_result as $tkt) {
|
||||
?>
|
||||
<li class="list-group-item">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-10">
|
||||
<span style="display: inline;" class="text-muted">#<?php echo(sprintf("%'.05d\n", $tkt["id"])); ?> </span><span><b><?php echo($tkt['title']); ?></b></span>
|
||||
<p class="m-0"><?php echo($tkt['description']); ?></p>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<a class="btn btn-success float-right" href="view?rid=<?php echo($tkt["uuid"]); ?>" role="button">Go</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<?php } } ?>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
</li>
|
||||
<?php } } ?>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section style="margin-top: 1%;">
|
||||
<div class="card mx-auto" style="width: 80%;">
|
||||
<div class="card-header">
|
||||
<span class="mdi mdi-rss"></span> My Subscribed Requests
|
||||
</div>
|
||||
<ul class="list-group list-group-flush">
|
||||
<?php
|
||||
if (count($sub_tickets_result) == 0) {
|
||||
echo("<center><b>No subscribed tickets</b></center>");
|
||||
} else {
|
||||
foreach($sub_tickets_result as $sub) {
|
||||
$tkt = get_sub_ticket($db, $sub['ticket_uuid']);
|
||||
$tkt_creator = get_user_name($db, $tkt['created_by']);
|
||||
?>
|
||||
<li class="list-group-item">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-10">
|
||||
<span style="display: inline;" class="text-muted">#<?php echo sprintf("%'.05d\n", $tkt["id"]); ?> </span><span><b><?php echo($tkt['title']); ?></b></span> <span style="display: inline;" class="text-muted"><?php echo("(Creator: " . $tkt_creator . ")"); ?></span>
|
||||
<p class="m-0"><?php echo($tkt['description']); ?></p>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<a class="btn btn-success float-right" href="view?rid=<?php echo($tkt["uuid"]); ?>" role="button">Go</a>
|
||||
<section style="margin-top: 1%;">
|
||||
<div class="card mx-auto" style="width: 80%;">
|
||||
<div class="card-header">
|
||||
<span class="mdi mdi-rss"></span> My Subscribed Requests
|
||||
</div>
|
||||
<ul class="list-group list-group-flush">
|
||||
<?php
|
||||
if (count($sub_tickets_result) == 0) {
|
||||
echo("<center><b>No subscribed tickets</b></center>");
|
||||
} else {
|
||||
foreach($sub_tickets_result as $sub) {
|
||||
$tkt = get_sub_ticket($db, $sub['ticket_uuid']);
|
||||
$tkt_creator = get_user_name($db, $tkt['created_by']);
|
||||
?>
|
||||
<li class="list-group-item">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-10">
|
||||
<span style="display: inline;" class="text-muted">#<?php echo sprintf("%'.05d\n", $tkt["id"]); ?> </span><span><b><?php echo($tkt['title']); ?></b></span> <span style="display: inline;" class="text-muted"><?php echo("(Creator: " . $tkt_creator . ")"); ?></span>
|
||||
<p class="m-0"><?php echo($tkt['description']); ?></p>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<a class="btn btn-success float-right" href="view?rid=<?php echo($tkt["uuid"]); ?>" role="button">Go</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<?php } } ?>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
</li>
|
||||
<?php } } ?>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
<?php } ?>
|
||||
|
||||
</main>
|
||||
|
||||
|
||||
@@ -1,60 +1,52 @@
|
||||
<?php
|
||||
$PAGE_NAME = "New request";
|
||||
require_once __DIR__ . "/../includes/header.php";
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
// If form submitted, save to database
|
||||
if($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
try {
|
||||
// Process ticket data
|
||||
$stmt = "INSERT INTO tickets (title, description, created_by) VALUES (:title, :description, :user)";
|
||||
$tkt_uuid = Uuid::uuid4()->toString();
|
||||
$stmt = "INSERT INTO tickets (uuid, title, description, created_by) VALUES (:tktuuid, :title, :description, :user)";
|
||||
$sql = $db->prepare($stmt);
|
||||
$sql->bindParam(':tktuuid', $tkt_uuid);
|
||||
$sql->bindParam(':title', $_POST['title']);
|
||||
$sql->bindParam(':description', $_POST['description']);
|
||||
$sql->bindParam(':user', $_SESSION['uuid']);
|
||||
$sql->execute();
|
||||
} catch (PDOException $e) {
|
||||
// echo("Error: <br>" . $e->getMessage() . "<br>");
|
||||
$new_ticket_alert = array("danger", "SQL Error: " . $e->getMessage());
|
||||
$new_ticket_alert = array("danger", "Failed to save request: " . $e->getMessage());
|
||||
}
|
||||
|
||||
// Get ticket UUID
|
||||
// If file is uploaded, process that
|
||||
if(isset($_FILES['file']) && $_FILES['file']['name'] != "") {
|
||||
try {
|
||||
$tkt_stmt = "SELECT uuid FROM tickets WHERE created_by=:uuid AND created_on > date_sub(now(), interval 1 minute)";
|
||||
$tkt_sql = $db->prepare($tkt_stmt);
|
||||
$tkt_sql->bindParam(':uuid', $_SESSION['uuid']);
|
||||
$tkt_sql->execute();
|
||||
$tkt_sql->setFetchMode(PDO::FETCH_ASSOC);
|
||||
$tkt_result = $tkt_sql->fetchAll()[0];
|
||||
$tkt_uuid = $tkt_result['uuid'];
|
||||
$file_name = $_FILES['file']['name'];
|
||||
$file_size = $_FILES['file']['size'];
|
||||
$file_type = $_FILES['file']['type'];
|
||||
$file_tmp = $_FILES['file']['tmp_name'];
|
||||
move_uploaded_file($file_tmp,"/srv/attachments/".$file_name);
|
||||
$stmt = "INSERT INTO ticket_uploads (ticket, user, filename) VALUES (:ticket, :user, :name)";
|
||||
$sql = $db->prepare($stmt);
|
||||
$sql->bindParam(':ticket', $tkt_uuid);
|
||||
$sql->bindParam(':user', $_SESSION['uuid']);
|
||||
$sql->bindParam(':name', $file_name);
|
||||
$sql->execute();
|
||||
} catch (PDOException $e) {
|
||||
// echo("Error: <br>" . $e->getMessage() . "<br>");
|
||||
$new_ticket_alert = array("danger", "SQL Error: " . $e->getMessage());
|
||||
$new_ticket_alert = array("danger", "Failed to upload file: " . $e->getMessage());
|
||||
}
|
||||
|
||||
// If file is uploaded, process that
|
||||
if(isset($_FILES['file'])) {
|
||||
try {
|
||||
$file_name = $_FILES['file']['name'];
|
||||
$file_size =$_FILES['file']['size'];
|
||||
$file_type=$_FILES['file']['type'];
|
||||
$file_tmp =$_FILES['file']['tmp_name'];
|
||||
move_uploaded_file($file_tmp,"/srv/attachments/".$file_name);
|
||||
$stmt = "INSERT INTO ticket_uploads (ticket, user, path) VALUES (:ticket, :user, :filepath)";
|
||||
$sql = $db->prepare($stmt);
|
||||
$sql->bindParam(':ticket', $tkt_uuid);
|
||||
$sql->bindParam(':user', $_SESSION['uuid']);
|
||||
$sql->bindParam(':filepath', "/srv/attachments/".$file_name);
|
||||
$sql->execute();
|
||||
} catch (PDOException $e) {
|
||||
// echo("Error: <br>" . $e->getMessage() . "<br>");
|
||||
$new_ticket_alert = array("danger", "SQL Error: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
header_remove("Location");
|
||||
header('Location: /view?rid=' . $tkt_uuid);
|
||||
}
|
||||
|
||||
if (!is_signed_in()) {
|
||||
$new_ticket_alert = array("danger", "You need to log in to access this page.");
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
@@ -66,21 +58,29 @@
|
||||
<?php
|
||||
if(isset($new_ticket_alert)) {
|
||||
echo("
|
||||
<div class='alert alert-" . $new_ticket_alert[0] . "' role='alert'>
|
||||
" . $new_ticket_alert[1] . "
|
||||
</div>
|
||||
"); }
|
||||
<section>
|
||||
<div class='alert alert-" . $new_ticket_alert[0] . " alert-dismissible fade show' role='alert'>
|
||||
" . $new_ticket_alert[1] . "
|
||||
<button type='button' class='close' data-dismiss='alert' aria-label='Close'>
|
||||
<span aria-hidden='true'>×</span>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
");
|
||||
unset($new_ticket_alert);
|
||||
}
|
||||
?>
|
||||
</section>
|
||||
|
||||
<section class="jumbotron text-center">
|
||||
<div class="container">
|
||||
<h1>Create a new request</h1>
|
||||
<p class="lead text-muted">
|
||||
Fill in the form below to create a new request. We'll respond to it as soon as we can.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
<?php if (is_signed_in()) { ?>
|
||||
<section class="jumbotron text-center">
|
||||
<div class="container">
|
||||
<h1>Create a new request</h1>
|
||||
<p class="lead text-muted">
|
||||
Fill in the form below to create a new request. We'll respond to it as soon as we can.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="card mx-auto" style="width: 50%;">
|
||||
@@ -101,6 +101,7 @@
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
<?php } ?>
|
||||
|
||||
</main>
|
||||
|
||||
|
||||
@@ -8,19 +8,30 @@
|
||||
<!-- Begin page content -->
|
||||
<main role="main" class="flex-shrink-0">
|
||||
|
||||
<section class="jumbotron text-center">
|
||||
<div class="container">
|
||||
<h1>Open requests</h1>
|
||||
<p class="lead text-muted">
|
||||
Here you can find all of your requests, and other requests that you are subscribed to.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>This page is currently under construction.</p>
|
||||
<?php if (is_signed_in()) { ?>
|
||||
<section class="jumbotron text-center">
|
||||
<div class="container">
|
||||
<h1>Open requests</h1>
|
||||
<p class="lead text-muted">
|
||||
Here you can find all of your requests, and other requests that you are subscribed to.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>This page is currently under construction.</p>
|
||||
</section>
|
||||
<?php } else { ?>
|
||||
<section>
|
||||
<div class='alert alert-danger alert-dismissible fade show' role='alert'>
|
||||
You need to log in to access this page.
|
||||
<button type='button' class='close' data-dismiss='alert' aria-label='Close'>
|
||||
<span aria-hidden='true'>×</span>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
<?php } ?>
|
||||
|
||||
</main>
|
||||
|
||||
<?php
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
array_push($authorised_users, $user['user_uuid']);
|
||||
}
|
||||
|
||||
if (in_array($_SESSION['uuid'], $authorised_users)) {
|
||||
if (in_array($_SESSION['uuid'], $authorised_users) || $_SESSION['uuid'] == $request['created_by']) {
|
||||
$is_authorised = true;
|
||||
} else {
|
||||
$is_authorised = false;
|
||||
@@ -45,29 +45,71 @@
|
||||
<!-- Begin page content -->
|
||||
<main role="main" class="flex-shrink-0">
|
||||
|
||||
<?php if ($is_authorised == true) { ?>
|
||||
<section class="jumbotron text-center">
|
||||
<div class="container">
|
||||
<h1><?php echo($request['title']); ?></h1>
|
||||
<p style="color: gray; font-style: italic;"><?php echo("#" . sprintf("%'.05d\n", $request["id"])); ?></p>
|
||||
<p class="lead text-muted">
|
||||
<?php echo($request['description']); ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php print_r($request); ?>
|
||||
</p>
|
||||
<p>
|
||||
<?php print_r($users_result) ?>
|
||||
</p>
|
||||
<?php if (!is_signed_in()) { ?>
|
||||
<section>
|
||||
<div class='alert alert-danger alert-dismissible fade show' role='alert'>
|
||||
You need to log in to access this page.
|
||||
<button type='button' class='close' data-dismiss='alert' aria-label='Close'>
|
||||
<span aria-hidden='true'>×</span>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
<?php } else if ($is_authorised == false) { ?>
|
||||
<section class="jumbotron text-center">
|
||||
<div class="container">
|
||||
<h1>You are not authorised to see this page.</h1>
|
||||
</div>
|
||||
</section>
|
||||
<?php } ?>
|
||||
<?php } else {
|
||||
if ($is_authorised == true) { ?>
|
||||
<section class="jumbotron text-center">
|
||||
<div class="container">
|
||||
<h1><?php echo($request['title']); ?></h1>
|
||||
<p style="color: gray; font-style: italic;"><?php echo("#" . sprintf("%'.05d\n", $request["id"])); ?></p>
|
||||
<p class="lead text-muted"><?php echo($request['description']); ?></p>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<div class="card mx-auto">
|
||||
<div class="card-header"><span class="mdi mdi-information-outline"></span> Information</div>
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<span style="display: inline;"><b>Status:</b> <?php echo($request['status']); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm">
|
||||
<div class="card mx-auto">
|
||||
<div class="card-header"><span class="mdi mdi-update"></span> Updates</div>
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-10">
|
||||
<span style="display: inline;" class="text-muted">#<?php echo(sprintf("%'.05d\n", $tkt["id"])); ?> </span><span><b><?php echo($tkt['title']); ?></b></span>
|
||||
<p class="m-0"><?php echo($tkt['description']); ?></p>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<a class="btn btn-success float-right" href="view?rid=<?php echo($tkt["uuid"]); ?>" role="button">Go</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><?php print_r($request); ?></p>
|
||||
</div>
|
||||
</section>
|
||||
<?php } else if ($is_authorised == false) { ?>
|
||||
<section class="jumbotron text-center">
|
||||
<div class="container">
|
||||
<h1>You are not authorised to see this page.</h1>
|
||||
</div>
|
||||
</section>
|
||||
<?php } } ?>
|
||||
|
||||
</main>
|
||||
|
||||
|
||||
5
composer.json
Normal file
5
composer.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"require": {
|
||||
"ramsey/uuid": "^4.1"
|
||||
}
|
||||
}
|
||||
295
composer.lock
generated
Normal file
295
composer.lock
generated
Normal file
@@ -0,0 +1,295 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "4776075042c636b02ae6c054c0e2fc37",
|
||||
"packages": [
|
||||
{
|
||||
"name": "brick/math",
|
||||
"version": "0.8.15",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/brick/math.git",
|
||||
"reference": "9b08d412b9da9455b210459ff71414de7e6241cd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/brick/math/zipball/9b08d412b9da9455b210459ff71414de7e6241cd",
|
||||
"reference": "9b08d412b9da9455b210459ff71414de7e6241cd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": "^7.1|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"php-coveralls/php-coveralls": "^2.2",
|
||||
"phpunit/phpunit": "^7.5.15|^8.5",
|
||||
"vimeo/psalm": "^3.5"
|
||||
},
|
||||
"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"
|
||||
],
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/brick/math",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-04-15T15:59:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ramsey/collection",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ramsey/collection.git",
|
||||
"reference": "925ad8cf55ba7a3fc92e332c58fd0478ace3e1ca"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ramsey/collection/zipball/925ad8cf55ba7a3fc92e332c58fd0478ace3e1ca",
|
||||
"reference": "925ad8cf55ba7a3fc92e332c58fd0478ace3e1ca",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.5.0",
|
||||
"fzaninotto/faker": "^1.5",
|
||||
"jakub-onderka/php-parallel-lint": "^1",
|
||||
"jangregor/phpstan-prophecy": "^0.6",
|
||||
"mockery/mockery": "^1.3",
|
||||
"phpstan/extension-installer": "^1",
|
||||
"phpstan/phpdoc-parser": "0.4.1",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"phpstan/phpstan-mockery": "^0.12",
|
||||
"phpstan/phpstan-phpunit": "^0.12",
|
||||
"phpunit/phpunit": "^8.5",
|
||||
"slevomat/coding-standard": "^6.0",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Ramsey\\Collection\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ben Ramsey",
|
||||
"email": "ben@benramsey.com",
|
||||
"homepage": "https://benramsey.com"
|
||||
}
|
||||
],
|
||||
"description": "A PHP 7.2+ library for representing and manipulating collections.",
|
||||
"homepage": "https://github.com/ramsey/collection",
|
||||
"keywords": [
|
||||
"array",
|
||||
"collection",
|
||||
"hash",
|
||||
"map",
|
||||
"queue",
|
||||
"set"
|
||||
],
|
||||
"time": "2020-01-05T00:22:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ramsey/uuid",
|
||||
"version": "4.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ramsey/uuid.git",
|
||||
"reference": "988dbefc7878d0a35f12afb4df1f7dd0bd153c43"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/988dbefc7878d0a35f12afb4df1f7dd0bd153c43",
|
||||
"reference": "988dbefc7878d0a35f12afb4df1f7dd0bd153c43",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"brick/math": "^0.8",
|
||||
"ext-json": "*",
|
||||
"php": "^7.2 || ^8",
|
||||
"ramsey/collection": "^1.0",
|
||||
"symfony/polyfill-ctype": "^1.8"
|
||||
},
|
||||
"replace": {
|
||||
"rhumsaa/uuid": "self.version"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeception/aspect-mock": "^3",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7.0",
|
||||
"doctrine/annotations": "^1.8",
|
||||
"goaop/framework": "^2",
|
||||
"mockery/mockery": "^1.3",
|
||||
"moontoast/math": "^1.1",
|
||||
"paragonie/random-lib": "^2",
|
||||
"php-mock/php-mock-mockery": "^1.3",
|
||||
"php-mock/php-mock-phpunit": "^2.5",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.1",
|
||||
"phpbench/phpbench": "^0.17.1",
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"phpstan/phpstan-mockery": "^0.12",
|
||||
"phpstan/phpstan-phpunit": "^0.12",
|
||||
"phpunit/phpunit": "^8.5",
|
||||
"psy/psysh": "^0.10.0",
|
||||
"slevomat/coding-standard": "^6.0",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"vimeo/psalm": "3.9.4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
|
||||
"ext-ctype": "Enables faster processing of character classification using ctype functions.",
|
||||
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
|
||||
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
|
||||
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
|
||||
"ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Ramsey\\Uuid\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
|
||||
"homepage": "https://github.com/ramsey/uuid",
|
||||
"keywords": [
|
||||
"guid",
|
||||
"identifier",
|
||||
"uuid"
|
||||
],
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/ramsey",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-07-28T16:51:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.18.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "1c302646f6efc070cd46856e600e5e0684d6b454"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/1c302646f6efc070cd46856e600e5e0684d6b454",
|
||||
"reference": "1c302646f6efc070cd46856e600e5e0684d6b454",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-ctype": "For best performance"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.18-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Ctype\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Gert de Pagter",
|
||||
"email": "BackEndTea@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for ctype functions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"ctype",
|
||||
"polyfill",
|
||||
"portable"
|
||||
],
|
||||
"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": "2020-07-14T12:35:20+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "1.1.0"
|
||||
}
|
||||
7
vendor/autoload.php
vendored
Normal file
7
vendor/autoload.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInita47a22c36b23233ed3ce46b8027644b1::getLoader();
|
||||
1
vendor/brick/math/.github/FUNDING.yml
vendored
Normal file
1
vendor/brick/math/.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
tidelift: "packagist/brick/math"
|
||||
20
vendor/brick/math/LICENSE
vendored
Normal file
20
vendor/brick/math/LICENSE
vendored
Normal 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.
|
||||
16
vendor/brick/math/SECURITY.md
vendored
Normal file
16
vendor/brick/math/SECURITY.md
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Only the latest release stream is supported.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 0.8.x | :white_check_mark: |
|
||||
| < 0.8 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
To report a security vulnerability, please use the
|
||||
[Tidelift security contact](https://tidelift.com/security).
|
||||
Tidelift will coordinate the fix and disclosure.
|
||||
35
vendor/brick/math/composer.json
vendored
Normal file
35
vendor/brick/math/composer.json
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "brick/math",
|
||||
"description": "Arbitrary-precision arithmetic library",
|
||||
"type": "library",
|
||||
"keywords": [
|
||||
"Brick",
|
||||
"Math",
|
||||
"Arbitrary-precision",
|
||||
"Arithmetic",
|
||||
"BigInteger",
|
||||
"BigDecimal",
|
||||
"BigRational",
|
||||
"Bignum"
|
||||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.1|^8.0",
|
||||
"ext-json": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.5.15|^8.5",
|
||||
"php-coveralls/php-coveralls": "^2.2",
|
||||
"vimeo/psalm": "^3.5"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Brick\\Math\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Brick\\Math\\Tests\\": "tests/"
|
||||
}
|
||||
}
|
||||
}
|
||||
40
vendor/brick/math/psalm-baseline.xml
vendored
Normal file
40
vendor/brick/math/psalm-baseline.xml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<files psalm-version="3.8.5@e6ec5fa22a7b9e61670a24d07b3119aff80dcd89">
|
||||
<file src="src/Internal/Calculator/BcMathCalculator.php">
|
||||
<InvalidNullableReturnType occurrences="3">
|
||||
<code>string</code>
|
||||
<code>string</code>
|
||||
<code>string</code>
|
||||
</InvalidNullableReturnType>
|
||||
<InvalidReturnStatement occurrences="1">
|
||||
<code>[$q, $r]</code>
|
||||
</InvalidReturnStatement>
|
||||
<InvalidReturnType occurrences="1">
|
||||
<code>array</code>
|
||||
</InvalidReturnType>
|
||||
<NullableReturnStatement occurrences="3">
|
||||
<code>\bcdiv($a, $b, 0)</code>
|
||||
<code>\bcmod($a, $b)</code>
|
||||
<code>\bcpowmod($base, $exp, $mod, 0)</code>
|
||||
</NullableReturnStatement>
|
||||
</file>
|
||||
<file src="src/Internal/Calculator/NativeCalculator.php">
|
||||
<InvalidOperand occurrences="6">
|
||||
<code>$a</code>
|
||||
<code>$a</code>
|
||||
<code>$a</code>
|
||||
<code>$b</code>
|
||||
<code>$blockA</code>
|
||||
<code>$blockA</code>
|
||||
</InvalidOperand>
|
||||
<LoopInvalidation occurrences="4">
|
||||
<code>$i</code>
|
||||
<code>$i</code>
|
||||
<code>$i</code>
|
||||
<code>$j</code>
|
||||
</LoopInvalidation>
|
||||
<PossiblyInvalidArgument occurrences="1">
|
||||
<code>$e / 2</code>
|
||||
</PossiblyInvalidArgument>
|
||||
</file>
|
||||
</files>
|
||||
56
vendor/brick/math/psalm.xml
vendored
Normal file
56
vendor/brick/math/psalm.xml
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
totallyTyped="false"
|
||||
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"
|
||||
errorBaseline="psalm-baseline.xml"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="src" />
|
||||
<ignoreFiles>
|
||||
<directory name="vendor" />
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
|
||||
<issueHandlers>
|
||||
<LessSpecificReturnType errorLevel="info" />
|
||||
|
||||
<!-- level 3 issues - slightly lazy code writing, but provably low false-negatives -->
|
||||
|
||||
<DeprecatedMethod errorLevel="info" />
|
||||
<DeprecatedProperty errorLevel="info" />
|
||||
<DeprecatedClass errorLevel="info" />
|
||||
<DeprecatedConstant errorLevel="info" />
|
||||
<DeprecatedFunction errorLevel="info" />
|
||||
<DeprecatedInterface errorLevel="info" />
|
||||
<DeprecatedTrait errorLevel="info" />
|
||||
|
||||
<InternalMethod errorLevel="info" />
|
||||
<InternalProperty errorLevel="info" />
|
||||
<InternalClass errorLevel="info" />
|
||||
|
||||
<MissingClosureReturnType errorLevel="info" />
|
||||
<MissingReturnType errorLevel="info" />
|
||||
<MissingPropertyType errorLevel="info" />
|
||||
<InvalidDocblock errorLevel="info" />
|
||||
<MisplacedRequiredParam errorLevel="info" />
|
||||
|
||||
<PropertyNotSetInConstructor errorLevel="info" />
|
||||
<MissingConstructor errorLevel="info" />
|
||||
<MissingClosureParamType errorLevel="info" />
|
||||
<MissingParamType errorLevel="info" />
|
||||
|
||||
<RedundantCondition errorLevel="info" />
|
||||
|
||||
<DocblockTypeContradiction errorLevel="info" />
|
||||
<RedundantConditionGivenDocblockType errorLevel="info" />
|
||||
|
||||
<UnresolvableInclude errorLevel="info" />
|
||||
|
||||
<RawObjectIteration errorLevel="info" />
|
||||
|
||||
<InvalidStringClass errorLevel="info" />
|
||||
</issueHandlers>
|
||||
</psalm>
|
||||
855
vendor/brick/math/src/BigDecimal.php
vendored
Normal file
855
vendor/brick/math/src/BigDecimal.php
vendored
Normal file
@@ -0,0 +1,855 @@
|
||||
<?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.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* The scale (number of digits after the decimal point) of this decimal number.
|
||||
*
|
||||
* This must be zero or more.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $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.
|
||||
*
|
||||
* @param BigNumber|int|float|string $value
|
||||
*
|
||||
* @return BigDecimal
|
||||
*
|
||||
* @throws MathException If the value cannot be converted to a BigDecimal.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function of($value) : BigNumber
|
||||
{
|
||||
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.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*
|
||||
* @throws \InvalidArgumentException If the scale is negative.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function ofUnscaledValue($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.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function zero() : BigDecimal
|
||||
{
|
||||
/** @psalm-suppress ImpureStaticVariable */
|
||||
static $zero;
|
||||
|
||||
if ($zero === null) {
|
||||
$zero = new BigDecimal('0');
|
||||
}
|
||||
|
||||
return $zero;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigDecimal representing one, with a scale of zero.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function one() : BigDecimal
|
||||
{
|
||||
/** @psalm-suppress ImpureStaticVariable */
|
||||
static $one;
|
||||
|
||||
if ($one === null) {
|
||||
$one = new BigDecimal('1');
|
||||
}
|
||||
|
||||
return $one;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigDecimal representing ten, with a scale of zero.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function ten() : BigDecimal
|
||||
{
|
||||
/** @psalm-suppress ImpureStaticVariable */
|
||||
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.
|
||||
*
|
||||
* @return BigDecimal The result.
|
||||
*
|
||||
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
|
||||
*/
|
||||
public function plus($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.
|
||||
*
|
||||
* @return BigDecimal The result.
|
||||
*
|
||||
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
|
||||
*/
|
||||
public function minus($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.
|
||||
*
|
||||
* @return BigDecimal The result.
|
||||
*
|
||||
* @throws MathException If the multiplier is not a valid number, or is not convertible to a BigDecimal.
|
||||
*/
|
||||
public function multipliedBy($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.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*
|
||||
* @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($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.
|
||||
*
|
||||
* @return BigDecimal The result.
|
||||
*
|
||||
* @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($that) : BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->value === '0') {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
[$a, $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`.
|
||||
*
|
||||
* @param int $exponent The exponent.
|
||||
*
|
||||
* @return BigDecimal The result.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @return BigDecimal The quotient.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||
*/
|
||||
public function quotient($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.
|
||||
*
|
||||
* @return BigDecimal The remainder.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||
*/
|
||||
public function remainder($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($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.
|
||||
*
|
||||
* @param int $scale
|
||||
*
|
||||
* @return BigDecimal
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @param int $n
|
||||
*
|
||||
* @return BigDecimal
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param int $n
|
||||
*
|
||||
* @return BigDecimal
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*/
|
||||
public function abs() : BigDecimal
|
||||
{
|
||||
return $this->isNegative() ? $this->negated() : $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negated value of this number.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*/
|
||||
public function negated() : BigDecimal
|
||||
{
|
||||
return new BigDecimal(Calculator::get()->neg($this->value), $this->scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function compareTo($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);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSign() : int
|
||||
{
|
||||
return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function getUnscaledValue() : BigInteger
|
||||
{
|
||||
return BigInteger::create($this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getScale() : int
|
||||
{
|
||||
return $this->scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representing the integral part of this decimal number.
|
||||
*
|
||||
* Example: `-123.456` => `-123`.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
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` => ''.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasNonZeroFractionalPart() : bool
|
||||
{
|
||||
return $this->getFractionalPart() !== \str_repeat('0', $this->scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toBigInteger() : BigInteger
|
||||
{
|
||||
if ($this->scale === 0) {
|
||||
$zeroScaleDecimal = $this;
|
||||
} else {
|
||||
$zeroScaleDecimal = $this->dividedBy(1, 0);
|
||||
}
|
||||
|
||||
return BigInteger::create($zeroScaleDecimal->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toBigDecimal() : BigDecimal
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toBigRational() : BigRational
|
||||
{
|
||||
$numerator = BigInteger::create($this->value);
|
||||
$denominator = BigInteger::create('1' . \str_repeat('0', $this->scale));
|
||||
|
||||
return BigRational::create($numerator, $denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
if ($scale === $this->scale) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toInt() : int
|
||||
{
|
||||
return $this->toBigInteger()->toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toFloat() : float
|
||||
{
|
||||
return (float) (string) $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
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 by interface Serializable and SHOULD NOT be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function serialize() : string
|
||||
{
|
||||
return $this->value . ':' . $this->scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only here to implement interface Serializable and cannot be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @param BigDecimal $x The first decimal number.
|
||||
* @param BigDecimal $y The second decimal number.
|
||||
*
|
||||
* @return array{0: string, 1: 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];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $scale
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
904
vendor/brick/math/src/BigInteger.php
vendored
Normal file
904
vendor/brick/math/src/BigInteger.php
vendored
Normal file
@@ -0,0 +1,904 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math;
|
||||
|
||||
use Brick\Math\Exception\DivisionByZeroException;
|
||||
use Brick\Math\Exception\IntegerOverflowException;
|
||||
use Brick\Math\Exception\MathException;
|
||||
use Brick\Math\Exception\NegativeNumberException;
|
||||
use Brick\Math\Exception\NumberFormatException;
|
||||
use Brick\Math\Internal\Calculator;
|
||||
|
||||
/**
|
||||
* An arbitrary-size integer.
|
||||
*
|
||||
* All methods accepting a number as a parameter accept either a BigInteger instance,
|
||||
* an integer, or a string representing an arbitrary size integer.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
final class BigInteger extends BigNumber
|
||||
{
|
||||
/**
|
||||
* The value, as a string of digits with optional leading minus sign.
|
||||
*
|
||||
* No leading zeros must be present.
|
||||
* No leading minus sign must be present if the number is zero.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* Protected constructor. Use a factory method to obtain an instance.
|
||||
*
|
||||
* @param string $value A string of digits, with optional leading minus sign.
|
||||
*/
|
||||
protected function __construct(string $value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BigInteger of the given value.
|
||||
*
|
||||
* @param BigNumber|int|float|string $value
|
||||
*
|
||||
* @return BigInteger
|
||||
*
|
||||
* @throws MathException If the value cannot be converted to a BigInteger.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function of($value) : BigNumber
|
||||
{
|
||||
return parent::of($value)->toBigInteger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a number from a string in a given base.
|
||||
*
|
||||
* The string can optionally be prefixed with the `+` or `-` sign.
|
||||
*
|
||||
* Bases greater than 36 are not supported by this method, as there is no clear consensus on which of the lowercase
|
||||
* or uppercase characters should come first. Instead, this method accepts any base up to 36, and does not
|
||||
* differentiate lowercase and uppercase characters, which are considered equal.
|
||||
*
|
||||
* For bases greater than 36, and/or custom alphabets, use the fromArbitraryBase() method.
|
||||
*
|
||||
* @param string $number The number to convert, in the given base.
|
||||
* @param int $base The base of the number, between 2 and 36.
|
||||
*
|
||||
* @return BigInteger
|
||||
*
|
||||
* @throws NumberFormatException If the number is empty, or contains invalid chars for the given base.
|
||||
* @throws \InvalidArgumentException If the base is out of range.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function fromBase(string $number, int $base) : BigInteger
|
||||
{
|
||||
if ($number === '') {
|
||||
throw new NumberFormatException('The number cannot be empty.');
|
||||
}
|
||||
|
||||
if ($base < 2 || $base > 36) {
|
||||
throw new \InvalidArgumentException(\sprintf('Base %d is not in range 2 to 36.', $base));
|
||||
}
|
||||
|
||||
if ($number[0] === '-') {
|
||||
$sign = '-';
|
||||
$number = \substr($number, 1);
|
||||
} elseif ($number[0] === '+') {
|
||||
$sign = '';
|
||||
$number = \substr($number, 1);
|
||||
} else {
|
||||
$sign = '';
|
||||
}
|
||||
|
||||
if ($number === '') {
|
||||
throw new NumberFormatException('The number cannot be empty.');
|
||||
}
|
||||
|
||||
$number = \ltrim($number, '0');
|
||||
|
||||
if ($number === '') {
|
||||
// The result will be the same in any base, avoid further calculation.
|
||||
return BigInteger::zero();
|
||||
}
|
||||
|
||||
if ($number === '1') {
|
||||
// The result will be the same in any base, avoid further calculation.
|
||||
return new BigInteger($sign . '1');
|
||||
}
|
||||
|
||||
$pattern = '/[^' . \substr(Calculator::ALPHABET, 0, $base) . ']/';
|
||||
|
||||
if (\preg_match($pattern, \strtolower($number), $matches) === 1) {
|
||||
throw new NumberFormatException(\sprintf('"%s" is not a valid character in base %d.', $matches[0], $base));
|
||||
}
|
||||
|
||||
if ($base === 10) {
|
||||
// The number is usable as is, avoid further calculation.
|
||||
return new BigInteger($sign . $number);
|
||||
}
|
||||
|
||||
$result = Calculator::get()->fromBase($number, $base);
|
||||
|
||||
return new BigInteger($sign . $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string containing an integer in an arbitrary base, using a custom alphabet.
|
||||
*
|
||||
* Because this method accepts an alphabet with any character, including dash, it does not handle negative numbers.
|
||||
*
|
||||
* @param string $number The number to parse.
|
||||
* @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8.
|
||||
*
|
||||
* @return BigInteger
|
||||
*
|
||||
* @throws NumberFormatException If the given number is empty or contains invalid chars for the given alphabet.
|
||||
* @throws \InvalidArgumentException If the alphabet does not contain at least 2 chars.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function fromArbitraryBase(string $number, string $alphabet) : BigInteger
|
||||
{
|
||||
if ($number === '') {
|
||||
throw new NumberFormatException('The number cannot be empty.');
|
||||
}
|
||||
|
||||
$base = \strlen($alphabet);
|
||||
|
||||
if ($base < 2) {
|
||||
throw new \InvalidArgumentException('The alphabet must contain at least 2 chars.');
|
||||
}
|
||||
|
||||
$pattern = '/[^' . \preg_quote($alphabet, '/') . ']/';
|
||||
|
||||
if (\preg_match($pattern, $number, $matches) === 1) {
|
||||
throw NumberFormatException::charNotInAlphabet($matches[0]);
|
||||
}
|
||||
|
||||
$number = Calculator::get()->fromArbitraryBase($number, $alphabet, $base);
|
||||
|
||||
return new BigInteger($number);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigInteger representing zero.
|
||||
*
|
||||
* @return BigInteger
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function zero() : BigInteger
|
||||
{
|
||||
/** @psalm-suppress ImpureStaticVariable */
|
||||
static $zero;
|
||||
|
||||
if ($zero === null) {
|
||||
$zero = new BigInteger('0');
|
||||
}
|
||||
|
||||
return $zero;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigInteger representing one.
|
||||
*
|
||||
* @return BigInteger
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function one() : BigInteger
|
||||
{
|
||||
/** @psalm-suppress ImpureStaticVariable */
|
||||
static $one;
|
||||
|
||||
if ($one === null) {
|
||||
$one = new BigInteger('1');
|
||||
}
|
||||
|
||||
return $one;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigInteger representing ten.
|
||||
*
|
||||
* @return BigInteger
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function ten() : BigInteger
|
||||
{
|
||||
/** @psalm-suppress ImpureStaticVariable */
|
||||
static $ten;
|
||||
|
||||
if ($ten === null) {
|
||||
$ten = new BigInteger('10');
|
||||
}
|
||||
|
||||
return $ten;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sum of this number and the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @return BigInteger The result.
|
||||
*
|
||||
* @throws MathException If the number is not valid, or is not convertible to a BigInteger.
|
||||
*/
|
||||
public function plus($that) : BigInteger
|
||||
{
|
||||
$that = BigInteger::of($that);
|
||||
|
||||
if ($that->value === '0') {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($this->value === '0') {
|
||||
return $that;
|
||||
}
|
||||
|
||||
$value = Calculator::get()->add($this->value, $that->value);
|
||||
|
||||
return new BigInteger($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the difference of this number and the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @return BigInteger The result.
|
||||
*
|
||||
* @throws MathException If the number is not valid, or is not convertible to a BigInteger.
|
||||
*/
|
||||
public function minus($that) : BigInteger
|
||||
{
|
||||
$that = BigInteger::of($that);
|
||||
|
||||
if ($that->value === '0') {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$value = Calculator::get()->sub($this->value, $that->value);
|
||||
|
||||
return new BigInteger($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the product of this number and the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @return BigInteger The result.
|
||||
*
|
||||
* @throws MathException If the multiplier is not a valid number, or is not convertible to a BigInteger.
|
||||
*/
|
||||
public function multipliedBy($that) : BigInteger
|
||||
{
|
||||
$that = BigInteger::of($that);
|
||||
|
||||
if ($that->value === '1') {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($this->value === '1') {
|
||||
return $that;
|
||||
}
|
||||
|
||||
$value = Calculator::get()->mul($this->value, $that->value);
|
||||
|
||||
return new BigInteger($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of the division of this number by the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
||||
* @param int $roundingMode An optional rounding mode.
|
||||
*
|
||||
* @return BigInteger The result.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid number, is not convertible to a BigInteger, is zero,
|
||||
* or RoundingMode::UNNECESSARY is used and the remainder is not zero.
|
||||
*/
|
||||
public function dividedBy($that, int $roundingMode = RoundingMode::UNNECESSARY) : BigInteger
|
||||
{
|
||||
$that = BigInteger::of($that);
|
||||
|
||||
if ($that->value === '1') {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($that->value === '0') {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
$result = Calculator::get()->divRound($this->value, $that->value, $roundingMode);
|
||||
|
||||
return new BigInteger($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this number exponentiated to the given value.
|
||||
*
|
||||
* @param int $exponent The exponent.
|
||||
*
|
||||
* @return BigInteger The result.
|
||||
*
|
||||
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
|
||||
*/
|
||||
public function power(int $exponent) : BigInteger
|
||||
{
|
||||
if ($exponent === 0) {
|
||||
return BigInteger::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 BigInteger(Calculator::get()->pow($this->value, $exponent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quotient of the division of this number by the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @return BigInteger
|
||||
*
|
||||
* @throws DivisionByZeroException If the divisor is zero.
|
||||
*/
|
||||
public function quotient($that) : BigInteger
|
||||
{
|
||||
$that = BigInteger::of($that);
|
||||
|
||||
if ($that->value === '1') {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($that->value === '0') {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
$quotient = Calculator::get()->divQ($this->value, $that->value);
|
||||
|
||||
return new BigInteger($quotient);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remainder of the division of this number by the given one.
|
||||
*
|
||||
* The remainder, when non-zero, has the same sign as the dividend.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @return BigInteger
|
||||
*
|
||||
* @throws DivisionByZeroException If the divisor is zero.
|
||||
*/
|
||||
public function remainder($that) : BigInteger
|
||||
{
|
||||
$that = BigInteger::of($that);
|
||||
|
||||
if ($that->value === '1') {
|
||||
return BigInteger::zero();
|
||||
}
|
||||
|
||||
if ($that->value === '0') {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
$remainder = Calculator::get()->divR($this->value, $that->value);
|
||||
|
||||
return new BigInteger($remainder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quotient and remainder of the division of this number by the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @return BigInteger[] An array containing the quotient and the remainder.
|
||||
*
|
||||
* @throws DivisionByZeroException If the divisor is zero.
|
||||
*/
|
||||
public function quotientAndRemainder($that) : array
|
||||
{
|
||||
$that = BigInteger::of($that);
|
||||
|
||||
if ($that->value === '0') {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
[$quotient, $remainder] = Calculator::get()->divQR($this->value, $that->value);
|
||||
|
||||
return [
|
||||
new BigInteger($quotient),
|
||||
new BigInteger($remainder)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the modulo of this number and the given one.
|
||||
*
|
||||
* The modulo operation yields the same result as the remainder operation when both operands are of the same sign,
|
||||
* and may differ when signs are different.
|
||||
*
|
||||
* The result of the modulo operation, when non-zero, has the same sign as the divisor.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @return BigInteger
|
||||
*
|
||||
* @throws DivisionByZeroException If the divisor is zero.
|
||||
*/
|
||||
public function mod($that) : BigInteger
|
||||
{
|
||||
$that = BigInteger::of($that);
|
||||
|
||||
if ($that->value === '0') {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
return $this->remainder($that)->plus($that)->remainder($that);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this number raised into power with modulo.
|
||||
*
|
||||
* This operation only works on positive numbers.
|
||||
*
|
||||
* @param BigNumber|int|float|string $exp The positive exponent.
|
||||
* @param BigNumber|int|float|string $mod The modulo. Must not be zero.
|
||||
*
|
||||
* @return BigInteger
|
||||
*
|
||||
* @throws NegativeNumberException If any of the operands is negative.
|
||||
* @throws DivisionByZeroException If the modulo is zero.
|
||||
*/
|
||||
public function powerMod($exp, $mod) : BigInteger
|
||||
{
|
||||
$exp = BigInteger::of($exp);
|
||||
$mod = BigInteger::of($mod);
|
||||
|
||||
if ($this->isNegative() || $exp->isNegative() || $mod->isNegative()) {
|
||||
throw new NegativeNumberException('The operands cannot be negative.');
|
||||
}
|
||||
|
||||
if ($mod->isZero()) {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
$result = Calculator::get()->powmod($this->value, $exp->value, $mod->value);
|
||||
|
||||
return new BigInteger($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the greatest common divisor of this number and the given one.
|
||||
*
|
||||
* The GCD is always positive, unless both operands are zero, in which case it is zero.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function gcd($that) : BigInteger
|
||||
{
|
||||
$that = BigInteger::of($that);
|
||||
|
||||
if ($that->value === '0' && $this->value[0] !== '-') {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($this->value === '0' && $that->value[0] !== '-') {
|
||||
return $that;
|
||||
}
|
||||
|
||||
$value = Calculator::get()->gcd($this->value, $that->value);
|
||||
|
||||
return new BigInteger($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the integer square root number of this number, rounded down.
|
||||
*
|
||||
* The result is the largest x such that x² ≤ n.
|
||||
*
|
||||
* @return BigInteger
|
||||
*
|
||||
* @throws NegativeNumberException If this number is negative.
|
||||
*/
|
||||
public function sqrt() : BigInteger
|
||||
{
|
||||
if ($this->value[0] === '-') {
|
||||
throw new NegativeNumberException('Cannot calculate the square root of a negative number.');
|
||||
}
|
||||
|
||||
$value = Calculator::get()->sqrt($this->value);
|
||||
|
||||
return new BigInteger($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute value of this number.
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function abs() : BigInteger
|
||||
{
|
||||
return $this->isNegative() ? $this->negated() : $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse of this number.
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function negated() : BigInteger
|
||||
{
|
||||
return new BigInteger(Calculator::get()->neg($this->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the integer bitwise-and combined with another integer.
|
||||
*
|
||||
* This method returns a negative BigInteger if and only if both operands are negative.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function and($that) : BigInteger
|
||||
{
|
||||
$that = BigInteger::of($that);
|
||||
|
||||
return new BigInteger(Calculator::get()->and($this->value, $that->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the integer bitwise-or combined with another integer.
|
||||
*
|
||||
* This method returns a negative BigInteger if and only if either of the operands is negative.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function or($that) : BigInteger
|
||||
{
|
||||
$that = BigInteger::of($that);
|
||||
|
||||
return new BigInteger(Calculator::get()->or($this->value, $that->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the integer bitwise-xor combined with another integer.
|
||||
*
|
||||
* This method returns a negative BigInteger if and only if exactly one of the operands is negative.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function xor($that) : BigInteger
|
||||
{
|
||||
$that = BigInteger::of($that);
|
||||
|
||||
return new BigInteger(Calculator::get()->xor($this->value, $that->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the integer left shifted by a given number of bits.
|
||||
*
|
||||
* @param int $distance The distance to shift.
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function shiftedLeft(int $distance) : BigInteger
|
||||
{
|
||||
if ($distance === 0) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($distance < 0) {
|
||||
return $this->shiftedRight(- $distance);
|
||||
}
|
||||
|
||||
return $this->multipliedBy(BigInteger::of(2)->power($distance));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the integer right shifted by a given number of bits.
|
||||
*
|
||||
* @param int $distance The distance to shift.
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function shiftedRight(int $distance) : BigInteger
|
||||
{
|
||||
if ($distance === 0) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($distance < 0) {
|
||||
return $this->shiftedLeft(- $distance);
|
||||
}
|
||||
|
||||
$operand = BigInteger::of(2)->power($distance);
|
||||
|
||||
if ($this->isPositiveOrZero()) {
|
||||
return $this->quotient($operand);
|
||||
}
|
||||
|
||||
return $this->dividedBy($operand, RoundingMode::UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bits in the minimal two's-complement representation of this BigInteger, excluding a sign bit.
|
||||
*
|
||||
* For positive BigIntegers, this is equivalent to the number of bits in the ordinary binary representation.
|
||||
* Computes (ceil(log2(this < 0 ? -this : this+1))).
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getBitLength() : int
|
||||
{
|
||||
if ($this->value === '0') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($this->isNegative()) {
|
||||
return $this->abs()->minus(1)->getBitLength();
|
||||
}
|
||||
|
||||
return strlen($this->toBase(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the rightmost (lowest-order) one bit in this BigInteger.
|
||||
*
|
||||
* Returns -1 if this BigInteger contains no one bits.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLowestSetBit() : int
|
||||
{
|
||||
$n = $this;
|
||||
$bitLength = $this->getBitLength();
|
||||
|
||||
for ($i = 0; $i <= $bitLength; $i++) {
|
||||
if ($n->isOdd()) {
|
||||
return $i;
|
||||
}
|
||||
|
||||
$n = $n->shiftedRight(1);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this number is even.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEven() : bool
|
||||
{
|
||||
return in_array($this->value[-1], ['0', '2', '4', '6', '8'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this number is odd.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isOdd() : bool
|
||||
{
|
||||
return in_array($this->value[-1], ['1', '3', '5', '7', '9'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if and only if the designated bit is set.
|
||||
*
|
||||
* Computes ((this & (1<<n)) != 0).
|
||||
*
|
||||
* @param int $n The bit to test, 0-based.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function testBit(int $n) : bool
|
||||
{
|
||||
if ($n < 0) {
|
||||
throw new \InvalidArgumentException('The bit to test cannot be negative.');
|
||||
}
|
||||
|
||||
return $this->shiftedRight($n)->isOdd();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function compareTo($that) : int
|
||||
{
|
||||
$that = BigNumber::of($that);
|
||||
|
||||
if ($that instanceof BigInteger) {
|
||||
return Calculator::get()->cmp($this->value, $that->value);
|
||||
}
|
||||
|
||||
return - $that->compareTo($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSign() : int
|
||||
{
|
||||
return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toBigInteger() : BigInteger
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toBigDecimal() : BigDecimal
|
||||
{
|
||||
return BigDecimal::create($this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toBigRational() : BigRational
|
||||
{
|
||||
return BigRational::create($this, BigInteger::one(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
return $this->toBigDecimal()->toScale($scale, $roundingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toInt() : int
|
||||
{
|
||||
$intValue = (int) $this->value;
|
||||
|
||||
if ($this->value !== (string) $intValue) {
|
||||
throw IntegerOverflowException::toIntOverflow($this);
|
||||
}
|
||||
|
||||
return $intValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toFloat() : float
|
||||
{
|
||||
return (float) $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this number in the given base.
|
||||
*
|
||||
* The output will always be lowercase for bases greater than 10.
|
||||
*
|
||||
* @param int $base
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \InvalidArgumentException If the base is out of range.
|
||||
*/
|
||||
public function toBase(int $base) : string
|
||||
{
|
||||
if ($base === 10) {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
if ($base < 2 || $base > 36) {
|
||||
throw new \InvalidArgumentException(\sprintf('Base %d is out of range [2, 36]', $base));
|
||||
}
|
||||
|
||||
return Calculator::get()->toBase($this->value, $base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this number in an arbitrary base with a custom alphabet.
|
||||
*
|
||||
* Because this method accepts an alphabet with any character, including dash, it does not handle negative numbers;
|
||||
* a NegativeNumberException will be thrown when attempting to call this method on a negative number.
|
||||
*
|
||||
* @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws NegativeNumberException If this number is negative.
|
||||
* @throws \InvalidArgumentException If the given alphabet does not contain at least 2 chars.
|
||||
*/
|
||||
public function toArbitraryBase(string $alphabet) : string
|
||||
{
|
||||
$base = \strlen($alphabet);
|
||||
|
||||
if ($base < 2) {
|
||||
throw new \InvalidArgumentException('The alphabet must contain at least 2 chars.');
|
||||
}
|
||||
|
||||
if ($this->value[0] === '-') {
|
||||
throw new NegativeNumberException(__FUNCTION__ . '() does not support negative numbers.');
|
||||
}
|
||||
|
||||
return Calculator::get()->toArbitraryBase($this->value, $alphabet, $base);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is required by interface Serializable and SHOULD NOT be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function serialize() : string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only here to implement interface Serializable and cannot be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @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.');
|
||||
}
|
||||
|
||||
$this->value = $value;
|
||||
}
|
||||
}
|
||||
528
vendor/brick/math/src/BigNumber.php
vendored
Normal file
528
vendor/brick/math/src/BigNumber.php
vendored
Normal file
@@ -0,0 +1,528 @@
|
||||
<?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.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private const PARSE_REGEXP =
|
||||
'/^' .
|
||||
'(?<integral>[\-\+]?[0-9]+)' .
|
||||
'(?:' .
|
||||
'(?:' .
|
||||
'(?:\.(?<fractional>[0-9]+))?' .
|
||||
'(?:[eE](?<exponent>[\-\+]?[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
|
||||
*
|
||||
* @param BigNumber|int|float|string $value
|
||||
*
|
||||
* @return BigNumber
|
||||
*
|
||||
* @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($value) : BigNumber
|
||||
{
|
||||
if ($value instanceof BigNumber) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (\is_int($value)) {
|
||||
return new BigInteger((string) $value);
|
||||
}
|
||||
|
||||
if (is_float($value)) {
|
||||
$value = self::floatToString($value);
|
||||
} else {
|
||||
$value = (string) $value;
|
||||
}
|
||||
|
||||
if (\preg_match(self::PARSE_REGEXP, $value, $matches) !== 1) {
|
||||
throw new NumberFormatException(\sprintf('The given value "%s" does not represent a valid number.', $value));
|
||||
}
|
||||
|
||||
if (isset($matches['denominator'])) {
|
||||
$numerator = self::cleanUp($matches['integral']);
|
||||
$denominator = \ltrim($matches['denominator'], '0');
|
||||
|
||||
if ($denominator === '') {
|
||||
throw DivisionByZeroException::denominatorMustNotBeZero();
|
||||
}
|
||||
|
||||
return new BigRational(new BigInteger($numerator), new BigInteger($denominator), false);
|
||||
}
|
||||
|
||||
if (isset($matches['fractional']) || isset($matches['exponent'])) {
|
||||
$fractional = isset($matches['fractional']) ? $matches['fractional'] : '';
|
||||
$exponent = isset($matches['exponent']) ? (int) $matches['exponent'] : 0;
|
||||
|
||||
$unscaledValue = self::cleanUp($matches['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($matches['integral']);
|
||||
|
||||
return new BigInteger($integral);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely converts float to string, avoiding locale-dependent issues.
|
||||
*
|
||||
* @see https://github.com/brick/math/pull/20
|
||||
*
|
||||
* @param float $float
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @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 protected constructors from sibling classes.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param mixed ...$args The arguments to the constructor.
|
||||
*
|
||||
* @return static
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
protected static function create(... $args) : BigNumber
|
||||
{
|
||||
/** @psalm-suppress TooManyArguments */
|
||||
return new static(... $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return static The minimum value.
|
||||
*
|
||||
* @throws \InvalidArgumentException If no values are given.
|
||||
* @throws MathException If an argument is not valid.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function min(...$values) : BigNumber
|
||||
{
|
||||
$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.
|
||||
*
|
||||
* @return static The maximum value.
|
||||
*
|
||||
* @throws \InvalidArgumentException If no values are given.
|
||||
* @throws MathException If an argument is not valid.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function max(...$values) : BigNumber
|
||||
{
|
||||
$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.
|
||||
*
|
||||
* @return static The sum.
|
||||
*
|
||||
* @throws \InvalidArgumentException If no values are given.
|
||||
* @throws MathException If an argument is not valid.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function sum(...$values) : BigNumber
|
||||
{
|
||||
/** @var BigNumber|null $sum */
|
||||
$sum = null;
|
||||
|
||||
foreach ($values as $value) {
|
||||
$value = static::of($value);
|
||||
|
||||
if ($sum === null) {
|
||||
$sum = $value;
|
||||
} else {
|
||||
$sum = 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...)
|
||||
*
|
||||
* @param BigNumber $a
|
||||
* @param BigNumber $b
|
||||
*
|
||||
* @return BigNumber
|
||||
*
|
||||
* @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 sign.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEqualTo($that) : bool
|
||||
{
|
||||
return $this->compareTo($that) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly lower than the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isLessThan($that) : bool
|
||||
{
|
||||
return $this->compareTo($that) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is lower than or equal to the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isLessThanOrEqualTo($that) : bool
|
||||
{
|
||||
return $this->compareTo($that) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly greater than the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isGreaterThan($that) : bool
|
||||
{
|
||||
return $this->compareTo($that) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is greater than or equal to the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isGreaterThanOrEqualTo($that) : bool
|
||||
{
|
||||
return $this->compareTo($that) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number equals zero.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isZero() : bool
|
||||
{
|
||||
return $this->getSign() === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly negative.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNegative() : bool
|
||||
{
|
||||
return $this->getSign() < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is negative or zero.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNegativeOrZero() : bool
|
||||
{
|
||||
return $this->getSign() <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly positive.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPositive() : bool
|
||||
{
|
||||
return $this->getSign() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is positive or zero.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that
|
||||
*
|
||||
* @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($that) : int;
|
||||
|
||||
/**
|
||||
* Converts this number to a BigInteger.
|
||||
*
|
||||
* @return BigInteger The converted number.
|
||||
*
|
||||
* @throws RoundingNecessaryException If this number cannot be converted to a BigInteger without rounding.
|
||||
*/
|
||||
abstract public function toBigInteger() : BigInteger;
|
||||
|
||||
/**
|
||||
* Converts this number to a BigDecimal.
|
||||
*
|
||||
* @return BigDecimal The converted number.
|
||||
*
|
||||
* @throws RoundingNecessaryException If this number cannot be converted to a BigDecimal without rounding.
|
||||
*/
|
||||
abstract public function toBigDecimal() : BigDecimal;
|
||||
|
||||
/**
|
||||
* Converts this number to a BigRational.
|
||||
*
|
||||
* @return BigRational The converted number.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @return int The converted value.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @return float The converted value.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function __toString() : string;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function jsonSerialize() : string
|
||||
{
|
||||
return $this->__toString();
|
||||
}
|
||||
}
|
||||
479
vendor/brick/math/src/BigRational.php
vendored
Normal file
479
vendor/brick/math/src/BigRational.php
vendored
Normal file
@@ -0,0 +1,479 @@
|
||||
<?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.
|
||||
*
|
||||
* @var BigInteger
|
||||
*/
|
||||
private $numerator;
|
||||
|
||||
/**
|
||||
* The denominator. Always strictly positive.
|
||||
*
|
||||
* @var BigInteger
|
||||
*/
|
||||
private $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.
|
||||
*
|
||||
* @param BigNumber|int|float|string $value
|
||||
*
|
||||
* @return BigRational
|
||||
*
|
||||
* @throws MathException If the value cannot be converted to a BigRational.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function of($value) : BigNumber
|
||||
{
|
||||
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.
|
||||
*
|
||||
* @return BigRational
|
||||
*
|
||||
* @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($numerator, $denominator) : BigRational
|
||||
{
|
||||
$numerator = BigInteger::of($numerator);
|
||||
$denominator = BigInteger::of($denominator);
|
||||
|
||||
return new BigRational($numerator, $denominator, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigRational representing zero.
|
||||
*
|
||||
* @return BigRational
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function zero() : BigRational
|
||||
{
|
||||
/** @psalm-suppress ImpureStaticVariable */
|
||||
static $zero;
|
||||
|
||||
if ($zero === null) {
|
||||
$zero = new BigRational(BigInteger::zero(), BigInteger::one(), false);
|
||||
}
|
||||
|
||||
return $zero;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigRational representing one.
|
||||
*
|
||||
* @return BigRational
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function one() : BigRational
|
||||
{
|
||||
/** @psalm-suppress ImpureStaticVariable */
|
||||
static $one;
|
||||
|
||||
if ($one === null) {
|
||||
$one = new BigRational(BigInteger::one(), BigInteger::one(), false);
|
||||
}
|
||||
|
||||
return $one;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigRational representing ten.
|
||||
*
|
||||
* @return BigRational
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function ten() : BigRational
|
||||
{
|
||||
/** @psalm-suppress ImpureStaticVariable */
|
||||
static $ten;
|
||||
|
||||
if ($ten === null) {
|
||||
$ten = new BigRational(BigInteger::ten(), BigInteger::one(), false);
|
||||
}
|
||||
|
||||
return $ten;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function getNumerator() : BigInteger
|
||||
{
|
||||
return $this->numerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function getDenominator() : BigInteger
|
||||
{
|
||||
return $this->denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quotient of the division of the numerator by the denominator.
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function quotient() : BigInteger
|
||||
{
|
||||
return $this->numerator->quotient($this->denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remainder of the division of the numerator by the denominator.
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @return BigRational The result.
|
||||
*
|
||||
* @throws MathException If the number is not valid.
|
||||
*/
|
||||
public function plus($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.
|
||||
*
|
||||
* @return BigRational The result.
|
||||
*
|
||||
* @throws MathException If the number is not valid.
|
||||
*/
|
||||
public function minus($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.
|
||||
*
|
||||
* @return BigRational The result.
|
||||
*
|
||||
* @throws MathException If the multiplier is not a valid number.
|
||||
*/
|
||||
public function multipliedBy($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.
|
||||
*
|
||||
* @return BigRational The result.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid number, or is zero.
|
||||
*/
|
||||
public function dividedBy($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.
|
||||
*
|
||||
* @param int $exponent The exponent.
|
||||
*
|
||||
* @return BigRational The result.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @return BigRational
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @return BigRational
|
||||
*/
|
||||
public function abs() : BigRational
|
||||
{
|
||||
return new BigRational($this->numerator->abs(), $this->denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negated value of this BigRational.
|
||||
*
|
||||
* @return BigRational
|
||||
*/
|
||||
public function negated() : BigRational
|
||||
{
|
||||
return new BigRational($this->numerator->negated(), $this->denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the simplified value of this BigRational.
|
||||
*
|
||||
* @return 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function compareTo($that) : int
|
||||
{
|
||||
return $this->minus($that)->getSign();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSign() : int
|
||||
{
|
||||
return $this->numerator->getSign();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toBigDecimal() : BigDecimal
|
||||
{
|
||||
return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toBigRational() : BigRational
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toInt() : int
|
||||
{
|
||||
return $this->toBigInteger()->toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toFloat() : float
|
||||
{
|
||||
return $this->numerator->toFloat() / $this->denominator->toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
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 by interface Serializable and SHOULD NOT be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function serialize() : string
|
||||
{
|
||||
return $this->numerator . '/' . $this->denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only here to implement interface Serializable and cannot be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
31
vendor/brick/math/src/Exception/DivisionByZeroException.php
vendored
Normal file
31
vendor/brick/math/src/Exception/DivisionByZeroException.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when a division by zero occurs.
|
||||
*/
|
||||
class DivisionByZeroException extends MathException
|
||||
{
|
||||
/**
|
||||
* @return DivisionByZeroException
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function divisionByZero() : DivisionByZeroException
|
||||
{
|
||||
return new self('Division by zero.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DivisionByZeroException
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function denominatorMustNotBeZero() : DivisionByZeroException
|
||||
{
|
||||
return new self('The denominator of a rational number cannot be zero.');
|
||||
}
|
||||
}
|
||||
27
vendor/brick/math/src/Exception/IntegerOverflowException.php
vendored
Normal file
27
vendor/brick/math/src/Exception/IntegerOverflowException.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
use Brick\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* Exception thrown when an integer overflow occurs.
|
||||
*/
|
||||
class IntegerOverflowException extends MathException
|
||||
{
|
||||
/**
|
||||
* @param BigInteger $value
|
||||
*
|
||||
* @return IntegerOverflowException
|
||||
*
|
||||
* @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));
|
||||
}
|
||||
}
|
||||
14
vendor/brick/math/src/Exception/MathException.php
vendored
Normal file
14
vendor/brick/math/src/Exception/MathException.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
/**
|
||||
* Base class for all math exceptions.
|
||||
*
|
||||
* This class is abstract to ensure that only fine-grained exceptions are thrown throughout the code.
|
||||
*/
|
||||
abstract class MathException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
12
vendor/brick/math/src/Exception/NegativeNumberException.php
vendored
Normal file
12
vendor/brick/math/src/Exception/NegativeNumberException.php
vendored
Normal 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
|
||||
{
|
||||
}
|
||||
35
vendor/brick/math/src/Exception/NumberFormatException.php
vendored
Normal file
35
vendor/brick/math/src/Exception/NumberFormatException.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?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.
|
||||
*
|
||||
* @return NumberFormatException
|
||||
*
|
||||
* @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));
|
||||
}
|
||||
}
|
||||
21
vendor/brick/math/src/Exception/RoundingNecessaryException.php
vendored
Normal file
21
vendor/brick/math/src/Exception/RoundingNecessaryException.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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
|
||||
{
|
||||
/**
|
||||
* @return RoundingNecessaryException
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function roundingNecessary() : RoundingNecessaryException
|
||||
{
|
||||
return new self('Rounding is necessary to represent the result of the operation at this scale.');
|
||||
}
|
||||
}
|
||||
686
vendor/brick/math/src/Internal/Calculator.php
vendored
Normal file
686
vendor/brick/math/src/Internal/Calculator.php
vendored
Normal file
@@ -0,0 +1,686 @@
|
||||
<?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.
|
||||
*
|
||||
* @var Calculator|null
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @return Calculator
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* @return Calculator
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param string $a The first operand.
|
||||
* @param string $b The second operand.
|
||||
*
|
||||
* @return array{0: bool, 1: bool, 2: string, 3: 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.
|
||||
*
|
||||
* @param string $n The number.
|
||||
*
|
||||
* @return string The absolute value.
|
||||
*/
|
||||
final public function abs(string $n) : string
|
||||
{
|
||||
return ($n[0] === '-') ? \substr($n, 1) : $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Negates a number.
|
||||
*
|
||||
* @param string $n The number.
|
||||
*
|
||||
* @return string The negated value.
|
||||
*/
|
||||
final public function neg(string $n) : string
|
||||
{
|
||||
if ($n === '0') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
if ($n[0] === '-') {
|
||||
return \substr($n, 1);
|
||||
}
|
||||
|
||||
return '-' . $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two numbers.
|
||||
*
|
||||
* @param string $a The first number.
|
||||
* @param string $b The second number.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @param string $a The augend.
|
||||
* @param string $b The addend.
|
||||
*
|
||||
* @return string The sum.
|
||||
*/
|
||||
abstract public function add(string $a, string $b) : string;
|
||||
|
||||
/**
|
||||
* Subtracts two numbers.
|
||||
*
|
||||
* @param string $a The minuend.
|
||||
* @param string $b The subtrahend.
|
||||
*
|
||||
* @return string The difference.
|
||||
*/
|
||||
abstract public function sub(string $a, string $b) : string;
|
||||
|
||||
/**
|
||||
* Multiplies two numbers.
|
||||
*
|
||||
* @param string $a The multiplicand.
|
||||
* @param string $b The multiplier.
|
||||
*
|
||||
* @return string The product.
|
||||
*/
|
||||
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 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;
|
||||
|
||||
/**
|
||||
* 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 modulo; must be strictly positive.
|
||||
*
|
||||
* @return string The power.
|
||||
*/
|
||||
abstract function powmod(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.
|
||||
*
|
||||
* @param string $a The first number.
|
||||
* @param string $b The second number.
|
||||
*
|
||||
* @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));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square root of the given number, rounded down.
|
||||
*
|
||||
* The result is the largest x such that x² ≤ n.
|
||||
* The input MUST NOT be negative.
|
||||
*
|
||||
* @param string $n The number.
|
||||
*
|
||||
* @return string The square root.
|
||||
*/
|
||||
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.
|
||||
* @param int $roundingMode The rounding mode.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \InvalidArgumentException If the rounding mode is invalid.
|
||||
* @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function xor(string $a, string $b) : string
|
||||
{
|
||||
return $this->bitwise('xor', $a, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a bitwise operation on a decimal number.
|
||||
*
|
||||
* @param string $operator The operator to use, must be "and", "or" or "xor".
|
||||
* @param string $a The left operand.
|
||||
* @param string $b The right operand.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function twosComplement(string $number) : string
|
||||
{
|
||||
$xor = \str_repeat("\xff", \strlen($number));
|
||||
|
||||
$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] = \chr(0);
|
||||
}
|
||||
|
||||
return $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a decimal number to a binary string.
|
||||
*
|
||||
* @param string $number The number to convert, positive or zero, only digits.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
92
vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php
vendored
Normal file
92
vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
<?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
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add(string $a, string $b) : string
|
||||
{
|
||||
return \bcadd($a, $b, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sub(string $a, string $b) : string
|
||||
{
|
||||
return \bcsub($a, $b, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function mul(string $a, string $b) : string
|
||||
{
|
||||
return \bcmul($a, $b, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divQ(string $a, string $b) : string
|
||||
{
|
||||
return \bcdiv($a, $b, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divR(string $a, string $b) : string
|
||||
{
|
||||
return \bcmod($a, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divQR(string $a, string $b) : array
|
||||
{
|
||||
$q = \bcdiv($a, $b, 0);
|
||||
$r = \bcmod($a, $b);
|
||||
|
||||
return [$q, $r];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function pow(string $a, int $e) : string
|
||||
{
|
||||
return \bcpow($a, (string) $e, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function powmod(string $base, string $exp, string $mod) : string
|
||||
{
|
||||
return \bcpowmod($base, $exp, $mod, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sqrt(string $n) : string
|
||||
{
|
||||
return \bcsqrt($n, 0);
|
||||
}
|
||||
}
|
||||
142
vendor/brick/math/src/Internal/Calculator/GmpCalculator.php
vendored
Normal file
142
vendor/brick/math/src/Internal/Calculator/GmpCalculator.php
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
<?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
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_add($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sub(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_sub($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function mul(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_mul($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divQ(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_div_q($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divR(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_div_r($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divQR(string $a, string $b) : array
|
||||
{
|
||||
[$q, $r] = \gmp_div_qr($a, $b);
|
||||
|
||||
return [
|
||||
\gmp_strval($q),
|
||||
\gmp_strval($r)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function pow(string $a, int $e) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_pow($a, $e));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function powmod(string $base, string $exp, string $mod) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_powm($base, $exp, $mod));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function gcd(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_gcd($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fromBase(string $number, int $base) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_init($number, $base));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toBase(string $number, int $base) : string
|
||||
{
|
||||
return \gmp_strval($number, $base);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function and(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_and($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function or(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_or($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function xor(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_xor($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sqrt(string $n) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_sqrt($n));
|
||||
}
|
||||
}
|
||||
616
vendor/brick/math/src/Internal/Calculator/NativeCalculator.php
vendored
Normal file
616
vendor/brick/math/src/Internal/Calculator/NativeCalculator.php
vendored
Normal file
@@ -0,0 +1,616 @@
|
||||
<?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.
|
||||
*
|
||||
* For 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)
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $maxDigits;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @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.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add(string $a, string $b) : string
|
||||
{
|
||||
$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);
|
||||
|
||||
if ($aNeg === $bNeg) {
|
||||
$result = $this->doAdd($aDig, $bDig);
|
||||
} else {
|
||||
$result = $this->doSub($aDig, $bDig);
|
||||
}
|
||||
|
||||
if ($aNeg) {
|
||||
$result = $this->neg($result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sub(string $a, string $b) : string
|
||||
{
|
||||
return $this->add($a, $this->neg($b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function mul(string $a, string $b) : string
|
||||
{
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divQ(string $a, string $b) : string
|
||||
{
|
||||
return $this->divQR($a, $b)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divR(string $a, string $b): string
|
||||
{
|
||||
return $this->divQR($a, $b)[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
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'];
|
||||
}
|
||||
|
||||
$na = $a * 1; // cast to number
|
||||
|
||||
if (is_int($na)) {
|
||||
$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];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
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);
|
||||
$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/
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function powmod(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
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param string $a The first operand.
|
||||
* @param string $b The second operand.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
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;
|
||||
$i = 0;
|
||||
}
|
||||
|
||||
$blockA = \substr($a, $i, $blockLength);
|
||||
$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.
|
||||
*
|
||||
* @param string $a The first operand.
|
||||
* @param string $b The second operand.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
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;
|
||||
$i = 0;
|
||||
}
|
||||
|
||||
$blockA = \substr($a, $i, $blockLength);
|
||||
$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.
|
||||
*
|
||||
* @param string $a The first operand.
|
||||
* @param string $b The second operand.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
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;
|
||||
$i = 0;
|
||||
}
|
||||
|
||||
$blockA = (int) \substr($a, $i, $blockALength);
|
||||
|
||||
$line = '';
|
||||
$carry = 0;
|
||||
|
||||
for ($j = $y - $maxDigits;; $j -= $maxDigits) {
|
||||
$blockBLength = $maxDigits;
|
||||
|
||||
if ($j < 0) {
|
||||
$blockBLength += $j;
|
||||
$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.
|
||||
*
|
||||
* @param string $a The first operand.
|
||||
* @param string $b The second operand.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @param string $a The first operand.
|
||||
* @param string $b The second operand.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @param string $a The first operand.
|
||||
* @param string $b The second operand.
|
||||
*
|
||||
* @return array{0: string, 1: string, 2: 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
107
vendor/brick/math/src/RoundingMode.php
vendored
Normal 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;
|
||||
}
|
||||
445
vendor/composer/ClassLoader.php
vendored
Normal file
445
vendor/composer/ClassLoader.php
vendored
Normal file
@@ -0,0 +1,445 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @see http://www.php-fig.org/psr/psr-0/
|
||||
* @see http://www.php-fig.org/psr/psr-4/
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
// PSR-4
|
||||
private $prefixLengthsPsr4 = array();
|
||||
private $prefixDirsPsr4 = array();
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
private $prefixesPsr0 = array();
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
private $useIncludePath = false;
|
||||
private $classMap = array();
|
||||
private $classMapAuthoritative = false;
|
||||
private $missingClasses = array();
|
||||
private $apcuPrefix;
|
||||
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', $this->prefixesPsr0);
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $classMap Class to filename map
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 base directories
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr0 = (array) $paths;
|
||||
} else {
|
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr4 = (array) $paths;
|
||||
} else {
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getApcuPrefix()
|
||||
{
|
||||
return $this->apcuPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return bool|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||
return false;
|
||||
}
|
||||
if (null !== $this->apcuPrefix) {
|
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||
if ($hit) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if (false === $file && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if (null !== $this->apcuPrefix) {
|
||||
apcu_add($this->apcuPrefix.$class, $file);
|
||||
}
|
||||
|
||||
if (false === $file) {
|
||||
// Remember that this class does not exist.
|
||||
$this->missingClasses[$class] = true;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath . '\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
if (file_exists($file = $dir . $pathEnd)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 lookup
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 include paths.
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
include $file;
|
||||
}
|
||||
21
vendor/composer/LICENSE
vendored
Normal file
21
vendor/composer/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
9
vendor/composer/autoload_classmap.php
vendored
Normal file
9
vendor/composer/autoload_classmap.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
||||
11
vendor/composer/autoload_files.php
vendored
Normal file
11
vendor/composer/autoload_files.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
// autoload_files.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'e39a8b23c42d4e1452234d762b03835a' => $vendorDir . '/ramsey/uuid/src/functions.php',
|
||||
);
|
||||
9
vendor/composer/autoload_namespaces.php
vendored
Normal file
9
vendor/composer/autoload_namespaces.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
||||
13
vendor/composer/autoload_psr4.php
vendored
Normal file
13
vendor/composer/autoload_psr4.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
|
||||
'Ramsey\\Uuid\\' => array($vendorDir . '/ramsey/uuid/src'),
|
||||
'Ramsey\\Collection\\' => array($vendorDir . '/ramsey/collection/src'),
|
||||
'Brick\\Math\\' => array($vendorDir . '/brick/math/src'),
|
||||
);
|
||||
73
vendor/composer/autoload_real.php
vendored
Normal file
73
vendor/composer/autoload_real.php
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInita47a22c36b23233ed3ce46b8027644b1
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
public static function loadClassLoader($class)
|
||||
{
|
||||
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||
require __DIR__ . '/ClassLoader.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInita47a22c36b23233ed3ce46b8027644b1', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInita47a22c36b23233ed3ce46b8027644b1', 'loadClassLoader'));
|
||||
|
||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
||||
if ($useStaticLoader) {
|
||||
require_once __DIR__ . '/autoload_static.php';
|
||||
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInita47a22c36b23233ed3ce46b8027644b1::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);
|
||||
}
|
||||
}
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
if ($useStaticLoader) {
|
||||
$includeFiles = Composer\Autoload\ComposerStaticInita47a22c36b23233ed3ce46b8027644b1::$files;
|
||||
} else {
|
||||
$includeFiles = require __DIR__ . '/autoload_files.php';
|
||||
}
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequirea47a22c36b23233ed3ce46b8027644b1($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
function composerRequirea47a22c36b23233ed3ce46b8027644b1($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
require $file;
|
||||
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
}
|
||||
}
|
||||
57
vendor/composer/autoload_static.php
vendored
Normal file
57
vendor/composer/autoload_static.php
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInita47a22c36b23233ed3ce46b8027644b1
|
||||
{
|
||||
public static $files = array (
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'e39a8b23c42d4e1452234d762b03835a' => __DIR__ . '/..' . '/ramsey/uuid/src/functions.php',
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'S' =>
|
||||
array (
|
||||
'Symfony\\Polyfill\\Ctype\\' => 23,
|
||||
),
|
||||
'R' =>
|
||||
array (
|
||||
'Ramsey\\Uuid\\' => 12,
|
||||
'Ramsey\\Collection\\' => 18,
|
||||
),
|
||||
'B' =>
|
||||
array (
|
||||
'Brick\\Math\\' => 11,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'Symfony\\Polyfill\\Ctype\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
|
||||
),
|
||||
'Ramsey\\Uuid\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/ramsey/uuid/src',
|
||||
),
|
||||
'Ramsey\\Collection\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/ramsey/collection/src',
|
||||
),
|
||||
'Brick\\Math\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/brick/math/src',
|
||||
),
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInita47a22c36b23233ed3ce46b8027644b1::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInita47a22c36b23233ed3ce46b8027644b1::$prefixDirsPsr4;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
||||
286
vendor/composer/installed.json
vendored
Normal file
286
vendor/composer/installed.json
vendored
Normal file
@@ -0,0 +1,286 @@
|
||||
[
|
||||
{
|
||||
"name": "brick/math",
|
||||
"version": "0.8.15",
|
||||
"version_normalized": "0.8.15.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/brick/math.git",
|
||||
"reference": "9b08d412b9da9455b210459ff71414de7e6241cd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/brick/math/zipball/9b08d412b9da9455b210459ff71414de7e6241cd",
|
||||
"reference": "9b08d412b9da9455b210459ff71414de7e6241cd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": "^7.1|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"php-coveralls/php-coveralls": "^2.2",
|
||||
"phpunit/phpunit": "^7.5.15|^8.5",
|
||||
"vimeo/psalm": "^3.5"
|
||||
},
|
||||
"time": "2020-04-15T15:59:35+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"
|
||||
],
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/brick/math",
|
||||
"type": "tidelift"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ramsey/collection",
|
||||
"version": "1.0.1",
|
||||
"version_normalized": "1.0.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ramsey/collection.git",
|
||||
"reference": "925ad8cf55ba7a3fc92e332c58fd0478ace3e1ca"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ramsey/collection/zipball/925ad8cf55ba7a3fc92e332c58fd0478ace3e1ca",
|
||||
"reference": "925ad8cf55ba7a3fc92e332c58fd0478ace3e1ca",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.5.0",
|
||||
"fzaninotto/faker": "^1.5",
|
||||
"jakub-onderka/php-parallel-lint": "^1",
|
||||
"jangregor/phpstan-prophecy": "^0.6",
|
||||
"mockery/mockery": "^1.3",
|
||||
"phpstan/extension-installer": "^1",
|
||||
"phpstan/phpdoc-parser": "0.4.1",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"phpstan/phpstan-mockery": "^0.12",
|
||||
"phpstan/phpstan-phpunit": "^0.12",
|
||||
"phpunit/phpunit": "^8.5",
|
||||
"slevomat/coding-standard": "^6.0",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"time": "2020-01-05T00:22:59+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Ramsey\\Collection\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ben Ramsey",
|
||||
"email": "ben@benramsey.com",
|
||||
"homepage": "https://benramsey.com"
|
||||
}
|
||||
],
|
||||
"description": "A PHP 7.2+ library for representing and manipulating collections.",
|
||||
"homepage": "https://github.com/ramsey/collection",
|
||||
"keywords": [
|
||||
"array",
|
||||
"collection",
|
||||
"hash",
|
||||
"map",
|
||||
"queue",
|
||||
"set"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ramsey/uuid",
|
||||
"version": "4.1.0",
|
||||
"version_normalized": "4.1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ramsey/uuid.git",
|
||||
"reference": "988dbefc7878d0a35f12afb4df1f7dd0bd153c43"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/988dbefc7878d0a35f12afb4df1f7dd0bd153c43",
|
||||
"reference": "988dbefc7878d0a35f12afb4df1f7dd0bd153c43",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"brick/math": "^0.8",
|
||||
"ext-json": "*",
|
||||
"php": "^7.2 || ^8",
|
||||
"ramsey/collection": "^1.0",
|
||||
"symfony/polyfill-ctype": "^1.8"
|
||||
},
|
||||
"replace": {
|
||||
"rhumsaa/uuid": "self.version"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeception/aspect-mock": "^3",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7.0",
|
||||
"doctrine/annotations": "^1.8",
|
||||
"goaop/framework": "^2",
|
||||
"mockery/mockery": "^1.3",
|
||||
"moontoast/math": "^1.1",
|
||||
"paragonie/random-lib": "^2",
|
||||
"php-mock/php-mock-mockery": "^1.3",
|
||||
"php-mock/php-mock-phpunit": "^2.5",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.1",
|
||||
"phpbench/phpbench": "^0.17.1",
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"phpstan/phpstan-mockery": "^0.12",
|
||||
"phpstan/phpstan-phpunit": "^0.12",
|
||||
"phpunit/phpunit": "^8.5",
|
||||
"psy/psysh": "^0.10.0",
|
||||
"slevomat/coding-standard": "^6.0",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"vimeo/psalm": "3.9.4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
|
||||
"ext-ctype": "Enables faster processing of character classification using ctype functions.",
|
||||
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
|
||||
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
|
||||
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
|
||||
"ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
|
||||
},
|
||||
"time": "2020-07-28T16:51:01+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Ramsey\\Uuid\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
|
||||
"homepage": "https://github.com/ramsey/uuid",
|
||||
"keywords": [
|
||||
"guid",
|
||||
"identifier",
|
||||
"uuid"
|
||||
],
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/ramsey",
|
||||
"type": "github"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.18.1",
|
||||
"version_normalized": "1.18.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "1c302646f6efc070cd46856e600e5e0684d6b454"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/1c302646f6efc070cd46856e600e5e0684d6b454",
|
||||
"reference": "1c302646f6efc070cd46856e600e5e0684d6b454",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-ctype": "For best performance"
|
||||
},
|
||||
"time": "2020-07-14T12:35:20+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.18-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Ctype\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Gert de Pagter",
|
||||
"email": "BackEndTea@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for ctype functions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"ctype",
|
||||
"polyfill",
|
||||
"portable"
|
||||
],
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
103
vendor/ramsey/collection/CHANGELOG.md
vendored
Normal file
103
vendor/ramsey/collection/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
# ramsey/collection Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
### Changed
|
||||
### Deprecated
|
||||
### Removed
|
||||
### Fixed
|
||||
### Security
|
||||
|
||||
## [1.0.1] - 2020-01-04
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed `AbstractCollection::offsetSet()` so that it uses the provided `$offset`
|
||||
when setting `$value` in the array.
|
||||
|
||||
## [1.0.0] - 2018-12-31
|
||||
|
||||
### Added
|
||||
|
||||
* Added support for *queue* data structures to represent collections of ordered
|
||||
entities. Together with *double-ended queues* (a.k.a. *deques*),
|
||||
first-in-first-out (FIFO), last-in-first-out (LIFO), and other queue and stack
|
||||
behaviors may be implemented. This functionality includes interfaces
|
||||
`QueueInterface` and `DoubleEndedQueueInterface` and classes `Queue` and
|
||||
`DoubleEndedQueue`.
|
||||
* Added support for *set* data structures, representing collections that cannot
|
||||
contain any duplicated elements; includes classes `AbstractSet` and `Set`.
|
||||
* Added support for *typed map* data structures to represent maps of elements
|
||||
where both keys and values have specified data types; includes
|
||||
`TypedMapInterface` and the classes `AbstractTypedMap` and `TypedMap`.
|
||||
* Added new manipulation and analyze methods for collections: `column()`,
|
||||
`first()`, `last()`, `sort()`, `filter()`, `where()`, `map()`, `diff()`,
|
||||
`intersect()`, and `merge()`. See [CollectionInterface](https://github.com/ramsey/collection/blob/master/src/CollectionInterface.php)
|
||||
for more information.
|
||||
* Added the following new exceptions specific to the ramsey/collection library:
|
||||
`CollectionMismatchException`, `InvalidArgumentException`,
|
||||
`InvalidSortOrderException`, `NoSuchElementException`, `OutOfBoundsException`,
|
||||
`UnsupportedOperationException`, and `ValueExtractionException`.
|
||||
|
||||
### Changed
|
||||
|
||||
* Minimum PHP version supported is 7.2.
|
||||
* Strict types are enforced throughout.
|
||||
|
||||
### Removed
|
||||
|
||||
* Removed support for HHVM.
|
||||
|
||||
### Security
|
||||
|
||||
* Fixed possible exploit using `AbstractArray::unserialize()`
|
||||
(see [#47](https://github.com/ramsey/collection/issues/47)).
|
||||
|
||||
## [0.3.0] - 2016-05-23
|
||||
|
||||
### Added
|
||||
|
||||
* Added `MapInterface::keys()` method to return the keys from a `MapInterface`
|
||||
object. This was added to the `AbstractMap` class.
|
||||
|
||||
### Removed
|
||||
|
||||
* Removed `getType()` and constructor methods from `AbstractCollection`. Children
|
||||
of `AbstractCollection` must now implement `getType()`, which should return a
|
||||
string value that defines the data type of items for the collection.
|
||||
|
||||
### Fixed
|
||||
|
||||
* Improve error messages in exceptions when `Collection` and `NamedParameterMap`
|
||||
items fail type checks.
|
||||
|
||||
## [0.2.1] - 2016-02-22
|
||||
|
||||
### Fixed
|
||||
|
||||
* Allow non-strict checking of values in typed collections.
|
||||
|
||||
## [0.2.0] - 2016-02-05
|
||||
|
||||
### Added
|
||||
|
||||
* Support typed collections.
|
||||
|
||||
## [0.1.0] - 2015-10-27
|
||||
|
||||
### Added
|
||||
|
||||
* Support generic arrays and maps.
|
||||
|
||||
[Unreleased]: https://github.com/ramsey/collection/compare/1.0.1...HEAD
|
||||
[1.0.1]: https://github.com/ramsey/collection/compare/1.0.0...1.0.1
|
||||
[1.0.0]: https://github.com/ramsey/collection/compare/0.3.0...1.0.0
|
||||
[0.3.0]: https://github.com/ramsey/collection/compare/0.2.1...0.3.0
|
||||
[0.2.1]: https://github.com/ramsey/collection/compare/0.2.0...0.2.1
|
||||
[0.2.0]: https://github.com/ramsey/collection/compare/0.1.0...0.2.0
|
||||
[0.1.0]: https://github.com/ramsey/collection/commits/0.1.0
|
||||
19
vendor/ramsey/collection/LICENSE
vendored
Normal file
19
vendor/ramsey/collection/LICENSE
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2015-2020 Ben Ramsey <ben@benramsey.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
72
vendor/ramsey/collection/README.md
vendored
Normal file
72
vendor/ramsey/collection/README.md
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
# ramsey/collection
|
||||
|
||||
[![Source Code][badge-source]][source]
|
||||
[![Latest Version][badge-release]][release]
|
||||
[![Software License][badge-license]][license]
|
||||
[![Build Status][badge-build]][build]
|
||||
[![Coverage Status][badge-coverage]][coverage]
|
||||
[![Total Downloads][badge-downloads]][downloads]
|
||||
|
||||
ramsey/collection is a PHP 7.2+ library for representing and manipulating collections..
|
||||
|
||||
This project adheres to a [Contributor Code of Conduct][conduct]. By participating in this project and its community, you are expected to uphold this code.
|
||||
|
||||
|
||||
## About
|
||||
|
||||
Much inspiration for this library came from the [Java Collections Framework][java].
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
The preferred method of installation is via [Packagist][] and [Composer][]. Run
|
||||
the following command to install the package and add it as a requirement to
|
||||
your project's `composer.json`:
|
||||
|
||||
```bash
|
||||
composer require ramsey/collection
|
||||
```
|
||||
|
||||
|
||||
## API documentation
|
||||
|
||||
The [latest class API documentation][apidocs] is available online.
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
Examples of how to use this framework can be found in the [Wiki pages](https://github.com/ramsey/collection/wiki/Examples).
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please read [CONTRIBUTING][] for details.
|
||||
|
||||
|
||||
## Copyright and License
|
||||
|
||||
The ramsey/collection library is copyright © [Ben Ramsey](https://benramsey.com/) and licensed for use under the MIT License (MIT). Please see [LICENSE][] for more information.
|
||||
|
||||
|
||||
|
||||
[conduct]: https://github.com/ramsey/collection/blob/master/.github/CODE_OF_CONDUCT.md
|
||||
[java]: http://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html
|
||||
[packagist]: https://packagist.org/packages/ramsey/collection
|
||||
[composer]: http://getcomposer.org/
|
||||
[apidocs]: https://docs.benramsey.com/ramsey-collection/latest/
|
||||
[contributing]: https://github.com/ramsey/collection/blob/master/.github/CONTRIBUTING.md
|
||||
|
||||
[badge-source]: http://img.shields.io/badge/source-ramsey/collection-blue.svg?style=flat-square
|
||||
[badge-release]: https://img.shields.io/github/release/ramsey/collection.svg?style=flat-square
|
||||
[badge-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square
|
||||
[badge-build]: https://img.shields.io/travis/ramsey/collection/master.svg?style=flat-square
|
||||
[badge-coverage]: https://img.shields.io/coveralls/ramsey/collection/master.svg?style=flat-square
|
||||
[badge-downloads]: https://img.shields.io/packagist/dt/ramsey/collection.svg?style=flat-square
|
||||
|
||||
[source]: https://github.com/ramsey/collection
|
||||
[release]: https://github.com/ramsey/collection/releases
|
||||
[license]: https://github.com/ramsey/collection/blob/master/LICENSE
|
||||
[build]: https://travis-ci.org/ramsey/collection
|
||||
[hhvm]: http://hhvm.h4cc.de/package/ramsey/collection
|
||||
[coverage]: https://coveralls.io/r/ramsey/collection?branch=master
|
||||
[downloads]: https://packagist.org/packages/ramsey/collection
|
||||
67
vendor/ramsey/collection/composer.json
vendored
Normal file
67
vendor/ramsey/collection/composer.json
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"name": "ramsey/collection",
|
||||
"description": "A PHP 7.2+ library for representing and manipulating collections.",
|
||||
"type": "library",
|
||||
"keywords": ["array", "collection", "hash", "map", "queue", "set"],
|
||||
"homepage": "https://github.com/ramsey/collection",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ben Ramsey",
|
||||
"email": "ben@benramsey.com",
|
||||
"homepage": "https://benramsey.com"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/ramsey/collection/issues",
|
||||
"source": "https://github.com/ramsey/collection"
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.5.0",
|
||||
"fzaninotto/faker": "^1.5",
|
||||
"jakub-onderka/php-parallel-lint": "^1",
|
||||
"jangregor/phpstan-prophecy": "^0.6",
|
||||
"mockery/mockery": "^1.3",
|
||||
"phpstan/extension-installer": "^1",
|
||||
"phpstan/phpdoc-parser": "0.4.1",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"phpstan/phpstan-mockery": "^0.12",
|
||||
"phpstan/phpstan-phpunit": "^0.12",
|
||||
"phpunit/phpunit": "^8.5",
|
||||
"slevomat/coding-standard": "^6.0",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Ramsey\\Collection\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Ramsey\\Collection\\Test\\": "tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "parallel-lint src tests",
|
||||
"phpcbf": "phpcbf -vpw",
|
||||
"phpcs": "phpcs",
|
||||
"phpstan": [
|
||||
"phpstan analyse src -c phpstan.neon --level max --no-progress",
|
||||
"phpstan analyse tests -c phpstan-tests.neon --level max --no-progress"
|
||||
],
|
||||
"phpunit": "phpunit --verbose --colors=always",
|
||||
"phpunit-coverage": "phpunit --verbose --colors=always --coverage-html build/coverage",
|
||||
"test": [
|
||||
"@lint",
|
||||
"@phpcs",
|
||||
"@phpstan",
|
||||
"@phpunit"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
}
|
||||
}
|
||||
3
vendor/ramsey/collection/phpstan-tests.neon
vendored
Normal file
3
vendor/ramsey/collection/phpstan-tests.neon
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
parameters:
|
||||
checkGenericClassInNonGenericObjectType: false
|
||||
checkMissingIterableValueType: false
|
||||
180
vendor/ramsey/collection/src/AbstractArray.php
vendored
Normal file
180
vendor/ramsey/collection/src/AbstractArray.php
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection;
|
||||
|
||||
use ArrayIterator;
|
||||
use Traversable;
|
||||
|
||||
use function serialize;
|
||||
use function unserialize;
|
||||
|
||||
/**
|
||||
* This class provides a basic implementation of `ArrayInterface`, to minimize
|
||||
* the effort required to implement this interface.
|
||||
*/
|
||||
abstract class AbstractArray implements ArrayInterface
|
||||
{
|
||||
/**
|
||||
* The items of this array.
|
||||
*
|
||||
* @var mixed[]
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* Constructs a new array object.
|
||||
*
|
||||
* @param mixed[] $data The initial items to add to this array.
|
||||
*/
|
||||
public function __construct(array $data = [])
|
||||
{
|
||||
// Invoke offsetSet() for each value added; in this way, sub-classes
|
||||
// may provide additional logic about values added to the array object.
|
||||
foreach ($data as $key => $value) {
|
||||
$this[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator for this array.
|
||||
*
|
||||
* @link http://php.net/manual/en/iteratoraggregate.getiterator.php IteratorAggregate::getIterator()
|
||||
*
|
||||
* @return ArrayIterator<mixed, mixed>
|
||||
*/
|
||||
public function getIterator(): Traversable
|
||||
{
|
||||
return new ArrayIterator($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the given offset exists in this array.
|
||||
*
|
||||
* @link http://php.net/manual/en/arrayaccess.offsetexists.php ArrayAccess::offsetExists()
|
||||
*
|
||||
* @param mixed $offset The offset to check.
|
||||
*/
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
return isset($this->data[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at the specified offset.
|
||||
*
|
||||
* @link http://php.net/manual/en/arrayaccess.offsetget.php ArrayAccess::offsetGet()
|
||||
*
|
||||
* @param mixed $offset The offset for which a value should be returned.
|
||||
*
|
||||
* @return mixed|null the value stored at the offset, or null if the offset
|
||||
* does not exist.
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->data[$offset] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given value to the given offset in the array.
|
||||
*
|
||||
* @link http://php.net/manual/en/arrayaccess.offsetset.php ArrayAccess::offsetSet()
|
||||
*
|
||||
* @param mixed|null $offset The offset to set. If `null`, the value may be
|
||||
* set at a numerically-indexed offset.
|
||||
* @param mixed $value The value to set at the given offset.
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
if ($offset === null) {
|
||||
$this->data[] = $value;
|
||||
} else {
|
||||
$this->data[$offset] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given offset and its value from the array.
|
||||
*
|
||||
* @link http://php.net/manual/en/arrayaccess.offsetunset.php ArrayAccess::offsetUnset()
|
||||
*
|
||||
* @param mixed $offset The offset to remove from the array.
|
||||
*/
|
||||
public function offsetUnset($offset): void
|
||||
{
|
||||
unset($this->data[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a serialized string representation of this array object.
|
||||
*
|
||||
* @link http://php.net/manual/en/serializable.serialize.php Serializable::serialize()
|
||||
*
|
||||
* @return string a PHP serialized string.
|
||||
*/
|
||||
public function serialize(): string
|
||||
{
|
||||
return serialize($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a serialized string representation into an instance object.
|
||||
*
|
||||
* @link http://php.net/manual/en/serializable.unserialize.php Serializable::unserialize()
|
||||
*
|
||||
* @param string $serialized A PHP serialized string to unserialize.
|
||||
*
|
||||
* @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
|
||||
*/
|
||||
public function unserialize($serialized): void
|
||||
{
|
||||
$this->data = unserialize($serialized, ['allowed_classes' => false]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of items in this array.
|
||||
*
|
||||
* @link http://php.net/manual/en/countable.count.php Countable::count()
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all items from this array.
|
||||
*/
|
||||
public function clear(): void
|
||||
{
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a native PHP array representation of this array object.
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if this array is empty.
|
||||
*/
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return count($this->data) === 0;
|
||||
}
|
||||
}
|
||||
355
vendor/ramsey/collection/src/AbstractCollection.php
vendored
Normal file
355
vendor/ramsey/collection/src/AbstractCollection.php
vendored
Normal file
@@ -0,0 +1,355 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection;
|
||||
|
||||
use Ramsey\Collection\Exception\CollectionMismatchException;
|
||||
use Ramsey\Collection\Exception\InvalidArgumentException;
|
||||
use Ramsey\Collection\Exception\InvalidSortOrderException;
|
||||
use Ramsey\Collection\Exception\OutOfBoundsException;
|
||||
use Ramsey\Collection\Exception\ValueExtractionException;
|
||||
use Ramsey\Collection\Tool\TypeTrait;
|
||||
use Ramsey\Collection\Tool\ValueExtractorTrait;
|
||||
use Ramsey\Collection\Tool\ValueToStringTrait;
|
||||
|
||||
use function array_filter;
|
||||
use function array_map;
|
||||
use function array_merge;
|
||||
use function array_search;
|
||||
use function array_udiff;
|
||||
use function array_uintersect;
|
||||
use function current;
|
||||
use function end;
|
||||
use function in_array;
|
||||
use function reset;
|
||||
use function sprintf;
|
||||
use function unserialize;
|
||||
use function usort;
|
||||
|
||||
/**
|
||||
* This class provides a basic implementation of `CollectionInterface`, to
|
||||
* minimize the effort required to implement this interface
|
||||
*/
|
||||
abstract class AbstractCollection extends AbstractArray implements CollectionInterface
|
||||
{
|
||||
use TypeTrait;
|
||||
use ValueToStringTrait;
|
||||
use ValueExtractorTrait;
|
||||
|
||||
/**
|
||||
* Ensures that this collection contains the specified element.
|
||||
*
|
||||
* @param mixed $element The element to add to the collection.
|
||||
*
|
||||
* @return bool `true` if this collection changed as a result of the call.
|
||||
*
|
||||
* @throws InvalidArgumentException when the element does not match the
|
||||
* specified type for this collection.
|
||||
*/
|
||||
public function add($element): bool
|
||||
{
|
||||
$this[] = $element;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if this collection contains the specified element.
|
||||
*
|
||||
* @param mixed $element The element to check whether the collection contains.
|
||||
* @param bool $strict Whether to perform a strict type check on the value.
|
||||
*/
|
||||
public function contains($element, bool $strict = true): bool
|
||||
{
|
||||
return in_array($element, $this->data, $strict);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given value to the given offset in the array.
|
||||
*
|
||||
* @param mixed|null $offset The position to set the value in the array, or
|
||||
* `null` to append the value to the array.
|
||||
* @param mixed $value The value to set at the given offset.
|
||||
*
|
||||
* @throws InvalidArgumentException when the value does not match the
|
||||
* specified type for this collection.
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
if ($this->checkType($this->getType(), $value) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
'Value must be of type ' . $this->getType() . '; value is '
|
||||
. $this->toolValueToString($value)
|
||||
);
|
||||
}
|
||||
|
||||
if ($offset === null) {
|
||||
$this->data[] = $value;
|
||||
} else {
|
||||
$this->data[$offset] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a single instance of the specified element from this collection,
|
||||
* if it is present.
|
||||
*
|
||||
* @param mixed $element The element to remove from the collection.
|
||||
*
|
||||
* @return bool `true` if an element was removed as a result of this call.
|
||||
*/
|
||||
public function remove($element): bool
|
||||
{
|
||||
if (($position = array_search($element, $this->data, true)) !== false) {
|
||||
unset($this->data[$position]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the values from given property or method.
|
||||
*
|
||||
* @param string $propertyOrMethod The property or method name to filter by.
|
||||
*
|
||||
* @return mixed[]
|
||||
*
|
||||
* @throws ValueExtractionException if property or method is not defined.
|
||||
*/
|
||||
public function column(string $propertyOrMethod): array
|
||||
{
|
||||
$temp = [];
|
||||
|
||||
foreach ($this->data as $item) {
|
||||
$temp[] = $this->extractValue($item, $propertyOrMethod);
|
||||
}
|
||||
|
||||
return $temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first item of the collection.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws OutOfBoundsException when the collection is empty.
|
||||
*/
|
||||
public function first()
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
throw new OutOfBoundsException('Can\'t determine first item. Collection is empty');
|
||||
}
|
||||
|
||||
reset($this->data);
|
||||
|
||||
return current($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last item of the collection.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws OutOfBoundsException when the collection is empty.
|
||||
*/
|
||||
public function last()
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
throw new OutOfBoundsException('Can\'t determine last item. Collection is empty');
|
||||
}
|
||||
|
||||
$item = end($this->data);
|
||||
reset($this->data);
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sorted collection.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param string $propertyOrMethod The property or method to sort by.
|
||||
* @param string $order The sort order for the resulting collection (one of
|
||||
* this interface's `SORT_*` constants).
|
||||
*
|
||||
* @return CollectionInterface<mixed, mixed>
|
||||
*
|
||||
* @throws InvalidSortOrderException if neither "asc" nor "desc" was given
|
||||
* as the order.
|
||||
* @throws ValueExtractionException if property or method is not defined.
|
||||
*/
|
||||
public function sort(string $propertyOrMethod, string $order = self::SORT_ASC): CollectionInterface
|
||||
{
|
||||
if (!in_array($order, [self::SORT_ASC, self::SORT_DESC], true)) {
|
||||
throw new InvalidSortOrderException('Invalid sort order given: ' . $order);
|
||||
}
|
||||
|
||||
$collection = clone $this;
|
||||
|
||||
usort($collection->data, function ($a, $b) use ($propertyOrMethod, $order) {
|
||||
$aValue = $this->extractValue($a, $propertyOrMethod);
|
||||
$bValue = $this->extractValue($b, $propertyOrMethod);
|
||||
|
||||
return ($aValue <=> $bValue) * ($order === self::SORT_DESC ? -1 : 1);
|
||||
});
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a filtered collection.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param callable $callback A callable to use for filtering elements.
|
||||
*
|
||||
* @return CollectionInterface<mixed, mixed>
|
||||
*/
|
||||
public function filter(callable $callback): CollectionInterface
|
||||
{
|
||||
$collection = clone $this;
|
||||
$collection->data = array_merge([], array_filter($collection->data, $callback));
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of matching items.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param string $propertyOrMethod The property or method to evaluate.
|
||||
* @param mixed $value The value to match.
|
||||
*
|
||||
* @return CollectionInterface<mixed, mixed>
|
||||
*
|
||||
* @throws ValueExtractionException if property or method is not defined.
|
||||
*/
|
||||
public function where(string $propertyOrMethod, $value): CollectionInterface
|
||||
{
|
||||
return $this->filter(function ($item) use ($propertyOrMethod, $value) {
|
||||
$accessorValue = $this->extractValue($item, $propertyOrMethod);
|
||||
|
||||
return $accessorValue === $value;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a callback to each item of the collection.
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param callable $callback A callable to apply to each item of the
|
||||
* collection.
|
||||
*
|
||||
* @return CollectionInterface<mixed, mixed>
|
||||
*/
|
||||
public function map(callable $callback): CollectionInterface
|
||||
{
|
||||
$collection = clone $this;
|
||||
array_map($callback, $collection->data);
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new collection with divergent items between current and given
|
||||
* collection.
|
||||
*
|
||||
* @param CollectionInterface<mixed, mixed> $other The collection to check for divergent
|
||||
* items.
|
||||
*
|
||||
* @return CollectionInterface<mixed, mixed>
|
||||
*
|
||||
* @throws CollectionMismatchException if the given collection is not of the
|
||||
* same type.
|
||||
*/
|
||||
public function diff(CollectionInterface $other): CollectionInterface
|
||||
{
|
||||
if (!$other instanceof static) {
|
||||
throw new CollectionMismatchException('Collection must be of type ' . static::class);
|
||||
}
|
||||
|
||||
$comparator = function ($a, $b) {
|
||||
return $a === $b ? 0 : -1;
|
||||
};
|
||||
|
||||
$diffAtoB = array_udiff($this->data, $other->data, $comparator);
|
||||
$diffBtoA = array_udiff($other->data, $this->data, $comparator);
|
||||
|
||||
return new static(array_merge($diffAtoB, $diffBtoA));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new collection with intersecting item between current and given
|
||||
* collection.
|
||||
*
|
||||
* @param CollectionInterface<mixed, mixed> $other The collection to check for
|
||||
* intersecting items.
|
||||
*
|
||||
* @return CollectionInterface<mixed, mixed>
|
||||
*
|
||||
* @throws CollectionMismatchException if the given collection is not of the
|
||||
* same type.
|
||||
*/
|
||||
public function intersect(CollectionInterface $other): CollectionInterface
|
||||
{
|
||||
if (!$other instanceof static) {
|
||||
throw new CollectionMismatchException('Collection must be of type ' . static::class);
|
||||
}
|
||||
|
||||
$intersect = array_uintersect($this->data, $other->data, function ($a, $b) {
|
||||
return $a === $b ? 0 : -1;
|
||||
});
|
||||
|
||||
return new static($intersect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge current items and items of given collections into a new one.
|
||||
*
|
||||
* @param CollectionInterface<mixed, mixed> ...$collections The collections to merge.
|
||||
*
|
||||
* @return CollectionInterface<mixed, mixed>
|
||||
*
|
||||
* @throws CollectionMismatchException if any of the given collections are not of the same type.
|
||||
*/
|
||||
public function merge(CollectionInterface ...$collections): CollectionInterface
|
||||
{
|
||||
$temp = [$this->data];
|
||||
|
||||
foreach ($collections as $index => $collection) {
|
||||
if (!$collection instanceof static) {
|
||||
throw new CollectionMismatchException(
|
||||
sprintf('Collection with index %d must be of type %s', $index, static::class)
|
||||
);
|
||||
}
|
||||
|
||||
$temp[] = $collection->toArray();
|
||||
}
|
||||
|
||||
return new static(array_merge(...$temp));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function unserialize($serialized): void
|
||||
{
|
||||
$this->data = unserialize($serialized, ['allowed_classes' => [$this->getType()]]);
|
||||
}
|
||||
}
|
||||
64
vendor/ramsey/collection/src/AbstractSet.php
vendored
Normal file
64
vendor/ramsey/collection/src/AbstractSet.php
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection;
|
||||
|
||||
use Ramsey\Collection\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* This class contains the basic implementation of a collection that does not
|
||||
* allow duplicated values (a set), to minimize the effort required to implement
|
||||
* this specific type of collection.
|
||||
*/
|
||||
abstract class AbstractSet extends AbstractCollection
|
||||
{
|
||||
/**
|
||||
* Adds the specified element to this set, if it is not already present.
|
||||
*
|
||||
* @param mixed $element The element to add to the set.
|
||||
*
|
||||
* @return bool `true` if this set did not already contain the specified
|
||||
* element.
|
||||
*
|
||||
* @throws InvalidArgumentException when the element does not match the
|
||||
* specified type for this set.
|
||||
*/
|
||||
public function add($element): bool
|
||||
{
|
||||
if ($this->contains($element)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return parent::add($element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given value to the given offset in this set, if it is not
|
||||
* already present.
|
||||
*
|
||||
* @param mixed|null $offset The offset is ignored and is treated as `null`.
|
||||
* @param mixed $value The value to set at the given offset.
|
||||
*
|
||||
* @throws InvalidArgumentException when the value does not match the
|
||||
* specified type for this set.
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
if ($this->contains($value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
parent::offsetSet($offset, $value);
|
||||
}
|
||||
}
|
||||
47
vendor/ramsey/collection/src/ArrayInterface.php
vendored
Normal file
47
vendor/ramsey/collection/src/ArrayInterface.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection;
|
||||
|
||||
use ArrayAccess;
|
||||
use Countable;
|
||||
use IteratorAggregate;
|
||||
use Serializable;
|
||||
|
||||
/**
|
||||
* `ArrayInterface` provides traversable array functionality to data types.
|
||||
*/
|
||||
interface ArrayInterface extends
|
||||
ArrayAccess,
|
||||
Countable,
|
||||
IteratorAggregate,
|
||||
Serializable
|
||||
{
|
||||
/**
|
||||
* Removes all items from this array.
|
||||
*/
|
||||
public function clear(): void;
|
||||
|
||||
/**
|
||||
* Returns a native PHP array representation of this array object.
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function toArray(): array;
|
||||
|
||||
/**
|
||||
* Returns `true` if this array is empty.
|
||||
*/
|
||||
public function isEmpty(): bool;
|
||||
}
|
||||
106
vendor/ramsey/collection/src/Collection.php
vendored
Normal file
106
vendor/ramsey/collection/src/Collection.php
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection;
|
||||
|
||||
/**
|
||||
* A collection represents a group of objects.
|
||||
*
|
||||
* Each object in the collection is of a specific, defined type.
|
||||
*
|
||||
* This is a direct implementation of `CollectionInterface`, provided for
|
||||
* the sake of convenience.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* ``` php
|
||||
* $collection = new \Ramsey\Collection\Collection('My\\Foo');
|
||||
* $collection->add(new \My\Foo());
|
||||
* $collection->add(new \My\Foo());
|
||||
*
|
||||
* foreach ($collection as $foo) {
|
||||
* // Do something with $foo
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* It is preferable to subclass `AbstractCollection` to create your own typed
|
||||
* collections. For example:
|
||||
*
|
||||
* ``` php
|
||||
* namespace My\Foo;
|
||||
*
|
||||
* class FooCollection extends \Ramsey\Collection\AbstractCollection
|
||||
* {
|
||||
* public function getType()
|
||||
* {
|
||||
* return 'My\\Foo';
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* And then use it similarly to the earlier example:
|
||||
*
|
||||
* ``` php
|
||||
* $fooCollection = new \My\Foo\FooCollection();
|
||||
* $fooCollection->add(new \My\Foo());
|
||||
* $fooCollection->add(new \My\Foo());
|
||||
*
|
||||
* foreach ($fooCollection as $foo) {
|
||||
* // Do something with $foo
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The benefit with this approach is that you may do type-checking on the
|
||||
* collection object:
|
||||
*
|
||||
* ``` php
|
||||
* if ($collection instanceof \My\Foo\FooCollection) {
|
||||
* // the collection is a collection of My\Foo objects
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class Collection extends AbstractCollection
|
||||
{
|
||||
/**
|
||||
* The type of elements stored in this collection.
|
||||
*
|
||||
* A collection's type is immutable once it is set. For this reason, this
|
||||
* property is set private.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $collectionType;
|
||||
|
||||
/**
|
||||
* Constructs a collection object of the specified type, optionally with the
|
||||
* specified data.
|
||||
*
|
||||
* @param string $collectionType The type (FQCN) associated with this
|
||||
* collection.
|
||||
* @param mixed[] $data The initial items to store in the collection.
|
||||
*/
|
||||
public function __construct(string $collectionType, array $data = [])
|
||||
{
|
||||
$this->collectionType = $collectionType;
|
||||
parent::__construct($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type associated with this collection.
|
||||
*/
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->collectionType;
|
||||
}
|
||||
}
|
||||
196
vendor/ramsey/collection/src/CollectionInterface.php
vendored
Normal file
196
vendor/ramsey/collection/src/CollectionInterface.php
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection;
|
||||
|
||||
/**
|
||||
* A collection represents a group of objects, known as its elements.
|
||||
*
|
||||
* Some collections allow duplicate elements and others do not. Some are ordered
|
||||
* and others unordered.
|
||||
*/
|
||||
interface CollectionInterface extends ArrayInterface
|
||||
{
|
||||
/**
|
||||
* Ascending sort type.
|
||||
*/
|
||||
public const SORT_ASC = 'asc';
|
||||
|
||||
/**
|
||||
* Descending sort type.
|
||||
*/
|
||||
public const SORT_DESC = 'desc';
|
||||
|
||||
/**
|
||||
* Ensures that this collection contains the specified element (optional
|
||||
* operation).
|
||||
*
|
||||
* Returns `true` if this collection changed as a result of the call.
|
||||
* (Returns `false` if this collection does not permit duplicates and
|
||||
* already contains the specified element.)
|
||||
*
|
||||
* Collections that support this operation may place limitations on what
|
||||
* elements may be added to this collection. In particular, some
|
||||
* collections will refuse to add `null` elements, and others will impose
|
||||
* restrictions on the type of elements that may be added. Collection
|
||||
* classes should clearly specify in their documentation any restrictions
|
||||
* on what elements may be added.
|
||||
*
|
||||
* If a collection refuses to add a particular element for any reason other
|
||||
* than that it already contains the element, it must throw an exception
|
||||
* (rather than returning `false`). This preserves the invariant that a
|
||||
* collection always contains the specified element after this call returns.
|
||||
*
|
||||
* @param mixed $element The element to add to the collection.
|
||||
*
|
||||
* @return bool `true` if this collection changed as a result of the call.
|
||||
*/
|
||||
public function add($element): bool;
|
||||
|
||||
/**
|
||||
* Returns `true` if this collection contains the specified element.
|
||||
*
|
||||
* @param mixed $element The element to check whether the collection contains.
|
||||
* @param bool $strict Whether to perform a strict type check on the value.
|
||||
*/
|
||||
public function contains($element, bool $strict = true): bool;
|
||||
|
||||
/**
|
||||
* Returns the type associated with this collection.
|
||||
*/
|
||||
public function getType(): string;
|
||||
|
||||
/**
|
||||
* Removes a single instance of the specified element from this collection,
|
||||
* if it is present.
|
||||
*
|
||||
* @param mixed $element The element to remove from the collection.
|
||||
*
|
||||
* @return bool `true` if an element was removed as a result of this call.
|
||||
*/
|
||||
public function remove($element): bool;
|
||||
|
||||
/**
|
||||
* Returns the values from the given property or method.
|
||||
*
|
||||
* @param string $propertyOrMethod The property or method name to filter by.
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function column(string $propertyOrMethod): array;
|
||||
|
||||
/**
|
||||
* Returns the first item of the collection.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function first();
|
||||
|
||||
/**
|
||||
* Returns the last item of the collection.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function last();
|
||||
|
||||
/**
|
||||
* Sort the collection by a property or method with the given sort order.
|
||||
*
|
||||
* This will always leave the original collection untouched and will return
|
||||
* a new one.
|
||||
*
|
||||
* @param string $propertyOrMethod The property or method to sort by.
|
||||
* @param string $order The sort order for the resulting collection (one of
|
||||
* this interface's `SORT_*` constants).
|
||||
*
|
||||
* @return CollectionInterface<mixed, mixed>
|
||||
*/
|
||||
public function sort(string $propertyOrMethod, string $order = self::SORT_ASC): self;
|
||||
|
||||
/**
|
||||
* Filter out items of the collection which don't match the criteria of
|
||||
* given callback.
|
||||
*
|
||||
* This will always leave the original collection untouched and will return
|
||||
* a new one.
|
||||
*
|
||||
* See the {@link http://php.net/manual/en/function.array-filter.php PHP array_filter() documentation}
|
||||
* for examples of how the `$callback` parameter works.
|
||||
*
|
||||
* @param callable $callback A callable to use for filtering elements.
|
||||
*
|
||||
* @return CollectionInterface<mixed, mixed>
|
||||
*/
|
||||
public function filter(callable $callback): self;
|
||||
|
||||
/**
|
||||
* Create a new collection where items match the criteria of given callback.
|
||||
*
|
||||
* This will always leave the original collection untouched and will return
|
||||
* a new one.
|
||||
*
|
||||
* @param string $propertyOrMethod The property or method to evaluate.
|
||||
* @param mixed $value The value to match.
|
||||
*
|
||||
* @return CollectionInterface<mixed, mixed>
|
||||
*/
|
||||
public function where(string $propertyOrMethod, $value): self;
|
||||
|
||||
/**
|
||||
* Apply a given callback method on each item of the collection.
|
||||
*
|
||||
* This will always leave the original collection untouched and will return
|
||||
* a new one.
|
||||
*
|
||||
* See the {@link http://php.net/manual/en/function.array-map.php PHP array_map() documentation}
|
||||
* for examples of how the `$callback` parameter works.
|
||||
*
|
||||
* @param callable $callback A callable to apply to each item of the
|
||||
* collection.
|
||||
*
|
||||
* @return CollectionInterface<mixed, mixed>
|
||||
*/
|
||||
public function map(callable $callback): self;
|
||||
|
||||
/**
|
||||
* Create a new collection with divergent items between current and given
|
||||
* collection.
|
||||
*
|
||||
* @param CollectionInterface<mixed, mixed> $other The collection to check for divergent
|
||||
* items.
|
||||
*
|
||||
* @return CollectionInterface<mixed, mixed>
|
||||
*/
|
||||
public function diff(CollectionInterface $other): self;
|
||||
|
||||
/**
|
||||
* Create a new collection with intersecting item between current and given
|
||||
* collection.
|
||||
*
|
||||
* @param CollectionInterface<mixed, mixed> $other The collection to check for
|
||||
* intersecting items.
|
||||
*
|
||||
* @return CollectionInterface<mixed, mixed>
|
||||
*/
|
||||
public function intersect(CollectionInterface $other): self;
|
||||
|
||||
/**
|
||||
* Merge current items and items of given collections into a new one.
|
||||
*
|
||||
* @param CollectionInterface<mixed, mixed> ...$collections The collections to merge.
|
||||
*
|
||||
* @return CollectionInterface<mixed, mixed>
|
||||
*/
|
||||
public function merge(CollectionInterface ...$collections): self;
|
||||
}
|
||||
288
vendor/ramsey/collection/src/DoubleEndedQueue.php
vendored
Normal file
288
vendor/ramsey/collection/src/DoubleEndedQueue.php
vendored
Normal file
@@ -0,0 +1,288 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection;
|
||||
|
||||
use Ramsey\Collection\Exception\InvalidArgumentException;
|
||||
use Ramsey\Collection\Exception\NoSuchElementException;
|
||||
|
||||
/**
|
||||
* This class provides a basic implementation of `DoubleEndedQueueInterface`, to
|
||||
* minimize the effort required to implement this interface.
|
||||
*/
|
||||
class DoubleEndedQueue extends Queue implements DoubleEndedQueueInterface
|
||||
{
|
||||
/**
|
||||
* Index of the last element in the queue.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $tail = -1;
|
||||
|
||||
/**
|
||||
* Sets the given value to the given offset in the queue.
|
||||
*
|
||||
* Since arbitrary offsets may not be manipulated in a queue, this method
|
||||
* serves only to fulfill the `ArrayAccess` interface requirements. It is
|
||||
* invoked by other operations when adding values to the queue.
|
||||
*
|
||||
* @link http://php.net/manual/en/arrayaccess.offsetset.php ArrayAccess::offsetSet()
|
||||
*
|
||||
* @param mixed|null $offset The offset is ignored and is treated as `null`.
|
||||
* @param mixed $value The value to set at the given offset.
|
||||
*
|
||||
* @throws InvalidArgumentException when the value does not match the
|
||||
* specified type for this queue.
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
if ($this->checkType($this->getType(), $value) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
'Value must be of type ' . $this->getType() . '; value is '
|
||||
. $this->toolValueToString($value)
|
||||
);
|
||||
}
|
||||
|
||||
$this->tail++;
|
||||
|
||||
$this->data[$this->tail] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the specified element is inserted at the front of this queue.
|
||||
*
|
||||
* @see self::offerFirst()
|
||||
*
|
||||
* @param mixed $element The element to add to this queue.
|
||||
*
|
||||
* @return bool `true` if this queue changed as a result of the call.
|
||||
*
|
||||
* @throws InvalidArgumentException when the value does not match the
|
||||
* specified type for this queue.
|
||||
*/
|
||||
public function addFirst($element): bool
|
||||
{
|
||||
if ($this->checkType($this->getType(), $element) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
'Value must be of type ' . $this->getType() . '; value is '
|
||||
. $this->toolValueToString($element)
|
||||
);
|
||||
}
|
||||
|
||||
$this->index--;
|
||||
|
||||
$this->data[$this->index] = $element;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the specified element in inserted at the end of this queue.
|
||||
*
|
||||
* @see Queue::add()
|
||||
*
|
||||
* @param mixed $element The element to add to this queue.
|
||||
*
|
||||
* @return bool `true` if this queue changed as a result of the call.
|
||||
*
|
||||
* @throws InvalidArgumentException when the value does not match the
|
||||
* specified type for this queue.
|
||||
*/
|
||||
public function addLast($element): bool
|
||||
{
|
||||
return $this->add($element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the front this queue.
|
||||
*
|
||||
* @see self::addFirst()
|
||||
*
|
||||
* @param mixed $element The element to add to this queue.
|
||||
*
|
||||
* @return bool `true` if the element was added to this queue, else `false`.
|
||||
*/
|
||||
public function offerFirst($element): bool
|
||||
{
|
||||
try {
|
||||
return $this->addFirst($element);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the end this queue.
|
||||
*
|
||||
* @see self::addLast()
|
||||
* @see Queue::offer()
|
||||
*
|
||||
* @param mixed $element The element to add to this queue.
|
||||
*
|
||||
* @return bool `true` if the element was added to this queue, else `false`.
|
||||
*/
|
||||
public function offerLast($element): bool
|
||||
{
|
||||
return $this->offer($element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of this queue.
|
||||
*
|
||||
* This method differs from `pollFirst()` only in that it throws an
|
||||
* exception if this queue is empty.
|
||||
*
|
||||
* @see self::pollFirst()
|
||||
* @see Queue::remove()
|
||||
*
|
||||
* @return mixed the head of this queue.
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function removeFirst()
|
||||
{
|
||||
return $this->remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and removes the tail of this queue.
|
||||
*
|
||||
* This method differs from `pollLast()` only in that it throws an exception
|
||||
* if this queue is empty.
|
||||
*
|
||||
* @see self::pollLast()
|
||||
*
|
||||
* @return mixed the tail of this queue.
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function removeLast()
|
||||
{
|
||||
if ($this->count() === 0) {
|
||||
throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
|
||||
}
|
||||
|
||||
$tail = $this[$this->tail];
|
||||
|
||||
unset($this[$this->tail]);
|
||||
$this->tail--;
|
||||
|
||||
return $tail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of this queue, or returns `null` if this
|
||||
* queue is empty.
|
||||
*
|
||||
* @see self::removeFirst()
|
||||
*
|
||||
* @return mixed|null the head of this queue, or `null` if this queue is empty.
|
||||
*/
|
||||
public function pollFirst()
|
||||
{
|
||||
return $this->poll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and removes the tail of this queue, or returns `null` if this
|
||||
* queue is empty.
|
||||
*
|
||||
* @see self::removeLast()
|
||||
*
|
||||
* @return mixed|null the tail of this queue, or `null` if this queue is empty.
|
||||
*/
|
||||
public function pollLast()
|
||||
{
|
||||
if ($this->count() === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$tail = $this[$this->tail];
|
||||
|
||||
unset($this[$this->tail]);
|
||||
$this->tail--;
|
||||
|
||||
return $tail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the head of this queue.
|
||||
*
|
||||
* This method differs from `peekFirst()` only in that it throws an
|
||||
* exception if this queue is empty.
|
||||
*
|
||||
* @see self::peekFirst()
|
||||
* @see Queue::element()
|
||||
*
|
||||
* @return mixed the head of this queue.
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function firstElement()
|
||||
{
|
||||
return $this->element();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the tail of this queue.
|
||||
*
|
||||
* This method differs from `peekLast()` only in that it throws an exception
|
||||
* if this queue is empty.
|
||||
*
|
||||
* @see self::peekLast()
|
||||
*
|
||||
* @return mixed the tail of this queue.
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function lastElement()
|
||||
{
|
||||
if ($this->count() === 0) {
|
||||
throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
|
||||
}
|
||||
|
||||
return $this->data[$this->tail];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the head of this queue, or returns `null`
|
||||
* if this queue is empty.
|
||||
*
|
||||
* @see self::firstElement()
|
||||
* @see Queue::peek()
|
||||
*
|
||||
* @return mixed|null the head of this queue, or `null` if this queue is empty.
|
||||
*/
|
||||
public function peekFirst()
|
||||
{
|
||||
return $this->peek();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the tail of this queue, or returns `null`
|
||||
* if this queue is empty.
|
||||
*
|
||||
* @see self::lastElement()
|
||||
*
|
||||
* @return mixed|null the tail of this queue, or `null` if this queue is empty
|
||||
*/
|
||||
public function peekLast()
|
||||
{
|
||||
if ($this->count() === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->data[$this->tail];
|
||||
}
|
||||
}
|
||||
309
vendor/ramsey/collection/src/DoubleEndedQueueInterface.php
vendored
Normal file
309
vendor/ramsey/collection/src/DoubleEndedQueueInterface.php
vendored
Normal file
@@ -0,0 +1,309 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection;
|
||||
|
||||
use Ramsey\Collection\Exception\NoSuchElementException;
|
||||
|
||||
/**
|
||||
* A linear collection that supports element insertion and removal at both ends.
|
||||
*
|
||||
* Most `DoubleEndedQueueInterface` implementations place no fixed limits on the
|
||||
* number of elements they may contain, but this interface supports
|
||||
* capacity-restricted double-ended queues as well as those with no fixed size
|
||||
* limit.
|
||||
*
|
||||
* This interface defines methods to access the elements at both ends of the
|
||||
* double-ended queue. Methods are provided to insert, remove, and examine the
|
||||
* element. Each of these methods exists in two forms: one throws an exception
|
||||
* if the operation fails, the other returns a special value (either `null` or
|
||||
* `false`, depending on the operation). The latter form of the insert operation
|
||||
* is designed specifically for use with capacity-restricted implementations; in
|
||||
* most implementations, insert operations cannot fail.
|
||||
*
|
||||
* The twelve methods described above are summarized in the following table:
|
||||
*
|
||||
* <table>
|
||||
* <caption>Summary of DoubleEndedQueueInterface methods</caption>
|
||||
* <thead>
|
||||
* <tr>
|
||||
* <th></th>
|
||||
* <th colspan=2>First Element (Head)</th>
|
||||
* <th colspan=2>Last Element (Tail)</th>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td><em>Throws exception</em></td>
|
||||
* <td><em>Special value</em></td>
|
||||
* <td><em>Throws exception</em></td>
|
||||
* <td><em>Special value</em></td>
|
||||
* </tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr>
|
||||
* <th>Insert</th>
|
||||
* <td><code>addFirst()</code></td>
|
||||
* <td><code>offerFirst()</code></td>
|
||||
* <td><code>addLast()</code></td>
|
||||
* <td><code>offerLast()</code></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th>Remove</th>
|
||||
* <td><code>removeFirst()</code></td>
|
||||
* <td><code>pollFirst()</code></td>
|
||||
* <td><code>removeLast()</code></td>
|
||||
* <td><code>pollLast()</code></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th>Examine</th>
|
||||
* <td><code>firstElement()</code></td>
|
||||
* <td><code>peekFirst()</code></td>
|
||||
* <td><code>lastElement()</code></td>
|
||||
* <td><code>peekLast()</code></td>
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
*
|
||||
* This interface extends the `QueueInterface`. When a double-ended queue is
|
||||
* used as a queue, FIFO (first-in-first-out) behavior results. Elements are
|
||||
* added at the end of the double-ended queue and removed from the beginning.
|
||||
* The methods inherited from the `QueueInterface` are precisely equivalent to
|
||||
* `DoubleEndedQueueInterface` methods as indicated in the following table:
|
||||
*
|
||||
* <table>
|
||||
* <caption>Comparison of QueueInterface and DoubleEndedQueueInterface methods</caption>
|
||||
* <thead>
|
||||
* <tr>
|
||||
* <th>QueueInterface Method</th>
|
||||
* <th>DoubleEndedQueueInterface Method</th>
|
||||
* </tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr>
|
||||
* <td><code>add()</code></td>
|
||||
* <td><code>addLast()</code></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><code>offer()</code></td>
|
||||
* <td><code>offerLast()</code></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><code>remove()</code></td>
|
||||
* <td><code>removeFirst()</code></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><code>poll()</code></td>
|
||||
* <td><code>pollFirst()</code></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><code>element()</code></td>
|
||||
* <td><code>firstElement()</code></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><code>peek()</code></td>
|
||||
* <td><code>peekFirst()</code></td>
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
*
|
||||
* Double-ended queues can also be used as LIFO (last-in-first-out) stacks. When
|
||||
* a double-ended queue is used as a stack, elements are pushed and popped from
|
||||
* the beginning of the double-ended queue. Stack concepts are precisely
|
||||
* equivalent to `DoubleEndedQueueInterface` methods as indicated in the table
|
||||
* below:
|
||||
*
|
||||
* <table>
|
||||
* <caption>Comparison of stack concepts and DoubleEndedQueueInterface methods</caption>
|
||||
* <thead>
|
||||
* <tr>
|
||||
* <th>Stack concept</th>
|
||||
* <th>DoubleEndedQueueInterface Method</th>
|
||||
* </tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr>
|
||||
* <td><em>push</em></td>
|
||||
* <td><code>addFirst()</code></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><em>pop</em></td>
|
||||
* <td><code>removeFirst()</code></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><em>peek</em></td>
|
||||
* <td><code>peekFirst()</code></td>
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
*
|
||||
* Note that the `peek()` method works equally well when a double-ended queue is
|
||||
* used as a queue or a stack; in either case, elements are drawn from the
|
||||
* beginning of the double-ended queue.
|
||||
*
|
||||
* While `DoubleEndedQueueInterface` implementations are not strictly required
|
||||
* to prohibit the insertion of `null` elements, they are strongly encouraged to
|
||||
* do so. Users of any `DoubleEndedQueueInterface` implementations that do allow
|
||||
* `null` elements are strongly encouraged *not* to take advantage of the
|
||||
* ability to insert nulls. This is so because `null` is used as a special
|
||||
* return value by various methods to indicated that the double-ended queue is
|
||||
* empty.
|
||||
*/
|
||||
interface DoubleEndedQueueInterface extends QueueInterface
|
||||
{
|
||||
/**
|
||||
* Inserts the specified element at the front of this queue if it is
|
||||
* possible to do so immediately without violating capacity restrictions.
|
||||
*
|
||||
* When using a capacity-restricted double-ended queue, it is generally
|
||||
* preferable to use the `offerFirst()` method.
|
||||
*
|
||||
* @param mixed $element The element to add to the front of this queue.
|
||||
*
|
||||
* @return bool `true` if this queue changed as a result of the call.
|
||||
*
|
||||
* @throws \RuntimeException if a queue refuses to add a particular element
|
||||
* for any reason other than that it already contains the element.
|
||||
* Implementations should use a more-specific exception that extends
|
||||
* `\RuntimeException`.
|
||||
*/
|
||||
public function addFirst($element): bool;
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the end of this queue if it is possible
|
||||
* to do so immediately without violating capacity restrictions.
|
||||
*
|
||||
* When using a capacity-restricted double-ended queue, it is generally
|
||||
* preferable to use the `offerLast()` method.
|
||||
*
|
||||
* This method is equivalent to `add()`.
|
||||
*
|
||||
* @param mixed $element The element to add to the end of this queue.
|
||||
*
|
||||
* @return bool `true` if this queue changed as a result of the call.
|
||||
*
|
||||
* @throws \RuntimeException if a queue refuses to add a particular element
|
||||
* for any reason other than that it already contains the element.
|
||||
* Implementations should use a more-specific exception that extends
|
||||
* `\RuntimeException`.
|
||||
*/
|
||||
public function addLast($element): bool;
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the front of this queue if it is
|
||||
* possible to do so immediately without violating capacity restrictions.
|
||||
*
|
||||
* When using a capacity-restricted queue, this method is generally
|
||||
* preferable to `addFirst()`, which can fail to insert an element only by
|
||||
* throwing an exception.
|
||||
*
|
||||
* @param mixed $element The element to add to the front of this queue.
|
||||
*
|
||||
* @return bool `true` if the element was added to this queue, else `false`.
|
||||
*/
|
||||
public function offerFirst($element): bool;
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the end of this queue if it is possible
|
||||
* to do so immediately without violating capacity restrictions.
|
||||
*
|
||||
* When using a capacity-restricted queue, this method is generally
|
||||
* preferable to `addLast()` which can fail to insert an element only by
|
||||
* throwing an exception.
|
||||
*
|
||||
* @param mixed $element The element to add to the end of this queue.
|
||||
*
|
||||
* @return bool `true` if the element was added to this queue, else `false`.
|
||||
*/
|
||||
public function offerLast($element): bool;
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of this queue.
|
||||
*
|
||||
* This method differs from `pollFirst()` only in that it throws an
|
||||
* exception if this queue is empty.
|
||||
*
|
||||
* @return mixed the first element in this queue.
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function removeFirst();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the tail of this queue.
|
||||
*
|
||||
* This method differs from `pollLast()` only in that it throws an exception
|
||||
* if this queue is empty.
|
||||
*
|
||||
* @return mixed the last element in this queue.
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function removeLast();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of this queue, or returns `null` if this
|
||||
* queue is empty.
|
||||
*
|
||||
* @return mixed|null the head of this queue, or `null` if this queue is empty.
|
||||
*/
|
||||
public function pollFirst();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the tail of this queue, or returns `null` if this
|
||||
* queue is empty.
|
||||
*
|
||||
* @return mixed|null the tail of this queue, or `null` if this queue is empty.
|
||||
*/
|
||||
public function pollLast();
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the head of this queue.
|
||||
*
|
||||
* This method differs from `peekFirst()` only in that it throws an
|
||||
* exception if this queue is empty.
|
||||
*
|
||||
* @return mixed the head of this queue.
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function firstElement();
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the tail of this queue.
|
||||
*
|
||||
* This method differs from `peekLast()` only in that it throws an exception
|
||||
* if this queue is empty.
|
||||
*
|
||||
* @return mixed the tail of this queue.
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function lastElement();
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the head of this queue, or returns `null`
|
||||
* if this queue is empty.
|
||||
*
|
||||
* @return mixed|null the head of this queue, or `null` if this queue is empty.
|
||||
*/
|
||||
public function peekFirst();
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the tail of this queue, or returns `null`
|
||||
* if this queue is empty.
|
||||
*
|
||||
* @return mixed|null the tail of this queue, or `null` if this queue is empty.
|
||||
*/
|
||||
public function peekLast();
|
||||
}
|
||||
22
vendor/ramsey/collection/src/Exception/CollectionMismatchException.php
vendored
Normal file
22
vendor/ramsey/collection/src/Exception/CollectionMismatchException.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when attempting to operate on collections of differing types.
|
||||
*/
|
||||
class CollectionMismatchException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
22
vendor/ramsey/collection/src/Exception/InvalidArgumentException.php
vendored
Normal file
22
vendor/ramsey/collection/src/Exception/InvalidArgumentException.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Exception;
|
||||
|
||||
/**
|
||||
* Thrown to indicate an argument is not of the expected type.
|
||||
*/
|
||||
class InvalidArgumentException extends \InvalidArgumentException
|
||||
{
|
||||
}
|
||||
22
vendor/ramsey/collection/src/Exception/InvalidSortOrderException.php
vendored
Normal file
22
vendor/ramsey/collection/src/Exception/InvalidSortOrderException.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when attempting to use a sort order that is not recognized.
|
||||
*/
|
||||
class InvalidSortOrderException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
22
vendor/ramsey/collection/src/Exception/NoSuchElementException.php
vendored
Normal file
22
vendor/ramsey/collection/src/Exception/NoSuchElementException.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when attempting to access an element that does not exist.
|
||||
*/
|
||||
class NoSuchElementException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
22
vendor/ramsey/collection/src/Exception/OutOfBoundsException.php
vendored
Normal file
22
vendor/ramsey/collection/src/Exception/OutOfBoundsException.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when attempting to access an element out of the range of the collection.
|
||||
*/
|
||||
class OutOfBoundsException extends \OutOfBoundsException
|
||||
{
|
||||
}
|
||||
22
vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php
vendored
Normal file
22
vendor/ramsey/collection/src/Exception/UnsupportedOperationException.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Exception;
|
||||
|
||||
/**
|
||||
* Thrown to indicate that the requested operation is not supported.
|
||||
*/
|
||||
class UnsupportedOperationException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
22
vendor/ramsey/collection/src/Exception/ValueExtractionException.php
vendored
Normal file
22
vendor/ramsey/collection/src/Exception/ValueExtractionException.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when attempting to extract a value for a method or property that does not exist.
|
||||
*/
|
||||
class ValueExtractionException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
22
vendor/ramsey/collection/src/GenericArray.php
vendored
Normal file
22
vendor/ramsey/collection/src/GenericArray.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection;
|
||||
|
||||
/**
|
||||
* `GenericArray` represents a standard array object.
|
||||
*/
|
||||
class GenericArray extends AbstractArray
|
||||
{
|
||||
}
|
||||
226
vendor/ramsey/collection/src/Map/AbstractMap.php
vendored
Normal file
226
vendor/ramsey/collection/src/Map/AbstractMap.php
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Map;
|
||||
|
||||
use Ramsey\Collection\AbstractArray;
|
||||
use Ramsey\Collection\Exception\InvalidArgumentException;
|
||||
|
||||
use function array_key_exists;
|
||||
use function array_keys;
|
||||
use function in_array;
|
||||
|
||||
/**
|
||||
* This class provides a basic implementation of `MapInterface`, to minimize the
|
||||
* effort required to implement this interface.
|
||||
*/
|
||||
abstract class AbstractMap extends AbstractArray implements MapInterface
|
||||
{
|
||||
/**
|
||||
* Sets the given value to the given offset in the map.
|
||||
*
|
||||
* @param mixed $offset The offset to set.
|
||||
* @param mixed $value The value to set at the given offset.
|
||||
*
|
||||
* @throws InvalidArgumentException if the offset provided is `null`.
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
if ($offset === null) {
|
||||
throw new InvalidArgumentException(
|
||||
'Map elements are key/value pairs; a key must be provided for '
|
||||
. 'value ' . $value
|
||||
);
|
||||
}
|
||||
|
||||
$this->data[$offset] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if this map contains a mapping for the specified key.
|
||||
*
|
||||
* @param mixed $key The key to check in the map.
|
||||
*/
|
||||
public function containsKey($key): bool
|
||||
{
|
||||
return array_key_exists($key, $this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if this map maps one or more keys to the specified value.
|
||||
*
|
||||
* This performs a strict type check on the value.
|
||||
*
|
||||
* @param mixed $value The value to check in the map.
|
||||
*/
|
||||
public function containsValue($value): bool
|
||||
{
|
||||
return in_array($value, $this->data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of the keys contained in this map.
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function keys(): array
|
||||
{
|
||||
return array_keys($this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value to which the specified key is mapped, `null` if this
|
||||
* map contains no mapping for the key, or (optionally) `$defaultValue` if
|
||||
* this map contains no mapping for the key.
|
||||
*
|
||||
* @param mixed $key The key to return from the map.
|
||||
* @param mixed $defaultValue The default value to use if `$key` is not found.
|
||||
*
|
||||
* @return mixed|null the value or `null` if the key could not be found.
|
||||
*/
|
||||
public function get($key, $defaultValue = null)
|
||||
{
|
||||
if (!$this->containsKey($key)) {
|
||||
return $defaultValue;
|
||||
}
|
||||
|
||||
return $this[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates the specified value with the specified key in this map.
|
||||
*
|
||||
* If the map previously contained a mapping for the key, the old value is
|
||||
* replaced by the specified value.
|
||||
*
|
||||
* @param mixed $key The key to put or replace in the map.
|
||||
* @param mixed $value The value to store at `$key`.
|
||||
*
|
||||
* @return mixed|null the previous value associated with key, or `null` if
|
||||
* there was no mapping for `$key`.
|
||||
*/
|
||||
public function put($key, $value)
|
||||
{
|
||||
$previousValue = $this->get($key);
|
||||
$this[$key] = $value;
|
||||
|
||||
return $previousValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates the specified value with the specified key in this map only if
|
||||
* it is not already set.
|
||||
*
|
||||
* If there is already a value associated with `$key`, this returns that
|
||||
* value without replacing it.
|
||||
*
|
||||
* @param mixed $key The key to put in the map.
|
||||
* @param mixed $value The value to store at `$key`.
|
||||
*
|
||||
* @return mixed|null the previous value associated with key, or `null` if
|
||||
* there was no mapping for `$key`.
|
||||
*/
|
||||
public function putIfAbsent($key, $value)
|
||||
{
|
||||
$currentValue = $this->get($key);
|
||||
|
||||
if ($currentValue === null) {
|
||||
$this[$key] = $value;
|
||||
}
|
||||
|
||||
return $currentValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the mapping for a key from this map if it is present.
|
||||
*
|
||||
* @param mixed $key The key to remove from the map.
|
||||
*
|
||||
* @return mixed|null the previous value associated with key, or `null` if
|
||||
* there was no mapping for `$key`.
|
||||
*/
|
||||
public function remove($key)
|
||||
{
|
||||
$previousValue = $this->get($key);
|
||||
unset($this[$key]);
|
||||
|
||||
return $previousValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the entry for the specified key only if it is currently mapped to
|
||||
* the specified value.
|
||||
*
|
||||
* This performs a strict type check on the value.
|
||||
*
|
||||
* @param mixed $key The key to remove from the map.
|
||||
* @param mixed $value The value to match.
|
||||
*
|
||||
* @return bool true if the value was removed.
|
||||
*/
|
||||
public function removeIf($key, $value): bool
|
||||
{
|
||||
if ($this->get($key) === $value) {
|
||||
unset($this[$key]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the entry for the specified key only if it is currently mapped
|
||||
* to some value.
|
||||
*
|
||||
* @param mixed $key The key to replace.
|
||||
* @param mixed $value The value to set at `$key`.
|
||||
*
|
||||
* @return mixed|null the previous value associated with key, or `null` if
|
||||
* there was no mapping for `$key`.
|
||||
*/
|
||||
public function replace($key, $value)
|
||||
{
|
||||
$currentValue = $this->get($key);
|
||||
|
||||
if ($this->containsKey($key)) {
|
||||
$this[$key] = $value;
|
||||
}
|
||||
|
||||
return $currentValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the entry for the specified key only if currently mapped to the
|
||||
* specified value.
|
||||
*
|
||||
* This performs a strict type check on the value.
|
||||
*
|
||||
* @param mixed $key The key to remove from the map.
|
||||
* @param mixed $oldValue The value to match.
|
||||
* @param mixed $newValue The value to use as a replacement.
|
||||
*
|
||||
* @return bool true if the value was replaced.
|
||||
*/
|
||||
public function replaceIf($key, $oldValue, $newValue): bool
|
||||
{
|
||||
if ($this->get($key) === $oldValue) {
|
||||
$this[$key] = $newValue;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
57
vendor/ramsey/collection/src/Map/AbstractTypedMap.php
vendored
Normal file
57
vendor/ramsey/collection/src/Map/AbstractTypedMap.php
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Map;
|
||||
|
||||
use Ramsey\Collection\Exception\InvalidArgumentException;
|
||||
use Ramsey\Collection\Tool\TypeTrait;
|
||||
use Ramsey\Collection\Tool\ValueToStringTrait;
|
||||
|
||||
/**
|
||||
* This class provides a basic implementation of `TypedMapInterface`, to
|
||||
* minimize the effort required to implement this interface.
|
||||
*/
|
||||
abstract class AbstractTypedMap extends AbstractMap implements TypedMapInterface
|
||||
{
|
||||
use TypeTrait;
|
||||
use ValueToStringTrait;
|
||||
|
||||
/**
|
||||
* Sets the given value to the given offset in the map.
|
||||
*
|
||||
* @param mixed $offset The offset to set.
|
||||
* @param mixed $value The value to set at the given offset.
|
||||
*
|
||||
* @throws InvalidArgumentException if the offset or value do not match the
|
||||
* expected types.
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
if ($this->checkType($this->getKeyType(), $offset) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
'Key must be of type ' . $this->getKeyType() . '; key is '
|
||||
. $this->toolValueToString($offset)
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->checkType($this->getValueType(), $value) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
'Value must be of type ' . $this->getValueType() . '; value is '
|
||||
. $this->toolValueToString($value)
|
||||
);
|
||||
}
|
||||
|
||||
parent::offsetSet($offset, $value);
|
||||
}
|
||||
}
|
||||
22
vendor/ramsey/collection/src/Map/AssociativeArrayMap.php
vendored
Normal file
22
vendor/ramsey/collection/src/Map/AssociativeArrayMap.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Map;
|
||||
|
||||
/**
|
||||
* `AssociativeArrayMap` represents a standard associative array object.
|
||||
*/
|
||||
class AssociativeArrayMap extends AbstractMap
|
||||
{
|
||||
}
|
||||
138
vendor/ramsey/collection/src/Map/MapInterface.php
vendored
Normal file
138
vendor/ramsey/collection/src/Map/MapInterface.php
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Map;
|
||||
|
||||
use Ramsey\Collection\ArrayInterface;
|
||||
|
||||
/**
|
||||
* An object that maps keys to values.
|
||||
*
|
||||
* A map cannot contain duplicate keys; each key can map to at most one value.
|
||||
*/
|
||||
interface MapInterface extends ArrayInterface
|
||||
{
|
||||
/**
|
||||
* Returns `true` if this map contains a mapping for the specified key.
|
||||
*
|
||||
* @param mixed $key The key to check in the map.
|
||||
*/
|
||||
public function containsKey($key): bool;
|
||||
|
||||
/**
|
||||
* Returns `true` if this map maps one or more keys to the specified value.
|
||||
*
|
||||
* This performs a strict type check on the value.
|
||||
*
|
||||
* @param mixed $value The value to check in the map.
|
||||
*/
|
||||
public function containsValue($value): bool;
|
||||
|
||||
/**
|
||||
* Return an array of the keys contained in this map.
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function keys(): array;
|
||||
|
||||
/**
|
||||
* Returns the value to which the specified key is mapped, `null` if this
|
||||
* map contains no mapping for the key, or (optionally) `$defaultValue` if
|
||||
* this map contains no mapping for the key.
|
||||
*
|
||||
* @param mixed $key The key to return from the map.
|
||||
* @param mixed $defaultValue The default value to use if `$key` is not found.
|
||||
*
|
||||
* @return mixed|null the value or `null` if the key could not be found.
|
||||
*/
|
||||
public function get($key, $defaultValue = null);
|
||||
|
||||
/**
|
||||
* Associates the specified value with the specified key in this map.
|
||||
*
|
||||
* If the map previously contained a mapping for the key, the old value is
|
||||
* replaced by the specified value.
|
||||
*
|
||||
* @param mixed $key The key to put or replace in the map.
|
||||
* @param mixed $value The value to store at `$key`.
|
||||
*
|
||||
* @return mixed|null the previous value associated with key, or `null` if
|
||||
* there was no mapping for `$key`.
|
||||
*/
|
||||
public function put($key, $value);
|
||||
|
||||
/**
|
||||
* Associates the specified value with the specified key in this map only if
|
||||
* it is not already set.
|
||||
*
|
||||
* If there is already a value associated with `$key`, this returns that
|
||||
* value without replacing it.
|
||||
*
|
||||
* @param mixed $key The key to put in the map.
|
||||
* @param mixed $value The value to store at `$key`.
|
||||
*
|
||||
* @return mixed|null the previous value associated with key, or `null` if
|
||||
* there was no mapping for `$key`.
|
||||
*/
|
||||
public function putIfAbsent($key, $value);
|
||||
|
||||
/**
|
||||
* Removes the mapping for a key from this map if it is present.
|
||||
*
|
||||
* @param mixed $key The key to remove from the map.
|
||||
*
|
||||
* @return mixed|null the previous value associated with key, or `null` if
|
||||
* there was no mapping for `$key`.
|
||||
*/
|
||||
public function remove($key);
|
||||
|
||||
/**
|
||||
* Removes the entry for the specified key only if it is currently mapped to
|
||||
* the specified value.
|
||||
*
|
||||
* This performs a strict type check on the value.
|
||||
*
|
||||
* @param mixed $key The key to remove from the map.
|
||||
* @param mixed $value The value to match.
|
||||
*
|
||||
* @return bool true if the value was removed.
|
||||
*/
|
||||
public function removeIf($key, $value): bool;
|
||||
|
||||
/**
|
||||
* Replaces the entry for the specified key only if it is currently mapped
|
||||
* to some value.
|
||||
*
|
||||
* @param mixed $key The key to replace.
|
||||
* @param mixed $value The value to set at `$key`.
|
||||
*
|
||||
* @return mixed|null the previous value associated with key, or `null` if
|
||||
* there was no mapping for `$key`.
|
||||
*/
|
||||
public function replace($key, $value);
|
||||
|
||||
/**
|
||||
* Replaces the entry for the specified key only if currently mapped to the
|
||||
* specified value.
|
||||
*
|
||||
* This performs a strict type check on the value.
|
||||
*
|
||||
* @param mixed $key The key to remove from the map.
|
||||
* @param mixed $oldValue The value to match.
|
||||
* @param mixed $newValue The value to use as a replacement.
|
||||
*
|
||||
* @return bool true if the value was replaced.
|
||||
*/
|
||||
public function replaceIf($key, $oldValue, $newValue): bool;
|
||||
}
|
||||
118
vendor/ramsey/collection/src/Map/NamedParameterMap.php
vendored
Normal file
118
vendor/ramsey/collection/src/Map/NamedParameterMap.php
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Map;
|
||||
|
||||
use Ramsey\Collection\Exception\InvalidArgumentException;
|
||||
use Ramsey\Collection\Tool\TypeTrait;
|
||||
use Ramsey\Collection\Tool\ValueToStringTrait;
|
||||
|
||||
use function array_combine;
|
||||
use function array_key_exists;
|
||||
use function is_int;
|
||||
|
||||
/**
|
||||
* `NamedParameterMap` represents a mapping of values to a set of named keys
|
||||
* that may optionally be typed
|
||||
*/
|
||||
class NamedParameterMap extends AbstractMap
|
||||
{
|
||||
use TypeTrait;
|
||||
use ValueToStringTrait;
|
||||
|
||||
/**
|
||||
* Named parameters defined for this map.
|
||||
*
|
||||
* @var array<mixed, string>
|
||||
*/
|
||||
protected $namedParameters;
|
||||
|
||||
/**
|
||||
* Constructs a new `NamedParameterMap`.
|
||||
*
|
||||
* @param array<mixed, string> $namedParameters The named parameters defined for this map.
|
||||
* @param mixed[] $data An initial set of data to set on this map.
|
||||
*/
|
||||
public function __construct(array $namedParameters, array $data = [])
|
||||
{
|
||||
$this->namedParameters = $this->filterNamedParameters($namedParameters);
|
||||
parent::__construct($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns named parameters set for this `NamedParameterMap`.
|
||||
*
|
||||
* @return array<mixed, string>
|
||||
*/
|
||||
public function getNamedParameters(): array
|
||||
{
|
||||
return $this->namedParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given value to the given offset in the map.
|
||||
*
|
||||
* @param mixed $offset The offset to set.
|
||||
* @param mixed $value The value to set at the given offset.
|
||||
*
|
||||
* @throws InvalidArgumentException if the offset provided is not a
|
||||
* defined named parameter, or if the value is not of the type defined
|
||||
* for the given named parameter.
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
if (!array_key_exists($offset, $this->namedParameters)) {
|
||||
throw new InvalidArgumentException(
|
||||
'Attempting to set value for unconfigured parameter \''
|
||||
. $offset . '\''
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->checkType($this->namedParameters[$offset], $value) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
'Value for \'' . $offset . '\' must be of type '
|
||||
. $this->namedParameters[$offset] . '; value is '
|
||||
. $this->toolValueToString($value)
|
||||
);
|
||||
}
|
||||
|
||||
$this->data[$offset] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of named parameters, constructs a proper mapping of
|
||||
* named parameters to types.
|
||||
*
|
||||
* @param array<mixed, string> $namedParameters The named parameters to filter.
|
||||
*
|
||||
* @return array<mixed, string>
|
||||
*/
|
||||
protected function filterNamedParameters(array $namedParameters): array
|
||||
{
|
||||
$names = [];
|
||||
$types = [];
|
||||
|
||||
foreach ($namedParameters as $key => $value) {
|
||||
if (is_int($key)) {
|
||||
$names[] = (string) $value;
|
||||
$types[] = 'mixed';
|
||||
} else {
|
||||
$names[] = $key;
|
||||
$types[] = (string) $value;
|
||||
}
|
||||
}
|
||||
|
||||
return array_combine($names, $types) ?: [];
|
||||
}
|
||||
}
|
||||
137
vendor/ramsey/collection/src/Map/TypedMap.php
vendored
Normal file
137
vendor/ramsey/collection/src/Map/TypedMap.php
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Map;
|
||||
|
||||
use Ramsey\Collection\Tool\TypeTrait;
|
||||
|
||||
/**
|
||||
* A `TypedMap` represents a map of elements where key and value are typed.
|
||||
*
|
||||
* Each element is identified by a key with defined type and a value of defined
|
||||
* type. The keys of the map must be unique. The values on the map can be=
|
||||
* repeated but each with its own different key.
|
||||
*
|
||||
* The most common case is to use a string type key, but it's not limited to
|
||||
* this type of keys.
|
||||
*
|
||||
* This is a direct implementation of `TypedMapInterface`, provided for the sake
|
||||
* of convenience.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* ```php
|
||||
* $map = new TypedMap('string', Foo::class);
|
||||
* $map['x'] = new Foo();
|
||||
* foreach ($map as $key => $value) {
|
||||
* // do something with $key, it will be a Foo::class
|
||||
* }
|
||||
*
|
||||
* // this will throw an exception since key must be string
|
||||
* $map[10] = new Foo();
|
||||
*
|
||||
* // this will throw an exception since value must be a Foo
|
||||
* $map['bar'] = 'bar';
|
||||
*
|
||||
* // initialize map with contents
|
||||
* $map = new TypedMap('string', Foo::class, [
|
||||
* new Foo(), new Foo(), new Foo()
|
||||
* ]);
|
||||
* ```
|
||||
*
|
||||
* It is preferable to subclass `AbstractTypedMap` to create your own typed map
|
||||
* implementation:
|
||||
*
|
||||
* ```php
|
||||
* class FooTypedMap extends AbstractTypedMap
|
||||
* {
|
||||
* public function getKeyType()
|
||||
* {
|
||||
* return 'int';
|
||||
* }
|
||||
*
|
||||
* public function getValueType()
|
||||
* {
|
||||
* return Foo::class;
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* … but you also may use the `TypedMap` class:
|
||||
*
|
||||
* ```php
|
||||
* class FooTypedMap extends TypedMap
|
||||
* {
|
||||
* public function __constructor(array $data = [])
|
||||
* {
|
||||
* parent::__construct('int', Foo::class, $data);
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class TypedMap extends AbstractTypedMap
|
||||
{
|
||||
use TypeTrait;
|
||||
|
||||
/**
|
||||
* The data type of keys stored in this collection.
|
||||
*
|
||||
* A map key's type is immutable once it is set. For this reason, this
|
||||
* property is set private.
|
||||
*
|
||||
* @var string data type of the map key.
|
||||
*/
|
||||
private $keyType;
|
||||
|
||||
/**
|
||||
* The data type of values stored in this collection.
|
||||
*
|
||||
* A map values's type is immutable once it is set. For this reason, this
|
||||
* property is set private.
|
||||
*
|
||||
* @var string data type of the map value.
|
||||
*/
|
||||
private $valueType;
|
||||
|
||||
/**
|
||||
* Constructs a map object of the specified key and value types,
|
||||
* optionally with the specified data.
|
||||
*
|
||||
* @param string $keyType The data type of the map's keys.
|
||||
* @param string $valueType The data type of the map's values.
|
||||
* @param mixed[] $data The initial data to set for this map.
|
||||
*/
|
||||
public function __construct(string $keyType, string $valueType, array $data = [])
|
||||
{
|
||||
$this->keyType = $keyType;
|
||||
$this->valueType = $valueType;
|
||||
parent::__construct($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type used on the key.
|
||||
*/
|
||||
public function getKeyType(): string
|
||||
{
|
||||
return $this->keyType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type forced on the values.
|
||||
*/
|
||||
public function getValueType(): string
|
||||
{
|
||||
return $this->valueType;
|
||||
}
|
||||
}
|
||||
32
vendor/ramsey/collection/src/Map/TypedMapInterface.php
vendored
Normal file
32
vendor/ramsey/collection/src/Map/TypedMapInterface.php
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Map;
|
||||
|
||||
/**
|
||||
* A `TypedMapInterface` represents a map of elements where key and value are
|
||||
* typed.
|
||||
*/
|
||||
interface TypedMapInterface extends MapInterface
|
||||
{
|
||||
/**
|
||||
* Return the type used on the key.
|
||||
*/
|
||||
public function getKeyType(): string;
|
||||
|
||||
/**
|
||||
* Return the type forced on the values.
|
||||
*/
|
||||
public function getValueType(): string;
|
||||
}
|
||||
226
vendor/ramsey/collection/src/Queue.php
vendored
Normal file
226
vendor/ramsey/collection/src/Queue.php
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection;
|
||||
|
||||
use Ramsey\Collection\Exception\InvalidArgumentException;
|
||||
use Ramsey\Collection\Exception\NoSuchElementException;
|
||||
use Ramsey\Collection\Tool\TypeTrait;
|
||||
use Ramsey\Collection\Tool\ValueToStringTrait;
|
||||
|
||||
/**
|
||||
* This class provides a basic implementation of `QueueInterface`, to minimize
|
||||
* the effort required to implement this interface.
|
||||
*/
|
||||
class Queue extends AbstractArray implements QueueInterface
|
||||
{
|
||||
use TypeTrait;
|
||||
use ValueToStringTrait;
|
||||
|
||||
/**
|
||||
* The type of elements stored in this queue.
|
||||
*
|
||||
* A queue's type is immutable once it is set. For this reason, this
|
||||
* property is set private.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $queueType;
|
||||
|
||||
/**
|
||||
* The index of the head of the queue.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $index = 0;
|
||||
|
||||
/**
|
||||
* Constructs a queue object of the specified type, optionally with the
|
||||
* specified data.
|
||||
*
|
||||
* @param string $queueType The type (FQCN) associated with this queue.
|
||||
* @param mixed[] $data The initial items to store in the collection.
|
||||
*/
|
||||
public function __construct(string $queueType, array $data = [])
|
||||
{
|
||||
$this->queueType = $queueType;
|
||||
parent::__construct($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given value to the given offset in the queue.
|
||||
*
|
||||
* Since arbitrary offsets may not be manipulated in a queue, this method
|
||||
* serves only to fulfill the `ArrayAccess` interface requirements. It is
|
||||
* invoked by other operations when adding values to the queue.
|
||||
*
|
||||
* @link http://php.net/manual/en/arrayaccess.offsetset.php ArrayAccess::offsetSet()
|
||||
*
|
||||
* @param mixed|null $offset The offset is ignored and is treated as `null`.
|
||||
* @param mixed $value The value to set at the given offset.
|
||||
*
|
||||
* @throws InvalidArgumentException when the value does not match the
|
||||
* specified type for this queue.
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
if ($this->checkType($this->getType(), $value) === false) {
|
||||
throw new InvalidArgumentException(
|
||||
'Value must be of type ' . $this->getType() . '; value is '
|
||||
. $this->toolValueToString($value)
|
||||
);
|
||||
}
|
||||
|
||||
$this->data[] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that this queue contains the specified element.
|
||||
*
|
||||
* This method differs from `offer()` only in that it throws an exception if
|
||||
* it cannot add the element to the queue.
|
||||
*
|
||||
* @see self::offer()
|
||||
*
|
||||
* @param mixed $element The element to add to this queue.
|
||||
*
|
||||
* @return bool `true` if this queue changed as a result of the call.
|
||||
*
|
||||
* @throws InvalidArgumentException when the element does not match the
|
||||
* specified type for this queue.
|
||||
*/
|
||||
public function add($element): bool
|
||||
{
|
||||
$this[] = $element;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the head of this queue.
|
||||
*
|
||||
* This method differs from `peek()` only in that it throws an exception if
|
||||
* this queue is empty.
|
||||
*
|
||||
* @see self::peek()
|
||||
*
|
||||
* @return mixed the head of this queue.
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function element()
|
||||
{
|
||||
if ($this->count() === 0) {
|
||||
throw new NoSuchElementException(
|
||||
'Can\'t return element from Queue. Queue is empty.'
|
||||
);
|
||||
}
|
||||
|
||||
return $this[$this->index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the specified element into this queue.
|
||||
*
|
||||
* This method differs from `add()` only in that it does not throw an
|
||||
* exception if it cannot add the element to the queue.
|
||||
*
|
||||
* @see self::add()
|
||||
*
|
||||
* @param mixed $element The element to add to this queue.
|
||||
*
|
||||
* @return bool `true` if the element was added to this queue, else `false`.
|
||||
*/
|
||||
public function offer($element): bool
|
||||
{
|
||||
try {
|
||||
return $this->add($element);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the head of this queue, or returns `null`
|
||||
* if this queue is empty.
|
||||
*
|
||||
* @see self::element()
|
||||
*
|
||||
* @return mixed|null the head of this queue, or `null` if this queue is empty.
|
||||
*/
|
||||
public function peek()
|
||||
{
|
||||
if ($this->count() === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this[$this->index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of this queue, or returns `null`
|
||||
* if this queue is empty.
|
||||
*
|
||||
* @see self::remove()
|
||||
*
|
||||
* @return mixed|null the head of this queue, or `null` if this queue is empty.
|
||||
*/
|
||||
public function poll()
|
||||
{
|
||||
if ($this->count() === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$head = $this[$this->index];
|
||||
|
||||
unset($this[$this->index]);
|
||||
$this->index++;
|
||||
|
||||
return $head;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of this queue.
|
||||
*
|
||||
* This method differs from `poll()` only in that it throws an exception if
|
||||
* this queue is empty.
|
||||
*
|
||||
* @see self::poll()
|
||||
*
|
||||
* @return mixed the head of this queue.
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function remove()
|
||||
{
|
||||
if ($this->count() === 0) {
|
||||
throw new NoSuchElementException('Can\'t return element from Queue. Queue is empty.');
|
||||
}
|
||||
|
||||
$head = $this[$this->index];
|
||||
|
||||
unset($this[$this->index]);
|
||||
$this->index++;
|
||||
|
||||
return $head;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type associated with this queue.
|
||||
*/
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->queueType;
|
||||
}
|
||||
}
|
||||
198
vendor/ramsey/collection/src/QueueInterface.php
vendored
Normal file
198
vendor/ramsey/collection/src/QueueInterface.php
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection;
|
||||
|
||||
use Ramsey\Collection\Exception\NoSuchElementException;
|
||||
|
||||
/**
|
||||
* A queue is a collection in which the entities in the collection are kept in
|
||||
* order.
|
||||
*
|
||||
* The principal operations on the queue are the addition of entities to the end
|
||||
* (tail), also known as *enqueue*, and removal of entities from the front
|
||||
* (head), also known as *dequeue*. This makes the queue a first-in-first-out
|
||||
* (FIFO) data structure.
|
||||
*
|
||||
* Besides basic array operations, queues provide additional insertion,
|
||||
* extraction, and inspection operations. Each of these methods exists in two
|
||||
* forms: one throws an exception if the operation fails, the other returns a
|
||||
* special value (either `null` or `false`, depending on the operation). The
|
||||
* latter form of the insert operation is designed specifically for use with
|
||||
* capacity-restricted `QueueInterface` implementations; in most
|
||||
* implementations, insert operations cannot fail.
|
||||
*
|
||||
* <table>
|
||||
* <caption>Summary of QueueInterface methods</caption>
|
||||
* <thead>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td><em>Throws exception</em></td>
|
||||
* <td><em>Returns special value</em></td>
|
||||
* </tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr>
|
||||
* <th>Insert</th>
|
||||
* <td><code>add()</code></td>
|
||||
* <td><code>offer()</code></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th>Remove</th>
|
||||
* <td><code>remove()</code></td>
|
||||
* <td><code>poll()</code></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th>Examine</th>
|
||||
* <td><code>element()</code></td>
|
||||
* <td><code>peek()</code></td>
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
*
|
||||
* Queues typically, but do not necessarily, order elements in a FIFO
|
||||
* (first-in-first-out) manner. Among the exceptions are priority queues, which
|
||||
* order elements according to a supplied comparator, or the elements' natural
|
||||
* ordering, and LIFO queues (or stacks) which order the elements LIFO
|
||||
* (last-in-first-out). Whatever the ordering used, the head of the queue is
|
||||
* that element which would be removed by a call to remove() or poll(). In a
|
||||
* FIFO queue, all new elements are inserted at the tail of the queue. Other
|
||||
* kinds of queues may use different placement rules. Every `QueueInterface`
|
||||
* implementation must specify its ordering properties.
|
||||
*
|
||||
* The `offer()` method inserts an element if possible, otherwise returning
|
||||
* `false`. This differs from the `add()` method, which can fail to add an
|
||||
* element only by throwing an unchecked exception. The `offer()` method is
|
||||
* designed for use when failure is a normal, rather than exceptional
|
||||
* occurrence, for example, in fixed-capacity (or "bounded") queues.
|
||||
*
|
||||
* The `remove()` and `poll()` methods remove and return the head of the queue.
|
||||
* Exactly which element is removed from the queue is a function of the queue's
|
||||
* ordering policy, which differs from implementation to implementation. The
|
||||
* `remove()` and `poll()` methods differ only in their behavior when the queue
|
||||
* is empty: the `remove()` method throws an exception, while the `poll()`
|
||||
* method returns `null`.
|
||||
*
|
||||
* The `element()` and `peek()` methods return, but do not remove, the head of
|
||||
* the queue.
|
||||
*
|
||||
* `QueueInterface` implementations generally do not allow insertion of `null`
|
||||
* elements, although some implementations do not prohibit insertion of `null`.
|
||||
* Even in the implementations that permit it, `null` should not be inserted
|
||||
* into a queue, as `null` is also used as a special return value by the
|
||||
* `poll()` method to indicate that the queue contains no elements.
|
||||
*/
|
||||
interface QueueInterface extends ArrayInterface
|
||||
{
|
||||
/**
|
||||
* Ensures that this queue contains the specified element (optional
|
||||
* operation).
|
||||
*
|
||||
* Returns `true` if this queue changed as a result of the call. (Returns
|
||||
* `false` if this queue does not permit duplicates and already contains the
|
||||
* specified element.)
|
||||
*
|
||||
* Queues that support this operation may place limitations on what elements
|
||||
* may be added to this queue. In particular, some queues will refuse to add
|
||||
* `null` elements, and others will impose restrictions on the type of
|
||||
* elements that may be added. Queue classes should clearly specify in their
|
||||
* documentation any restrictions on what elements may be added.
|
||||
*
|
||||
* If a queue refuses to add a particular element for any reason other than
|
||||
* that it already contains the element, it must throw an exception (rather
|
||||
* than returning `false`). This preserves the invariant that a queue always
|
||||
* contains the specified element after this call returns.
|
||||
*
|
||||
* @see self::offer()
|
||||
*
|
||||
* @param mixed $element The element to add to this queue.
|
||||
*
|
||||
* @return bool `true` if this queue changed as a result of the call.
|
||||
*
|
||||
* @throws \RuntimeException if a queue refuses to add a particular element
|
||||
* for any reason other than that it already contains the element.
|
||||
* Implementations should use a more-specific exception that extends
|
||||
* `\RuntimeException`.
|
||||
*/
|
||||
public function add($element): bool;
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the head of this queue.
|
||||
*
|
||||
* This method differs from `peek()` only in that it throws an exception if
|
||||
* this queue is empty.
|
||||
*
|
||||
* @see self::peek()
|
||||
*
|
||||
* @return mixed the head of this queue.
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function element();
|
||||
|
||||
/**
|
||||
* Inserts the specified element into this queue if it is possible to do so
|
||||
* immediately without violating capacity restrictions.
|
||||
*
|
||||
* When using a capacity-restricted queue, this method is generally
|
||||
* preferable to `add()`, which can fail to insert an element only by
|
||||
* throwing an exception.
|
||||
*
|
||||
* @see self::add()
|
||||
*
|
||||
* @param mixed $element The element to add to this queue.
|
||||
*
|
||||
* @return bool `true` if the element was added to this queue, else `false`.
|
||||
*/
|
||||
public function offer($element): bool;
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the head of this queue, or returns `null`
|
||||
* if this queue is empty.
|
||||
*
|
||||
* @see self::element()
|
||||
*
|
||||
* @return mixed|null the head of this queue, or `null` if this queue is empty.
|
||||
*/
|
||||
public function peek();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of this queue, or returns `null`
|
||||
* if this queue is empty.
|
||||
*
|
||||
* @see self::remove()
|
||||
*
|
||||
* @return mixed|null the head of this queue, or `null` if this queue is empty.
|
||||
*/
|
||||
public function poll();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the head of this queue.
|
||||
*
|
||||
* This method differs from `poll()` only in that it throws an exception if
|
||||
* this queue is empty.
|
||||
*
|
||||
* @see self::poll()
|
||||
*
|
||||
* @return mixed the head of this queue.
|
||||
*
|
||||
* @throws NoSuchElementException if this queue is empty.
|
||||
*/
|
||||
public function remove();
|
||||
|
||||
/**
|
||||
* Returns the type associated with this queue.
|
||||
*/
|
||||
public function getType(): string;
|
||||
}
|
||||
69
vendor/ramsey/collection/src/Set.php
vendored
Normal file
69
vendor/ramsey/collection/src/Set.php
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection;
|
||||
|
||||
/**
|
||||
* A set is a collection that contains no duplicate elements.
|
||||
*
|
||||
* Great care must be exercised if mutable objects are used as set elements.
|
||||
* The behavior of a set is not specified if the value of an object is changed
|
||||
* in a manner that affects equals comparisons while the object is an element in
|
||||
* the set.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* ``` php
|
||||
* $foo = new \My\Foo();
|
||||
* $set = new Set(\My\Foo::class);
|
||||
*
|
||||
* $set->add($foo); // returns TRUE, the element don't exists
|
||||
* $set->add($foo); // returns FALSE, the element already exists
|
||||
*
|
||||
* $bar = new \My\Foo();
|
||||
* $set->add($bar); // returns TRUE, $bar !== $foo
|
||||
* ```
|
||||
*/
|
||||
class Set extends AbstractSet
|
||||
{
|
||||
/**
|
||||
* The type of elements stored in this set
|
||||
*
|
||||
* A set's type is immutable. For this reason, this property is private.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $setType;
|
||||
|
||||
/**
|
||||
* Constructs a set object of the specified type, optionally with the
|
||||
* specified data.
|
||||
*
|
||||
* @param string $setType The type (FQCN) associated with this set.
|
||||
* @param mixed[] $data The initial items to store in the set.
|
||||
*/
|
||||
public function __construct(string $setType, array $data = [])
|
||||
{
|
||||
$this->setType = $setType;
|
||||
parent::__construct($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type associated with this set.
|
||||
*/
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->setType;
|
||||
}
|
||||
}
|
||||
73
vendor/ramsey/collection/src/Tool/TypeTrait.php
vendored
Normal file
73
vendor/ramsey/collection/src/Tool/TypeTrait.php
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Tool;
|
||||
|
||||
use function is_array;
|
||||
use function is_bool;
|
||||
use function is_callable;
|
||||
use function is_float;
|
||||
use function is_int;
|
||||
use function is_numeric;
|
||||
use function is_object;
|
||||
use function is_resource;
|
||||
use function is_scalar;
|
||||
use function is_string;
|
||||
|
||||
/**
|
||||
* Provides functionality to check values for specific types.
|
||||
*/
|
||||
trait TypeTrait
|
||||
{
|
||||
/**
|
||||
* Returns `true` if value is of the specified type.
|
||||
*
|
||||
* @param string $type The type to check the value against.
|
||||
* @param mixed $value The value to check.
|
||||
*/
|
||||
protected function checkType(string $type, $value): bool
|
||||
{
|
||||
switch ($type) {
|
||||
case 'array':
|
||||
return is_array($value);
|
||||
case 'bool':
|
||||
case 'boolean':
|
||||
return is_bool($value);
|
||||
case 'callable':
|
||||
return is_callable($value);
|
||||
case 'float':
|
||||
case 'double':
|
||||
return is_float($value);
|
||||
case 'int':
|
||||
case 'integer':
|
||||
return is_int($value);
|
||||
case 'null':
|
||||
return $value === null;
|
||||
case 'numeric':
|
||||
return is_numeric($value);
|
||||
case 'object':
|
||||
return is_object($value);
|
||||
case 'resource':
|
||||
return is_resource($value);
|
||||
case 'scalar':
|
||||
return is_scalar($value);
|
||||
case 'string':
|
||||
return is_string($value);
|
||||
case 'mixed':
|
||||
return true;
|
||||
default:
|
||||
return $value instanceof $type;
|
||||
}
|
||||
}
|
||||
}
|
||||
54
vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php
vendored
Normal file
54
vendor/ramsey/collection/src/Tool/ValueExtractorTrait.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Tool;
|
||||
|
||||
use Ramsey\Collection\Exception\ValueExtractionException;
|
||||
|
||||
use function get_class;
|
||||
use function method_exists;
|
||||
use function property_exists;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Provides functionality to extract the value of a property or method from an object.
|
||||
*/
|
||||
trait ValueExtractorTrait
|
||||
{
|
||||
/**
|
||||
* Extracts the value of the given property or method from the object.
|
||||
*
|
||||
* @param object $object The object to extract the value from.
|
||||
* @param string $propertyOrMethod The property or method for which the
|
||||
* value should be extracted.
|
||||
*
|
||||
* @return mixed the value extracted from the specified property or method.
|
||||
*
|
||||
* @throws ValueExtractionException if the method or property is not defined.
|
||||
*/
|
||||
protected function extractValue(object $object, string $propertyOrMethod)
|
||||
{
|
||||
if (property_exists($object, $propertyOrMethod)) {
|
||||
return $object->$propertyOrMethod;
|
||||
}
|
||||
|
||||
if (method_exists($object, $propertyOrMethod)) {
|
||||
return $object->{$propertyOrMethod}();
|
||||
}
|
||||
|
||||
throw new ValueExtractionException(
|
||||
sprintf('Method or property "%s" not defined in %s', $propertyOrMethod, get_class($object))
|
||||
);
|
||||
}
|
||||
}
|
||||
89
vendor/ramsey/collection/src/Tool/ValueToStringTrait.php
vendored
Normal file
89
vendor/ramsey/collection/src/Tool/ValueToStringTrait.php
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/collection library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Collection\Tool;
|
||||
|
||||
use DateTimeInterface;
|
||||
|
||||
use function get_class;
|
||||
use function get_resource_type;
|
||||
use function is_array;
|
||||
use function is_bool;
|
||||
use function is_callable;
|
||||
use function is_resource;
|
||||
use function is_scalar;
|
||||
|
||||
/**
|
||||
* Provides functionality to express a value as string
|
||||
*/
|
||||
trait ValueToStringTrait
|
||||
{
|
||||
/**
|
||||
* Returns a string representation of the value.
|
||||
*
|
||||
* - null value: `'NULL'`
|
||||
* - boolean: `'TRUE'`, `'FALSE'`
|
||||
* - array: `'Array'`
|
||||
* - scalar: converted-value
|
||||
* - resource: `'(type resource #number)'`
|
||||
* - object with `__toString()`: result of `__toString()`
|
||||
* - object DateTime: ISO 8601 date
|
||||
* - object: `'(className Object)'`
|
||||
* - anonymous function: same as object
|
||||
*
|
||||
* @param mixed $value the value to return as a string.
|
||||
*/
|
||||
protected function toolValueToString($value): string
|
||||
{
|
||||
// null
|
||||
if ($value === null) {
|
||||
return 'NULL';
|
||||
}
|
||||
|
||||
// boolean constants
|
||||
if (is_bool($value)) {
|
||||
return $value ? 'TRUE' : 'FALSE';
|
||||
}
|
||||
|
||||
// array
|
||||
if (is_array($value)) {
|
||||
return 'Array';
|
||||
}
|
||||
|
||||
// scalar types (integer, float, string)
|
||||
if (is_scalar($value)) {
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
// resource
|
||||
if (is_resource($value)) {
|
||||
return '(' . get_resource_type($value) . ' resource #' . (int) $value . ')';
|
||||
}
|
||||
|
||||
// after this line $value is an object since is not null, scalar, array or resource
|
||||
|
||||
// __toString() is implemented
|
||||
if (is_callable([$value, '__toString'])) {
|
||||
return (string) $value->__toString();
|
||||
}
|
||||
|
||||
// object of type \DateTime
|
||||
if ($value instanceof DateTimeInterface) {
|
||||
return $value->format('c');
|
||||
}
|
||||
|
||||
// unknown type
|
||||
return '(' . get_class($value) . ' Object)';
|
||||
}
|
||||
}
|
||||
1253
vendor/ramsey/uuid/CHANGELOG.md
vendored
Normal file
1253
vendor/ramsey/uuid/CHANGELOG.md
vendored
Normal file
File diff suppressed because it is too large
Load Diff
21
vendor/ramsey/uuid/LICENSE
vendored
Normal file
21
vendor/ramsey/uuid/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2012-2020 Ben Ramsey <ben@benramsey.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
79
vendor/ramsey/uuid/README.md
vendored
Normal file
79
vendor/ramsey/uuid/README.md
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
# ramsey/uuid
|
||||
|
||||
[![Source Code][badge-source]][source]
|
||||
[![Latest Version][badge-release]][release]
|
||||
[![Software License][badge-license]][license]
|
||||
[![PHP Version][badge-php]][php]
|
||||
[![Build Status][badge-build]][build]
|
||||
[![Coverage Status][badge-coverage]][coverage]
|
||||
[![Total Downloads][badge-downloads]][downloads]
|
||||
|
||||
ramsey/uuid is a PHP library for generating and working with universally unique
|
||||
identifiers (UUIDs).
|
||||
|
||||
This project adheres to a [Contributor Code of Conduct][conduct]. By
|
||||
participating in this project and its community, you are expected to uphold this
|
||||
code.
|
||||
|
||||
Much inspiration for this library came from the [Java][javauuid] and
|
||||
[Python][pyuuid] UUID libraries.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
The preferred method of installation is via [Composer][]. Run the following
|
||||
command to install the package and add it as a requirement to your project's
|
||||
`composer.json`:
|
||||
|
||||
```bash
|
||||
composer require ramsey/uuid
|
||||
```
|
||||
|
||||
|
||||
## Upgrading to Version 4
|
||||
|
||||
See the documentation for a thorough upgrade guide:
|
||||
|
||||
* [Upgrading ramsey/uuid Version 3 to 4](https://uuid.ramsey.dev/en/latest/upgrading/3-to-4.html)
|
||||
|
||||
|
||||
## Documentation
|
||||
|
||||
Please see <https://uuid.ramsey.dev> for documentation, tips, examples, and
|
||||
frequently asked questions.
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please read [CONTRIBUTING.md][] for details.
|
||||
|
||||
|
||||
## Copyright and License
|
||||
|
||||
The ramsey/uuid library is copyright © [Ben Ramsey](https://benramsey.com/) and
|
||||
licensed for use under the MIT License (MIT). Please see [LICENSE][] for more
|
||||
information.
|
||||
|
||||
|
||||
[rfc4122]: http://tools.ietf.org/html/rfc4122
|
||||
[conduct]: https://github.com/ramsey/uuid/blob/master/.github/CODE_OF_CONDUCT.md
|
||||
[javauuid]: http://docs.oracle.com/javase/6/docs/api/java/util/UUID.html
|
||||
[pyuuid]: http://docs.python.org/3/library/uuid.html
|
||||
[composer]: http://getcomposer.org/
|
||||
[contributing.md]: https://github.com/ramsey/uuid/blob/master/.github/CONTRIBUTING.md
|
||||
|
||||
[badge-source]: https://img.shields.io/badge/source-ramsey/uuid-blue.svg?style=flat-square
|
||||
[badge-release]: https://img.shields.io/packagist/v/ramsey/uuid.svg?style=flat-square&label=release
|
||||
[badge-license]: https://img.shields.io/packagist/l/ramsey/uuid.svg?style=flat-square
|
||||
[badge-php]: https://img.shields.io/packagist/php-v/ramsey/uuid.svg?style=flat-square
|
||||
[badge-build]: https://img.shields.io/travis/ramsey/uuid/master.svg?style=flat-square
|
||||
[badge-coverage]: https://img.shields.io/coveralls/github/ramsey/uuid/master.svg?style=flat-square
|
||||
[badge-downloads]: https://img.shields.io/packagist/dt/ramsey/uuid.svg?style=flat-square&colorB=mediumvioletred
|
||||
|
||||
[source]: https://github.com/ramsey/uuid
|
||||
[release]: https://packagist.org/packages/ramsey/uuid
|
||||
[license]: https://github.com/ramsey/uuid/blob/master/LICENSE
|
||||
[php]: https://php.net
|
||||
[build]: https://travis-ci.org/ramsey/uuid
|
||||
[coverage]: https://coveralls.io/github/ramsey/uuid?branch=master
|
||||
[downloads]: https://packagist.org/packages/ramsey/uuid
|
||||
101
vendor/ramsey/uuid/composer.json
vendored
Normal file
101
vendor/ramsey/uuid/composer.json
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
{
|
||||
"name": "ramsey/uuid",
|
||||
"type": "library",
|
||||
"description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
|
||||
"keywords": [
|
||||
"uuid",
|
||||
"identifier",
|
||||
"guid"
|
||||
],
|
||||
"homepage": "https://github.com/ramsey/uuid",
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.2 || ^8",
|
||||
"ext-json": "*",
|
||||
"brick/math": "^0.8",
|
||||
"ramsey/collection": "^1.0",
|
||||
"symfony/polyfill-ctype": "^1.8"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeception/aspect-mock": "^3",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7.0",
|
||||
"doctrine/annotations": "^1.8",
|
||||
"goaop/framework": "^2",
|
||||
"mockery/mockery": "^1.3",
|
||||
"moontoast/math": "^1.1",
|
||||
"paragonie/random-lib": "^2",
|
||||
"php-mock/php-mock-mockery": "^1.3",
|
||||
"php-mock/php-mock-phpunit": "^2.5",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.1",
|
||||
"phpbench/phpbench": "^0.17.1",
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"phpstan/phpstan-mockery": "^0.12",
|
||||
"phpstan/phpstan-phpunit": "^0.12",
|
||||
"phpunit/phpunit": "^8.5",
|
||||
"psy/psysh": "^0.10.0",
|
||||
"slevomat/coding-standard": "^6.0",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"vimeo/psalm": "3.9.4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
|
||||
"ext-ctype": "Enables faster processing of character classification using ctype functions.",
|
||||
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
|
||||
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
|
||||
"ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type.",
|
||||
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter"
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.x-dev"
|
||||
}
|
||||
},
|
||||
"replace": {
|
||||
"rhumsaa/uuid": "self.version"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Ramsey\\Uuid\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Ramsey\\Uuid\\Benchmark\\": "tests/benchmark/",
|
||||
"Ramsey\\Uuid\\StaticAnalysis\\": "tests/static-analysis/",
|
||||
"Ramsey\\Uuid\\Test\\": "tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "parallel-lint src tests",
|
||||
"phpbench": "phpbench run",
|
||||
"phpcbf": "phpcbf -vpw --cache=build/cache/phpcs.cache",
|
||||
"phpcs": "phpcs --cache=build/cache/phpcs.cache",
|
||||
"phpstan": [
|
||||
"phpstan analyse -c tests/phpstan.neon --no-progress",
|
||||
"phpstan analyse -c tests/phpstan-tests.neon --no-progress"
|
||||
],
|
||||
"psalm": "psalm --show-info=false --config=tests/psalm.xml",
|
||||
"phpunit": "phpunit --verbose --colors=always",
|
||||
"phpunit-coverage": "phpunit --verbose --colors=always --coverage-html build/coverage",
|
||||
"test": [
|
||||
"@lint",
|
||||
"@phpbench",
|
||||
"@phpcs",
|
||||
"@phpstan",
|
||||
"@psalm",
|
||||
"@phpunit"
|
||||
]
|
||||
},
|
||||
"support": {
|
||||
"issues": "https://github.com/ramsey/uuid/issues",
|
||||
"rss": "https://github.com/ramsey/uuid/releases.atom",
|
||||
"source": "https://github.com/ramsey/uuid"
|
||||
}
|
||||
}
|
||||
63
vendor/ramsey/uuid/src/BinaryUtils.php
vendored
Normal file
63
vendor/ramsey/uuid/src/BinaryUtils.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid;
|
||||
|
||||
/**
|
||||
* Provides binary math utilities
|
||||
*/
|
||||
class BinaryUtils
|
||||
{
|
||||
/**
|
||||
* Applies the RFC 4122 variant field to the 16-bit clock sequence
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc4122#section-4.1.1 RFC 4122, § 4.1.1: Variant
|
||||
*
|
||||
* @param int $clockSeq The 16-bit clock sequence value before the RFC 4122
|
||||
* variant is applied
|
||||
*
|
||||
* @return int The 16-bit clock sequence multiplexed with the UUID variant
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function applyVariant(int $clockSeq): int
|
||||
{
|
||||
$clockSeq = $clockSeq & 0x3fff;
|
||||
$clockSeq |= 0x8000;
|
||||
|
||||
return $clockSeq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the RFC 4122 version number to the 16-bit `time_hi_and_version` field
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc4122#section-4.1.3 RFC 4122, § 4.1.3: Version
|
||||
*
|
||||
* @param int $timeHi The value of the 16-bit `time_hi_and_version` field
|
||||
* before the RFC 4122 version is applied
|
||||
* @param int $version The RFC 4122 version to apply to the `time_hi` field
|
||||
*
|
||||
* @return int The 16-bit time_hi field of the timestamp multiplexed with
|
||||
* the UUID version number
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function applyVersion(int $timeHi, int $version): int
|
||||
{
|
||||
$timeHi = $timeHi & 0x0fff;
|
||||
$timeHi |= $version << 12;
|
||||
|
||||
return $timeHi;
|
||||
}
|
||||
}
|
||||
73
vendor/ramsey/uuid/src/Builder/BuilderCollection.php
vendored
Normal file
73
vendor/ramsey/uuid/src/Builder/BuilderCollection.php
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Builder;
|
||||
|
||||
use Ramsey\Collection\AbstractCollection;
|
||||
use Ramsey\Collection\CollectionInterface;
|
||||
use Ramsey\Uuid\Converter\Number\GenericNumberConverter;
|
||||
use Ramsey\Uuid\Converter\Time\GenericTimeConverter;
|
||||
use Ramsey\Uuid\Converter\Time\PhpTimeConverter;
|
||||
use Ramsey\Uuid\Guid\GuidBuilder;
|
||||
use Ramsey\Uuid\Math\BrickMathCalculator;
|
||||
use Ramsey\Uuid\Nonstandard\UuidBuilder as NonstandardUuidBuilder;
|
||||
use Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
* A collection of UuidBuilderInterface objects
|
||||
*/
|
||||
class BuilderCollection extends AbstractCollection implements CollectionInterface
|
||||
{
|
||||
public function getType(): string
|
||||
{
|
||||
return UuidBuilderInterface::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-mutation-free
|
||||
* @psalm-suppress ImpureMethodCall
|
||||
* @psalm-suppress InvalidTemplateParam
|
||||
*/
|
||||
public function getIterator(): Traversable
|
||||
{
|
||||
return parent::getIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-constructs the object from its serialized form
|
||||
*
|
||||
* @param string $serialized The serialized PHP string to unserialize into
|
||||
* a UuidInterface instance
|
||||
*
|
||||
* @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
|
||||
*/
|
||||
public function unserialize($serialized): void
|
||||
{
|
||||
/** @var mixed[] $data */
|
||||
$data = unserialize($serialized, [
|
||||
'allowed_classes' => [
|
||||
BrickMathCalculator::class,
|
||||
GenericNumberConverter::class,
|
||||
GenericTimeConverter::class,
|
||||
GuidBuilder::class,
|
||||
NonstandardUuidBuilder::class,
|
||||
PhpTimeConverter::class,
|
||||
Rfc4122UuidBuilder::class,
|
||||
],
|
||||
]);
|
||||
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
||||
26
vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.php
vendored
Normal file
26
vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Builder;
|
||||
|
||||
use Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder;
|
||||
|
||||
/**
|
||||
* @deprecated Transition to {@see Rfc4122UuidBuilder}.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class DefaultUuidBuilder extends Rfc4122UuidBuilder implements UuidBuilderInterface
|
||||
{
|
||||
}
|
||||
76
vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.php
vendored
Normal file
76
vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.php
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Builder;
|
||||
|
||||
use Ramsey\Uuid\Codec\CodecInterface;
|
||||
use Ramsey\Uuid\Converter\NumberConverterInterface;
|
||||
use Ramsey\Uuid\Converter\Time\DegradedTimeConverter;
|
||||
use Ramsey\Uuid\Converter\TimeConverterInterface;
|
||||
use Ramsey\Uuid\DegradedUuid;
|
||||
use Ramsey\Uuid\Rfc4122\Fields as Rfc4122Fields;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
/**
|
||||
* @deprecated DegradedUuid instances are no longer necessary to support 32-bit
|
||||
* systems. Transition to {@see DefaultUuidBuilder}.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class DegradedUuidBuilder implements UuidBuilderInterface
|
||||
{
|
||||
/**
|
||||
* @var NumberConverterInterface
|
||||
*/
|
||||
private $numberConverter;
|
||||
|
||||
/**
|
||||
* @var TimeConverterInterface
|
||||
*/
|
||||
private $timeConverter;
|
||||
|
||||
/**
|
||||
* @param NumberConverterInterface $numberConverter The number converter to
|
||||
* use when constructing the DegradedUuid
|
||||
* @param TimeConverterInterface|null $timeConverter The time converter to use
|
||||
* for converting timestamps extracted from a UUID to Unix timestamps
|
||||
*/
|
||||
public function __construct(
|
||||
NumberConverterInterface $numberConverter,
|
||||
?TimeConverterInterface $timeConverter = null
|
||||
) {
|
||||
$this->numberConverter = $numberConverter;
|
||||
$this->timeConverter = $timeConverter ?: new DegradedTimeConverter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns a DegradedUuid
|
||||
*
|
||||
* @param CodecInterface $codec The codec to use for building this DegradedUuid instance
|
||||
* @param string $bytes The byte string from which to construct a UUID
|
||||
*
|
||||
* @return DegradedUuid The DegradedUuidBuild returns an instance of Ramsey\Uuid\DegradedUuid
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public function build(CodecInterface $codec, string $bytes): UuidInterface
|
||||
{
|
||||
return new DegradedUuid(
|
||||
new Rfc4122Fields($bytes),
|
||||
$this->numberConverter,
|
||||
$codec,
|
||||
$this->timeConverter
|
||||
);
|
||||
}
|
||||
}
|
||||
75
vendor/ramsey/uuid/src/Builder/FallbackBuilder.php
vendored
Normal file
75
vendor/ramsey/uuid/src/Builder/FallbackBuilder.php
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Builder;
|
||||
|
||||
use Ramsey\Uuid\Codec\CodecInterface;
|
||||
use Ramsey\Uuid\Exception\BuilderNotFoundException;
|
||||
use Ramsey\Uuid\Exception\UnableToBuildUuidException;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
/**
|
||||
* FallbackBuilder builds a UUID by stepping through a list of UUID builders
|
||||
* until a UUID can be constructed without exceptions
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class FallbackBuilder implements UuidBuilderInterface
|
||||
{
|
||||
/**
|
||||
* @var BuilderCollection
|
||||
*/
|
||||
private $builders;
|
||||
|
||||
/**
|
||||
* @param BuilderCollection $builders An array of UUID builders
|
||||
*/
|
||||
public function __construct(BuilderCollection $builders)
|
||||
{
|
||||
$this->builders = $builders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns a UuidInterface instance using the first builder that
|
||||
* succeeds
|
||||
*
|
||||
* @param CodecInterface $codec The codec to use for building this instance
|
||||
* @param string $bytes The byte string from which to construct a UUID
|
||||
*
|
||||
* @return UuidInterface an instance of a UUID object
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public function build(CodecInterface $codec, string $bytes): UuidInterface
|
||||
{
|
||||
$lastBuilderException = null;
|
||||
|
||||
/** @var UuidBuilderInterface $builder */
|
||||
foreach ($this->builders as $builder) {
|
||||
try {
|
||||
return $builder->build($codec, $bytes);
|
||||
} catch (UnableToBuildUuidException $exception) {
|
||||
$lastBuilderException = $exception;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
throw new BuilderNotFoundException(
|
||||
'Could not find a suitable builder for the provided codec and fields',
|
||||
0,
|
||||
$lastBuilderException
|
||||
);
|
||||
}
|
||||
}
|
||||
39
vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php
vendored
Normal file
39
vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Builder;
|
||||
|
||||
use Ramsey\Uuid\Codec\CodecInterface;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
/**
|
||||
* A UUID builder builds instances of UuidInterface
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
interface UuidBuilderInterface
|
||||
{
|
||||
/**
|
||||
* Builds and returns a UuidInterface
|
||||
*
|
||||
* @param CodecInterface $codec The codec to use for building this UuidInterface instance
|
||||
* @param string $bytes The byte string from which to construct a UUID
|
||||
*
|
||||
* @return UuidInterface Implementations may choose to return more specific
|
||||
* instances of UUIDs that implement UuidInterface
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public function build(CodecInterface $codec, string $bytes): UuidInterface;
|
||||
}
|
||||
71
vendor/ramsey/uuid/src/Codec/CodecInterface.php
vendored
Normal file
71
vendor/ramsey/uuid/src/Codec/CodecInterface.php
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Codec;
|
||||
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
/**
|
||||
* A codec encodes and decodes a UUID according to defined rules
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
interface CodecInterface
|
||||
{
|
||||
/**
|
||||
* Returns a hexadecimal string representation of a UuidInterface
|
||||
*
|
||||
* @param UuidInterface $uuid The UUID for which to create a hexadecimal
|
||||
* string representation
|
||||
*
|
||||
* @return string Hexadecimal string representation of a UUID
|
||||
*
|
||||
* @psalm-return non-empty-string
|
||||
*/
|
||||
public function encode(UuidInterface $uuid): string;
|
||||
|
||||
/**
|
||||
* Returns a binary string representation of a UuidInterface
|
||||
*
|
||||
* @param UuidInterface $uuid The UUID for which to create a binary string
|
||||
* representation
|
||||
*
|
||||
* @return string Binary string representation of a UUID
|
||||
*
|
||||
* @psalm-return non-empty-string
|
||||
*/
|
||||
public function encodeBinary(UuidInterface $uuid): string;
|
||||
|
||||
/**
|
||||
* Returns a UuidInterface derived from a hexadecimal string representation
|
||||
*
|
||||
* @param string $encodedUuid The hexadecimal string representation to
|
||||
* convert into a UuidInterface instance
|
||||
*
|
||||
* @return UuidInterface An instance of a UUID decoded from a hexadecimal
|
||||
* string representation
|
||||
*/
|
||||
public function decode(string $encodedUuid): UuidInterface;
|
||||
|
||||
/**
|
||||
* Returns a UuidInterface derived from a binary string representation
|
||||
*
|
||||
* @param string $bytes The binary string representation to convert into a
|
||||
* UuidInterface instance
|
||||
*
|
||||
* @return UuidInterface An instance of a UUID decoded from a binary string
|
||||
* representation
|
||||
*/
|
||||
public function decodeBytes(string $bytes): UuidInterface;
|
||||
}
|
||||
55
vendor/ramsey/uuid/src/Codec/GuidStringCodec.php
vendored
Normal file
55
vendor/ramsey/uuid/src/Codec/GuidStringCodec.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Codec;
|
||||
|
||||
use Ramsey\Uuid\Guid\Guid;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
use function bin2hex;
|
||||
use function substr;
|
||||
|
||||
/**
|
||||
* GuidStringCodec encodes and decodes globally unique identifiers (GUID)
|
||||
*
|
||||
* @see Guid
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class GuidStringCodec extends StringCodec
|
||||
{
|
||||
public function decode(string $encodedUuid): UuidInterface
|
||||
{
|
||||
$bytes = $this->getBytes($encodedUuid);
|
||||
|
||||
return $this->getBuilder()->build($this, $this->swapBytes($bytes));
|
||||
}
|
||||
|
||||
public function decodeBytes(string $bytes): UuidInterface
|
||||
{
|
||||
// Specifically call parent::decode to preserve correct byte order
|
||||
return parent::decode(bin2hex($bytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps bytes according to the GUID rules
|
||||
*/
|
||||
private function swapBytes(string $bytes): string
|
||||
{
|
||||
return $bytes[3] . $bytes[2] . $bytes[1] . $bytes[0]
|
||||
. $bytes[5] . $bytes[4]
|
||||
. $bytes[7] . $bytes[6]
|
||||
. substr($bytes, 8);
|
||||
}
|
||||
}
|
||||
112
vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php
vendored
Normal file
112
vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Codec;
|
||||
|
||||
use Ramsey\Uuid\Exception\InvalidArgumentException;
|
||||
use Ramsey\Uuid\Exception\UnsupportedOperationException;
|
||||
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
use function strlen;
|
||||
use function substr;
|
||||
|
||||
/**
|
||||
* OrderedTimeCodec encodes and decodes a UUID, optimizing the byte order for
|
||||
* more efficient storage
|
||||
*
|
||||
* For binary representations of version 1 UUID, this codec may be used to
|
||||
* reorganize the time fields, making the UUID closer to sequential when storing
|
||||
* the bytes. According to Percona, this optimization can improve database
|
||||
* INSERTs and SELECTs using the UUID column as a key.
|
||||
*
|
||||
* The string representation of the UUID will remain unchanged. Only the binary
|
||||
* representation is reordered.
|
||||
*
|
||||
* **PLEASE NOTE:** Binary representations of UUIDs encoded with this codec must
|
||||
* be decoded with this codec. Decoding using another codec can result in
|
||||
* malformed UUIDs.
|
||||
*
|
||||
* @link https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/ Storing UUID Values in MySQL
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class OrderedTimeCodec extends StringCodec
|
||||
{
|
||||
/**
|
||||
* Returns a binary string representation of a UUID, with the timestamp
|
||||
* fields rearranged for optimized storage
|
||||
*
|
||||
* @inheritDoc
|
||||
* @psalm-return non-empty-string
|
||||
* @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
|
||||
* @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
|
||||
*/
|
||||
public function encodeBinary(UuidInterface $uuid): string
|
||||
{
|
||||
if (
|
||||
!($uuid->getFields() instanceof Rfc4122FieldsInterface)
|
||||
|| $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME
|
||||
) {
|
||||
throw new InvalidArgumentException(
|
||||
'Expected RFC 4122 version 1 (time-based) UUID'
|
||||
);
|
||||
}
|
||||
|
||||
$bytes = $uuid->getFields()->getBytes();
|
||||
|
||||
return $bytes[6] . $bytes[7]
|
||||
. $bytes[4] . $bytes[5]
|
||||
. $bytes[0] . $bytes[1] . $bytes[2] . $bytes[3]
|
||||
. substr($bytes, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a UuidInterface derived from an ordered-time binary string
|
||||
* representation
|
||||
*
|
||||
* @throws InvalidArgumentException if $bytes is an invalid length
|
||||
*
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function decodeBytes(string $bytes): UuidInterface
|
||||
{
|
||||
if (strlen($bytes) !== 16) {
|
||||
throw new InvalidArgumentException(
|
||||
'$bytes string should contain 16 characters.'
|
||||
);
|
||||
}
|
||||
|
||||
// Rearrange the bytes to their original order.
|
||||
$rearrangedBytes = $bytes[4] . $bytes[5] . $bytes[6] . $bytes[7]
|
||||
. $bytes[2] . $bytes[3]
|
||||
. $bytes[0] . $bytes[1]
|
||||
. substr($bytes, 8);
|
||||
|
||||
$uuid = parent::decodeBytes($rearrangedBytes);
|
||||
|
||||
if (
|
||||
!($uuid->getFields() instanceof Rfc4122FieldsInterface)
|
||||
|| $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME
|
||||
) {
|
||||
throw new UnsupportedOperationException(
|
||||
'Attempting to decode a non-time-based UUID using '
|
||||
. 'OrderedTimeCodec'
|
||||
);
|
||||
}
|
||||
|
||||
return $uuid;
|
||||
}
|
||||
}
|
||||
137
vendor/ramsey/uuid/src/Codec/StringCodec.php
vendored
Normal file
137
vendor/ramsey/uuid/src/Codec/StringCodec.php
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Codec;
|
||||
|
||||
use Ramsey\Uuid\Builder\UuidBuilderInterface;
|
||||
use Ramsey\Uuid\Exception\InvalidArgumentException;
|
||||
use Ramsey\Uuid\Exception\InvalidUuidStringException;
|
||||
use Ramsey\Uuid\Rfc4122\FieldsInterface;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
use function hex2bin;
|
||||
use function implode;
|
||||
use function str_replace;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
|
||||
/**
|
||||
* StringCodec encodes and decodes RFC 4122 UUIDs
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc4122
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class StringCodec implements CodecInterface
|
||||
{
|
||||
/**
|
||||
* @var UuidBuilderInterface
|
||||
*/
|
||||
private $builder;
|
||||
|
||||
/**
|
||||
* Constructs a StringCodec
|
||||
*
|
||||
* @param UuidBuilderInterface $builder The builder to use when encoding UUIDs
|
||||
*/
|
||||
public function __construct(UuidBuilderInterface $builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
}
|
||||
|
||||
public function encode(UuidInterface $uuid): string
|
||||
{
|
||||
/** @var FieldsInterface $fields */
|
||||
$fields = $uuid->getFields();
|
||||
|
||||
return $fields->getTimeLow()->toString()
|
||||
. '-'
|
||||
. $fields->getTimeMid()->toString()
|
||||
. '-'
|
||||
. $fields->getTimeHiAndVersion()->toString()
|
||||
. '-'
|
||||
. $fields->getClockSeqHiAndReserved()->toString()
|
||||
. $fields->getClockSeqLow()->toString()
|
||||
. '-'
|
||||
. $fields->getNode()->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-return non-empty-string
|
||||
* @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
|
||||
* @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
|
||||
*/
|
||||
public function encodeBinary(UuidInterface $uuid): string
|
||||
{
|
||||
return $uuid->getFields()->getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidUuidStringException
|
||||
*
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function decode(string $encodedUuid): UuidInterface
|
||||
{
|
||||
return $this->builder->build($this, $this->getBytes($encodedUuid));
|
||||
}
|
||||
|
||||
public function decodeBytes(string $bytes): UuidInterface
|
||||
{
|
||||
if (strlen($bytes) !== 16) {
|
||||
throw new InvalidArgumentException(
|
||||
'$bytes string should contain 16 characters.'
|
||||
);
|
||||
}
|
||||
|
||||
return $this->builder->build($this, $bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the UUID builder
|
||||
*/
|
||||
protected function getBuilder(): UuidBuilderInterface
|
||||
{
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a byte string of the UUID
|
||||
*/
|
||||
protected function getBytes(string $encodedUuid): string
|
||||
{
|
||||
$parsedUuid = str_replace(
|
||||
['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}', '-'],
|
||||
'',
|
||||
$encodedUuid
|
||||
);
|
||||
|
||||
$components = [
|
||||
substr($parsedUuid, 0, 8),
|
||||
substr($parsedUuid, 8, 4),
|
||||
substr($parsedUuid, 12, 4),
|
||||
substr($parsedUuid, 16, 4),
|
||||
substr($parsedUuid, 20),
|
||||
];
|
||||
|
||||
if (!Uuid::isValid(implode('-', $components))) {
|
||||
throw new InvalidUuidStringException(
|
||||
'Invalid UUID string: ' . $encodedUuid
|
||||
);
|
||||
}
|
||||
|
||||
return (string) hex2bin($parsedUuid);
|
||||
}
|
||||
}
|
||||
112
vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php
vendored
Normal file
112
vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Codec;
|
||||
|
||||
use Ramsey\Uuid\Exception\InvalidUuidStringException;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
use function bin2hex;
|
||||
use function sprintf;
|
||||
use function substr;
|
||||
use function substr_replace;
|
||||
|
||||
/**
|
||||
* TimestampFirstCombCodec encodes and decodes COMBs, with the timestamp as the
|
||||
* first 48 bits
|
||||
*
|
||||
* In contrast with the TimestampLastCombCodec, the TimestampFirstCombCodec
|
||||
* adds the timestamp to the first 48 bits of the COMB. To generate a
|
||||
* timestamp-first COMB, set the TimestampFirstCombCodec as the codec, along
|
||||
* with the CombGenerator as the random generator.
|
||||
*
|
||||
* ``` php
|
||||
* $factory = new UuidFactory();
|
||||
*
|
||||
* $factory->setCodec(new TimestampFirstCombCodec($factory->getUuidBuilder()));
|
||||
*
|
||||
* $factory->setRandomGenerator(new CombGenerator(
|
||||
* $factory->getRandomGenerator(),
|
||||
* $factory->getNumberConverter()
|
||||
* ));
|
||||
*
|
||||
* $timestampFirstComb = $factory->uuid4();
|
||||
* ```
|
||||
*
|
||||
* @link https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class TimestampFirstCombCodec extends StringCodec
|
||||
{
|
||||
/**
|
||||
* @psalm-return non-empty-string
|
||||
* @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
|
||||
* @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
|
||||
*/
|
||||
public function encode(UuidInterface $uuid): string
|
||||
{
|
||||
$bytes = $this->swapBytes($uuid->getFields()->getBytes());
|
||||
|
||||
return sprintf(
|
||||
'%08s-%04s-%04s-%04s-%012s',
|
||||
bin2hex(substr($bytes, 0, 4)),
|
||||
bin2hex(substr($bytes, 4, 2)),
|
||||
bin2hex(substr($bytes, 6, 2)),
|
||||
bin2hex(substr($bytes, 8, 2)),
|
||||
bin2hex(substr($bytes, 10))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-return non-empty-string
|
||||
* @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
|
||||
* @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
|
||||
*/
|
||||
public function encodeBinary(UuidInterface $uuid): string
|
||||
{
|
||||
return $this->swapBytes($uuid->getFields()->getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidUuidStringException
|
||||
*
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function decode(string $encodedUuid): UuidInterface
|
||||
{
|
||||
$bytes = $this->getBytes($encodedUuid);
|
||||
|
||||
return $this->getBuilder()->build($this, $this->swapBytes($bytes));
|
||||
}
|
||||
|
||||
public function decodeBytes(string $bytes): UuidInterface
|
||||
{
|
||||
return $this->getBuilder()->build($this, $this->swapBytes($bytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps bytes according to the timestamp-first COMB rules
|
||||
*/
|
||||
private function swapBytes(string $bytes): string
|
||||
{
|
||||
$first48Bits = substr($bytes, 0, 6);
|
||||
$last48Bits = substr($bytes, -6);
|
||||
|
||||
$bytes = substr_replace($bytes, $last48Bits, 0, 6);
|
||||
$bytes = substr_replace($bytes, $first48Bits, -6);
|
||||
|
||||
return $bytes;
|
||||
}
|
||||
}
|
||||
51
vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php
vendored
Normal file
51
vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Codec;
|
||||
|
||||
/**
|
||||
* TimestampLastCombCodec encodes and decodes COMBs, with the timestamp as the
|
||||
* last 48 bits
|
||||
*
|
||||
* The CombGenerator when used with the StringCodec (and, by proxy, the
|
||||
* TimestampLastCombCodec) adds the timestamp to the last 48 bits of the COMB.
|
||||
* The TimestampLastCombCodec is provided for the sake of consistency. In
|
||||
* practice, it is identical to the standard StringCodec but, it may be used
|
||||
* with the CombGenerator for additional context when reading code.
|
||||
*
|
||||
* Consider the following code. By default, the codec used by UuidFactory is the
|
||||
* StringCodec, but here, we explicitly set the TimestampLastCombCodec. It is
|
||||
* redundant, but it is clear that we intend this COMB to be generated with the
|
||||
* timestamp appearing at the end.
|
||||
*
|
||||
* ``` php
|
||||
* $factory = new UuidFactory();
|
||||
*
|
||||
* $factory->setCodec(new TimestampLastCombCodec($factory->getUuidBuilder()));
|
||||
*
|
||||
* $factory->setRandomGenerator(new CombGenerator(
|
||||
* $factory->getRandomGenerator(),
|
||||
* $factory->getNumberConverter()
|
||||
* ));
|
||||
*
|
||||
* $timestampLastComb = $factory->uuid4();
|
||||
* ```
|
||||
*
|
||||
* @link https://www.informit.com/articles/printerfriendly/25862 The Cost of GUIDs as Primary Keys
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class TimestampLastCombCodec extends StringCodec
|
||||
{
|
||||
}
|
||||
57
vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php
vendored
Normal file
57
vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Converter\Number;
|
||||
|
||||
use Ramsey\Uuid\Converter\NumberConverterInterface;
|
||||
use Ramsey\Uuid\Math\BrickMathCalculator;
|
||||
|
||||
/**
|
||||
* Previously used to integrate moontoast/math as a bignum arithmetic library,
|
||||
* BigNumberConverter is deprecated in favor of GenericNumberConverter
|
||||
*
|
||||
* @deprecated Transition to {@see GenericNumberConverter}.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class BigNumberConverter implements NumberConverterInterface
|
||||
{
|
||||
/**
|
||||
* @var NumberConverterInterface
|
||||
*/
|
||||
private $converter;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->converter = new GenericNumberConverter(new BrickMathCalculator());
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @psalm-pure
|
||||
*/
|
||||
public function fromHex(string $hex): string
|
||||
{
|
||||
return $this->converter->fromHex($hex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @psalm-pure
|
||||
*/
|
||||
public function toHex(string $number): string
|
||||
{
|
||||
return $this->converter->toHex($number);
|
||||
}
|
||||
}
|
||||
25
vendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php
vendored
Normal file
25
vendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Converter\Number;
|
||||
|
||||
/**
|
||||
* @deprecated DegradedNumberConverter is no longer necessary for converting
|
||||
* numbers on 32-bit systems. Transition to {@see GenericNumberConverter}.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class DegradedNumberConverter extends BigNumberConverter
|
||||
{
|
||||
}
|
||||
62
vendor/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php
vendored
Normal file
62
vendor/ramsey/uuid/src/Converter/Number/GenericNumberConverter.php
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Converter\Number;
|
||||
|
||||
use Ramsey\Uuid\Converter\NumberConverterInterface;
|
||||
use Ramsey\Uuid\Math\CalculatorInterface;
|
||||
use Ramsey\Uuid\Type\Integer as IntegerObject;
|
||||
|
||||
/**
|
||||
* GenericNumberConverter uses the provided calculate to convert decimal
|
||||
* numbers to and from hexadecimal values
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class GenericNumberConverter implements NumberConverterInterface
|
||||
{
|
||||
/**
|
||||
* @var CalculatorInterface
|
||||
*/
|
||||
private $calculator;
|
||||
|
||||
public function __construct(CalculatorInterface $calculator)
|
||||
{
|
||||
$this->calculator = $calculator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @psalm-pure
|
||||
* @psalm-return numeric-string
|
||||
* @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
|
||||
* @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
|
||||
*/
|
||||
public function fromHex(string $hex): string
|
||||
{
|
||||
return $this->calculator->fromBase($hex, 16)->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @psalm-pure
|
||||
* @psalm-return non-empty-string
|
||||
* @psalm-suppress MoreSpecificReturnType we know that the retrieved `string` is never empty
|
||||
* @psalm-suppress LessSpecificReturnStatement we know that the retrieved `string` is never empty
|
||||
*/
|
||||
public function toHex(string $number): string
|
||||
{
|
||||
return $this->calculator->toBase(new IntegerObject($number), 16);
|
||||
}
|
||||
}
|
||||
57
vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php
vendored
Normal file
57
vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Converter;
|
||||
|
||||
/**
|
||||
* A number converter converts UUIDs from hexadecimal characters into
|
||||
* representations of integers and vice versa
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
interface NumberConverterInterface
|
||||
{
|
||||
/**
|
||||
* Converts a hexadecimal number into an string integer representation of
|
||||
* the number
|
||||
*
|
||||
* The integer representation returned is a string representation of the
|
||||
* integer, to accommodate unsigned integers greater than PHP_INT_MAX.
|
||||
*
|
||||
* @param string $hex The hexadecimal string representation to convert
|
||||
*
|
||||
* @return string String representation of an integer
|
||||
*
|
||||
* @psalm-return numeric-string
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public function fromHex(string $hex): string;
|
||||
|
||||
/**
|
||||
* Converts a string integer representation into a hexadecimal string
|
||||
* representation of the number
|
||||
*
|
||||
* @param string $number A string integer representation to convert; this
|
||||
* must be a numeric string to accommodate unsigned integers greater
|
||||
* than PHP_INT_MAX.
|
||||
*
|
||||
* @return string Hexadecimal string
|
||||
*
|
||||
* @psalm-return non-empty-string
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public function toHex(string $number): string;
|
||||
}
|
||||
51
vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php
vendored
Normal file
51
vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Converter\Time;
|
||||
|
||||
use Ramsey\Uuid\Converter\TimeConverterInterface;
|
||||
use Ramsey\Uuid\Math\BrickMathCalculator;
|
||||
use Ramsey\Uuid\Type\Hexadecimal;
|
||||
use Ramsey\Uuid\Type\Time;
|
||||
|
||||
/**
|
||||
* Previously used to integrate moontoast/math as a bignum arithmetic library,
|
||||
* BigNumberTimeConverter is deprecated in favor of GenericTimeConverter
|
||||
*
|
||||
* @deprecated Transition to {@see GenericTimeConverter}.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class BigNumberTimeConverter implements TimeConverterInterface
|
||||
{
|
||||
/**
|
||||
* @var TimeConverterInterface
|
||||
*/
|
||||
private $converter;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->converter = new GenericTimeConverter(new BrickMathCalculator());
|
||||
}
|
||||
|
||||
public function calculateTime(string $seconds, string $microseconds): Hexadecimal
|
||||
{
|
||||
return $this->converter->calculateTime($seconds, $microseconds);
|
||||
}
|
||||
|
||||
public function convertTime(Hexadecimal $uuidTimestamp): Time
|
||||
{
|
||||
return $this->converter->convertTime($uuidTimestamp);
|
||||
}
|
||||
}
|
||||
25
vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php
vendored
Normal file
25
vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Converter\Time;
|
||||
|
||||
/**
|
||||
* @deprecated DegradedTimeConverter is no longer necessary for converting
|
||||
* time on 32-bit systems. Transition to {@see GenericTimeConverter}.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class DegradedTimeConverter extends BigNumberTimeConverter
|
||||
{
|
||||
}
|
||||
124
vendor/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php
vendored
Normal file
124
vendor/ramsey/uuid/src/Converter/Time/GenericTimeConverter.php
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Converter\Time;
|
||||
|
||||
use Ramsey\Uuid\Converter\TimeConverterInterface;
|
||||
use Ramsey\Uuid\Math\CalculatorInterface;
|
||||
use Ramsey\Uuid\Math\RoundingMode;
|
||||
use Ramsey\Uuid\Type\Hexadecimal;
|
||||
use Ramsey\Uuid\Type\Integer as IntegerObject;
|
||||
use Ramsey\Uuid\Type\Time;
|
||||
|
||||
use function explode;
|
||||
use function str_pad;
|
||||
|
||||
use const STR_PAD_LEFT;
|
||||
|
||||
/**
|
||||
* GenericTimeConverter uses the provided calculator to calculate and convert
|
||||
* time values
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class GenericTimeConverter implements TimeConverterInterface
|
||||
{
|
||||
/**
|
||||
* The number of 100-nanosecond intervals from the Gregorian calendar epoch
|
||||
* to the Unix epoch.
|
||||
*/
|
||||
private const GREGORIAN_TO_UNIX_INTERVALS = '122192928000000000';
|
||||
|
||||
/**
|
||||
* The number of 100-nanosecond intervals in one second.
|
||||
*/
|
||||
private const SECOND_INTERVALS = '10000000';
|
||||
|
||||
/**
|
||||
* The number of 100-nanosecond intervals in one microsecond.
|
||||
*/
|
||||
private const MICROSECOND_INTERVALS = '10';
|
||||
|
||||
/**
|
||||
* @var CalculatorInterface
|
||||
*/
|
||||
private $calculator;
|
||||
|
||||
public function __construct(CalculatorInterface $calculator)
|
||||
{
|
||||
$this->calculator = $calculator;
|
||||
}
|
||||
|
||||
public function calculateTime(string $seconds, string $microseconds): Hexadecimal
|
||||
{
|
||||
$timestamp = new Time($seconds, $microseconds);
|
||||
|
||||
// Convert the seconds into a count of 100-nanosecond intervals.
|
||||
$sec = $this->calculator->multiply(
|
||||
$timestamp->getSeconds(),
|
||||
new IntegerObject(self::SECOND_INTERVALS)
|
||||
);
|
||||
|
||||
// Convert the microseconds into a count of 100-nanosecond intervals.
|
||||
$usec = $this->calculator->multiply(
|
||||
$timestamp->getMicroseconds(),
|
||||
new IntegerObject(self::MICROSECOND_INTERVALS)
|
||||
);
|
||||
|
||||
// Combine the seconds and microseconds intervals and add the count of
|
||||
// 100-nanosecond intervals from the Gregorian calendar epoch to the
|
||||
// Unix epoch. This gives us the correct count of 100-nanosecond
|
||||
// intervals since the Gregorian calendar epoch for the given seconds
|
||||
// and microseconds.
|
||||
/** @var IntegerObject $uuidTime */
|
||||
$uuidTime = $this->calculator->add(
|
||||
$sec,
|
||||
$usec,
|
||||
new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS)
|
||||
);
|
||||
|
||||
$uuidTimeHex = str_pad(
|
||||
$this->calculator->toHexadecimal($uuidTime)->toString(),
|
||||
16,
|
||||
'0',
|
||||
STR_PAD_LEFT
|
||||
);
|
||||
|
||||
return new Hexadecimal($uuidTimeHex);
|
||||
}
|
||||
|
||||
public function convertTime(Hexadecimal $uuidTimestamp): Time
|
||||
{
|
||||
// From the total, subtract the number of 100-nanosecond intervals from
|
||||
// the Gregorian calendar epoch to the Unix epoch. This gives us the
|
||||
// number of 100-nanosecond intervals from the Unix epoch, which also
|
||||
// includes the microtime.
|
||||
$epochNanoseconds = $this->calculator->subtract(
|
||||
$this->calculator->toInteger($uuidTimestamp),
|
||||
new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS)
|
||||
);
|
||||
|
||||
// Convert the 100-nanosecond intervals into seconds and microseconds.
|
||||
$unixTimestamp = $this->calculator->divide(
|
||||
RoundingMode::HALF_UP,
|
||||
6,
|
||||
$epochNanoseconds,
|
||||
new IntegerObject(self::SECOND_INTERVALS)
|
||||
);
|
||||
|
||||
$split = explode('.', (string) $unixTimestamp, 2);
|
||||
|
||||
return new Time($split[0], $split[1] ?? 0);
|
||||
}
|
||||
}
|
||||
183
vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php
vendored
Normal file
183
vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Converter\Time;
|
||||
|
||||
use Ramsey\Uuid\Converter\TimeConverterInterface;
|
||||
use Ramsey\Uuid\Math\BrickMathCalculator;
|
||||
use Ramsey\Uuid\Math\CalculatorInterface;
|
||||
use Ramsey\Uuid\Type\Hexadecimal;
|
||||
use Ramsey\Uuid\Type\Integer as IntegerObject;
|
||||
use Ramsey\Uuid\Type\Time;
|
||||
|
||||
use function count;
|
||||
use function dechex;
|
||||
use function explode;
|
||||
use function is_float;
|
||||
use function is_int;
|
||||
use function str_pad;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
|
||||
use const STR_PAD_LEFT;
|
||||
use const STR_PAD_RIGHT;
|
||||
|
||||
/**
|
||||
* PhpTimeConverter uses built-in PHP functions and standard math operations
|
||||
* available to the PHP programming language to provide facilities for
|
||||
* converting parts of time into representations that may be used in UUIDs
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class PhpTimeConverter implements TimeConverterInterface
|
||||
{
|
||||
/**
|
||||
* The number of 100-nanosecond intervals from the Gregorian calendar epoch
|
||||
* to the Unix epoch.
|
||||
*/
|
||||
private const GREGORIAN_TO_UNIX_INTERVALS = 0x01b21dd213814000;
|
||||
|
||||
/**
|
||||
* The number of 100-nanosecond intervals in one second.
|
||||
*/
|
||||
private const SECOND_INTERVALS = 10000000;
|
||||
|
||||
/**
|
||||
* The number of 100-nanosecond intervals in one microsecond.
|
||||
*/
|
||||
private const MICROSECOND_INTERVALS = 10;
|
||||
|
||||
/**
|
||||
* @var CalculatorInterface
|
||||
*/
|
||||
private $calculator;
|
||||
|
||||
/**
|
||||
* @var TimeConverterInterface
|
||||
*/
|
||||
private $fallbackConverter;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $phpPrecision;
|
||||
|
||||
public function __construct(
|
||||
?CalculatorInterface $calculator = null,
|
||||
?TimeConverterInterface $fallbackConverter = null
|
||||
) {
|
||||
if ($calculator === null) {
|
||||
$calculator = new BrickMathCalculator();
|
||||
}
|
||||
|
||||
if ($fallbackConverter === null) {
|
||||
$fallbackConverter = new GenericTimeConverter($calculator);
|
||||
}
|
||||
|
||||
$this->calculator = $calculator;
|
||||
$this->fallbackConverter = $fallbackConverter;
|
||||
$this->phpPrecision = (int) ini_get('precision');
|
||||
}
|
||||
|
||||
public function calculateTime(string $seconds, string $microseconds): Hexadecimal
|
||||
{
|
||||
$seconds = new IntegerObject($seconds);
|
||||
$microseconds = new IntegerObject($microseconds);
|
||||
|
||||
// Calculate the count of 100-nanosecond intervals since the Gregorian
|
||||
// calendar epoch for the given seconds and microseconds.
|
||||
$uuidTime = ((int) $seconds->toString() * self::SECOND_INTERVALS)
|
||||
+ ((int) $microseconds->toString() * self::MICROSECOND_INTERVALS)
|
||||
+ self::GREGORIAN_TO_UNIX_INTERVALS;
|
||||
|
||||
// Check to see whether we've overflowed the max/min integer size.
|
||||
// If so, we will default to a different time converter.
|
||||
/** @psalm-suppress RedundantCondition */
|
||||
if (!is_int($uuidTime)) {
|
||||
return $this->fallbackConverter->calculateTime(
|
||||
$seconds->toString(),
|
||||
$microseconds->toString()
|
||||
);
|
||||
}
|
||||
|
||||
return new Hexadecimal(str_pad(dechex((int) $uuidTime), 16, '0', STR_PAD_LEFT));
|
||||
}
|
||||
|
||||
public function convertTime(Hexadecimal $uuidTimestamp): Time
|
||||
{
|
||||
$timestamp = $this->calculator->toInteger($uuidTimestamp);
|
||||
|
||||
// Convert the 100-nanosecond intervals into seconds and microseconds.
|
||||
$splitTime = $this->splitTime(
|
||||
((int) $timestamp->toString() - self::GREGORIAN_TO_UNIX_INTERVALS)
|
||||
/ self::SECOND_INTERVALS
|
||||
);
|
||||
|
||||
if (count($splitTime) === 0) {
|
||||
return $this->fallbackConverter->convertTime($uuidTimestamp);
|
||||
}
|
||||
|
||||
return new Time($splitTime['sec'], $splitTime['usec']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|float $time The time to split into seconds and microseconds
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private function splitTime($time): array
|
||||
{
|
||||
$split = explode('.', (string) $time, 2);
|
||||
|
||||
// If the $time value is a float but $split only has 1 element, then the
|
||||
// float math was rounded up to the next second, so we want to return
|
||||
// an empty array to allow use of the fallback converter.
|
||||
if (is_float($time) && count($split) === 1) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (count($split) === 1) {
|
||||
return [
|
||||
'sec' => $split[0],
|
||||
'usec' => '0',
|
||||
];
|
||||
}
|
||||
|
||||
// If the microseconds are less than six characters AND the length of
|
||||
// the number is greater than or equal to the PHP precision, then it's
|
||||
// possible that we lost some precision for the microseconds. Return an
|
||||
// empty array, so that we can choose to use the fallback converter.
|
||||
if (strlen($split[1]) < 6 && strlen((string) $time) >= $this->phpPrecision) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$microseconds = $split[1];
|
||||
|
||||
// Ensure the microseconds are no longer than 6 digits. If they are,
|
||||
// truncate the number to the first 6 digits and round up, if needed.
|
||||
if (strlen($microseconds) > 6) {
|
||||
$roundingDigit = (int) substr($microseconds, 6, 1);
|
||||
$microseconds = (int) substr($microseconds, 0, 6);
|
||||
|
||||
if ($roundingDigit >= 5) {
|
||||
$microseconds++;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'sec' => $split[0],
|
||||
'usec' => str_pad((string) $microseconds, 6, '0', STR_PAD_RIGHT),
|
||||
];
|
||||
}
|
||||
}
|
||||
58
vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php
vendored
Normal file
58
vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid\Converter;
|
||||
|
||||
use Ramsey\Uuid\Type\Hexadecimal;
|
||||
use Ramsey\Uuid\Type\Time;
|
||||
|
||||
/**
|
||||
* A time converter converts timestamps into representations that may be used
|
||||
* in UUIDs
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
interface TimeConverterInterface
|
||||
{
|
||||
/**
|
||||
* Uses the provided seconds and micro-seconds to calculate the count of
|
||||
* 100-nanosecond intervals since UTC 00:00:00.00, 15 October 1582, for
|
||||
* RFC 4122 variant UUIDs
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc4122#section-4.2.2 RFC 4122, § 4.2.2: Generation Details
|
||||
*
|
||||
* @param string $seconds A string representation of the number of seconds
|
||||
* since the Unix epoch for the time to calculate
|
||||
* @param string $microseconds A string representation of the micro-seconds
|
||||
* associated with the time to calculate
|
||||
*
|
||||
* @return Hexadecimal The full UUID timestamp as a Hexadecimal value
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public function calculateTime(string $seconds, string $microseconds): Hexadecimal;
|
||||
|
||||
/**
|
||||
* Converts a timestamp extracted from a UUID to a Unix timestamp
|
||||
*
|
||||
* @param Hexadecimal $uuidTimestamp A hexadecimal representation of a UUID
|
||||
* timestamp; a UUID timestamp is a count of 100-nanosecond intervals
|
||||
* since UTC 00:00:00.00, 15 October 1582.
|
||||
*
|
||||
* @return Time An instance of {@see Time}
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public function convertTime(Hexadecimal $uuidTimestamp): Time;
|
||||
}
|
||||
25
vendor/ramsey/uuid/src/DegradedUuid.php
vendored
Normal file
25
vendor/ramsey/uuid/src/DegradedUuid.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid;
|
||||
|
||||
/**
|
||||
* @deprecated DegradedUuid is no longer necessary to represent UUIDs on 32-bit
|
||||
* systems. Transition typehints to {@see UuidInterface}.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class DegradedUuid extends Uuid
|
||||
{
|
||||
}
|
||||
147
vendor/ramsey/uuid/src/DeprecatedUuidInterface.php
vendored
Normal file
147
vendor/ramsey/uuid/src/DeprecatedUuidInterface.php
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Ramsey\Uuid\Converter\NumberConverterInterface;
|
||||
|
||||
/**
|
||||
* This interface encapsulates deprecated methods for ramsey/uuid; this
|
||||
* interface and its methods will be removed in ramsey/uuid 5.0.0.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
interface DeprecatedUuidInterface
|
||||
{
|
||||
/**
|
||||
* @deprecated This method will be removed in 5.0.0. There is no alternative
|
||||
* recommendation, so plan accordingly.
|
||||
*/
|
||||
public function getNumberConverter(): NumberConverterInterface;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getFieldsHex(): array;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqHiAndReserved()}.
|
||||
*/
|
||||
public function getClockSeqHiAndReservedHex(): string;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeqLow()}.
|
||||
*/
|
||||
public function getClockSeqLowHex(): string;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getClockSeq()}.
|
||||
*/
|
||||
public function getClockSequenceHex(): string;
|
||||
|
||||
/**
|
||||
* @deprecated In ramsey/uuid version 5.0.0, this will be removed from the
|
||||
* interface. It is available at {@see UuidV1::getDateTime()}.
|
||||
*/
|
||||
public function getDateTime(): DateTimeInterface;
|
||||
|
||||
/**
|
||||
* @deprecated This method will be removed in 5.0.0. There is no direct
|
||||
* alternative, but the same information may be obtained by splitting
|
||||
* in half the value returned by {@see UuidInterface::getHex()}.
|
||||
*/
|
||||
public function getLeastSignificantBitsHex(): string;
|
||||
|
||||
/**
|
||||
* @deprecated This method will be removed in 5.0.0. There is no direct
|
||||
* alternative, but the same information may be obtained by splitting
|
||||
* in half the value returned by {@see UuidInterface::getHex()}.
|
||||
*/
|
||||
public function getMostSignificantBitsHex(): string;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getNode()}.
|
||||
*/
|
||||
public function getNodeHex(): string;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeHiAndVersion()}.
|
||||
*/
|
||||
public function getTimeHiAndVersionHex(): string;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeLow()}.
|
||||
*/
|
||||
public function getTimeLowHex(): string;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimeMid()}.
|
||||
*/
|
||||
public function getTimeMidHex(): string;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getTimestamp()}.
|
||||
*/
|
||||
public function getTimestampHex(): string;
|
||||
|
||||
/**
|
||||
* @deprecated In ramsey/uuid version 5.0.0, this will be removed from this
|
||||
* interface. It has moved to {@see \Ramsey\Uuid\Rfc4122\UuidInterface::getUrn()}.
|
||||
*/
|
||||
public function getUrn(): string;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVariant()}.
|
||||
*/
|
||||
public function getVariant(): ?int;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVersion()}.
|
||||
*/
|
||||
public function getVersion(): ?int;
|
||||
}
|
||||
370
vendor/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php
vendored
Normal file
370
vendor/ramsey/uuid/src/DeprecatedUuidMethodsTrait.php
vendored
Normal file
@@ -0,0 +1,370 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the ramsey/uuid library
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
|
||||
* @license http://opensource.org/licenses/MIT MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Ramsey\Uuid;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use Ramsey\Uuid\Converter\NumberConverterInterface;
|
||||
use Ramsey\Uuid\Converter\TimeConverterInterface;
|
||||
use Ramsey\Uuid\Exception\DateTimeException;
|
||||
use Ramsey\Uuid\Exception\UnsupportedOperationException;
|
||||
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
|
||||
use Throwable;
|
||||
|
||||
use function str_pad;
|
||||
use function substr;
|
||||
|
||||
use const STR_PAD_LEFT;
|
||||
|
||||
/**
|
||||
* This trait encapsulates deprecated methods for ramsey/uuid; this trait and
|
||||
* its methods will be removed in ramsey/uuid 5.0.0.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
trait DeprecatedUuidMethodsTrait
|
||||
{
|
||||
/**
|
||||
* @var Rfc4122FieldsInterface
|
||||
*/
|
||||
protected $fields;
|
||||
|
||||
/**
|
||||
* @var NumberConverterInterface
|
||||
*/
|
||||
protected $numberConverter;
|
||||
|
||||
/**
|
||||
* @var TimeConverterInterface
|
||||
*/
|
||||
protected $timeConverter;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
|
||||
* instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()}
|
||||
* and use the arbitrary-precision math library of your choice to
|
||||
* convert it to a string integer.
|
||||
*/
|
||||
public function getClockSeqHiAndReserved(): string
|
||||
{
|
||||
return $this->numberConverter->fromHex($this->fields->getClockSeqHiAndReserved()->toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
|
||||
* instance, you may call {@see Rfc4122FieldsInterface::getClockSeqHiAndReserved()}.
|
||||
*/
|
||||
public function getClockSeqHiAndReservedHex(): string
|
||||
{
|
||||
return $this->fields->getClockSeqHiAndReserved()->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
|
||||
* instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()}
|
||||
* and use the arbitrary-precision math library of your choice to
|
||||
* convert it to a string integer.
|
||||
*/
|
||||
public function getClockSeqLow(): string
|
||||
{
|
||||
return $this->numberConverter->fromHex($this->fields->getClockSeqLow()->toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
|
||||
* instance, you may call {@see Rfc4122FieldsInterface::getClockSeqLow()}.
|
||||
*/
|
||||
public function getClockSeqLowHex(): string
|
||||
{
|
||||
return $this->fields->getClockSeqLow()->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
|
||||
* instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()}
|
||||
* and use the arbitrary-precision math library of your choice to
|
||||
* convert it to a string integer.
|
||||
*/
|
||||
public function getClockSequence(): string
|
||||
{
|
||||
return $this->numberConverter->fromHex($this->fields->getClockSeq()->toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
|
||||
* instance, you may call {@see Rfc4122FieldsInterface::getClockSeq()}.
|
||||
*/
|
||||
public function getClockSequenceHex(): string
|
||||
{
|
||||
return $this->fields->getClockSeq()->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method will be removed in 5.0.0. There is no alternative
|
||||
* recommendation, so plan accordingly.
|
||||
*/
|
||||
public function getNumberConverter(): NumberConverterInterface
|
||||
{
|
||||
return $this->numberConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated In ramsey/uuid version 5.0.0, this will be removed.
|
||||
* It is available at {@see UuidV1::getDateTime()}.
|
||||
*
|
||||
* @return DateTimeImmutable An immutable instance of DateTimeInterface
|
||||
*
|
||||
* @throws UnsupportedOperationException if UUID is not time-based
|
||||
* @throws DateTimeException if DateTime throws an exception/error
|
||||
*/
|
||||
public function getDateTime(): DateTimeInterface
|
||||
{
|
||||
if ($this->fields->getVersion() !== 1) {
|
||||
throw new UnsupportedOperationException('Not a time-based UUID');
|
||||
}
|
||||
|
||||
$time = $this->timeConverter->convertTime($this->fields->getTimestamp());
|
||||
|
||||
try {
|
||||
return new DateTimeImmutable(
|
||||
'@'
|
||||
. $time->getSeconds()->toString()
|
||||
. '.'
|
||||
. str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT)
|
||||
);
|
||||
} catch (Throwable $e) {
|
||||
throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getFieldsHex(): array
|
||||
{
|
||||
return [
|
||||
'time_low' => $this->fields->getTimeLow()->toString(),
|
||||
'time_mid' => $this->fields->getTimeMid()->toString(),
|
||||
'time_hi_and_version' => $this->fields->getTimeHiAndVersion()->toString(),
|
||||
'clock_seq_hi_and_reserved' => $this->fields->getClockSeqHiAndReserved()->toString(),
|
||||
'clock_seq_low' => $this->fields->getClockSeqLow()->toString(),
|
||||
'node' => $this->fields->getNode()->toString(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method will be removed in 5.0.0. There is no direct
|
||||
* alternative, but the same information may be obtained by splitting
|
||||
* in half the value returned by {@see UuidInterface::getHex()}.
|
||||
*/
|
||||
public function getLeastSignificantBits(): string
|
||||
{
|
||||
$leastSignificantHex = substr($this->getHex()->toString(), 16);
|
||||
|
||||
return $this->numberConverter->fromHex($leastSignificantHex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method will be removed in 5.0.0. There is no direct
|
||||
* alternative, but the same information may be obtained by splitting
|
||||
* in half the value returned by {@see UuidInterface::getHex()}.
|
||||
*/
|
||||
public function getLeastSignificantBitsHex(): string
|
||||
{
|
||||
return substr($this->getHex()->toString(), 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method will be removed in 5.0.0. There is no direct
|
||||
* alternative, but the same information may be obtained by splitting
|
||||
* in half the value returned by {@see UuidInterface::getHex()}.
|
||||
*/
|
||||
public function getMostSignificantBits(): string
|
||||
{
|
||||
$mostSignificantHex = substr($this->getHex()->toString(), 0, 16);
|
||||
|
||||
return $this->numberConverter->fromHex($mostSignificantHex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method will be removed in 5.0.0. There is no direct
|
||||
* alternative, but the same information may be obtained by splitting
|
||||
* in half the value returned by {@see UuidInterface::getHex()}.
|
||||
*/
|
||||
public function getMostSignificantBitsHex(): string
|
||||
{
|
||||
return substr($this->getHex()->toString(), 0, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
|
||||
* instance, you may call {@see Rfc4122FieldsInterface::getNode()}
|
||||
* and use the arbitrary-precision math library of your choice to
|
||||
* convert it to a string integer.
|
||||
*/
|
||||
public function getNode(): string
|
||||
{
|
||||
return $this->numberConverter->fromHex($this->fields->getNode()->toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
|
||||
* instance, you may call {@see Rfc4122FieldsInterface::getNode()}.
|
||||
*/
|
||||
public function getNodeHex(): string
|
||||
{
|
||||
return $this->fields->getNode()->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
|
||||
* instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()}
|
||||
* and use the arbitrary-precision math library of your choice to
|
||||
* convert it to a string integer.
|
||||
*/
|
||||
public function getTimeHiAndVersion(): string
|
||||
{
|
||||
return $this->numberConverter->fromHex($this->fields->getTimeHiAndVersion()->toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
|
||||
* instance, you may call {@see Rfc4122FieldsInterface::getTimeHiAndVersion()}.
|
||||
*/
|
||||
public function getTimeHiAndVersionHex(): string
|
||||
{
|
||||
return $this->fields->getTimeHiAndVersion()->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
|
||||
* instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()}
|
||||
* and use the arbitrary-precision math library of your choice to
|
||||
* convert it to a string integer.
|
||||
*/
|
||||
public function getTimeLow(): string
|
||||
{
|
||||
return $this->numberConverter->fromHex($this->fields->getTimeLow()->toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
|
||||
* instance, you may call {@see Rfc4122FieldsInterface::getTimeLow()}.
|
||||
*/
|
||||
public function getTimeLowHex(): string
|
||||
{
|
||||
return $this->fields->getTimeLow()->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
|
||||
* instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()}
|
||||
* and use the arbitrary-precision math library of your choice to
|
||||
* convert it to a string integer.
|
||||
*/
|
||||
public function getTimeMid(): string
|
||||
{
|
||||
return $this->numberConverter->fromHex($this->fields->getTimeMid()->toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
|
||||
* instance, you may call {@see Rfc4122FieldsInterface::getTimeMid()}.
|
||||
*/
|
||||
public function getTimeMidHex(): string
|
||||
{
|
||||
return $this->fields->getTimeMid()->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
|
||||
* instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()}
|
||||
* and use the arbitrary-precision math library of your choice to
|
||||
* convert it to a string integer.
|
||||
*/
|
||||
public function getTimestamp(): string
|
||||
{
|
||||
if ($this->fields->getVersion() !== 1) {
|
||||
throw new UnsupportedOperationException('Not a time-based UUID');
|
||||
}
|
||||
|
||||
return $this->numberConverter->fromHex($this->fields->getTimestamp()->toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a {@see Rfc4122FieldsInterface}
|
||||
* instance, you may call {@see Rfc4122FieldsInterface::getTimestamp()}.
|
||||
*/
|
||||
public function getTimestampHex(): string
|
||||
{
|
||||
if ($this->fields->getVersion() !== 1) {
|
||||
throw new UnsupportedOperationException('Not a time-based UUID');
|
||||
}
|
||||
|
||||
return $this->fields->getTimestamp()->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This has moved to {@see Rfc4122FieldsInterface::getUrn()} and
|
||||
* is available on {@see \Ramsey\Uuid\Rfc4122\UuidV1},
|
||||
* {@see \Ramsey\Uuid\Rfc4122\UuidV3}, {@see \Ramsey\Uuid\Rfc4122\UuidV4},
|
||||
* and {@see \Ramsey\Uuid\Rfc4122\UuidV5}.
|
||||
*/
|
||||
public function getUrn(): string
|
||||
{
|
||||
return 'urn:uuid:' . $this->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVariant()}.
|
||||
*/
|
||||
public function getVariant(): ?int
|
||||
{
|
||||
return $this->fields->getVariant();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@see UuidInterface::getFields()} to get a
|
||||
* {@see FieldsInterface} instance. If it is a
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface} instance, you may call
|
||||
* {@see \Ramsey\Uuid\Rfc4122\FieldsInterface::getVersion()}.
|
||||
*/
|
||||
public function getVersion(): ?int
|
||||
{
|
||||
return $this->fields->getVersion();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user