[Web] Some minor fixes and improvements for PHP 8

master
andryyy 2021-08-08 16:06:55 +02:00
parent eec75690e0
commit cf8fdae277
No known key found for this signature in database
GPG Key ID: 8EC34FF2794E25EF
138 changed files with 2398 additions and 2342 deletions

View File

@ -81,7 +81,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
<div class="row">
<div class="col-sm-3 col-xs-5 text-right"><?=$lang['tfa']['tfa'];?>:</div>
<div class="col-sm-9 col-xs-7">
<p id="tfa_pretty"><?=$tfa_data['pretty'];?></p>
<p id="tfa_pretty"><?=(isset($tfa_data['pretty'])) ? $tfa_data['pretty'] : '';?></p>
<div id="tfa_keys">
<?php
if (!empty($tfa_data['additional'])) {
@ -133,7 +133,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
?>
<tr>
<td>
<?=($_SESSION['fido2_cid'] == $key_info['cid']) ? '<i class="bi bi-unlock-fill"></i> ' : NULL; ?><?=(!empty($key_info['fn']))?$key_info['fn']:$key_info['subject'];?>
<?=(isset($_SESSION['fido2_cid']) && $_SESSION['fido2_cid'] == $key_info['cid']) ? '<i class="bi bi-unlock-fill"></i> ' : NULL; ?><?=(!empty($key_info['fn']))?$key_info['fn']:$key_info['subject'];?>
</td>
<td style="min-width:240px;text-align: right">
<form style="display:inline;" method="post">
@ -222,13 +222,13 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
<div class="form-group">
<label class="control-label col-sm-3" for="allow_from_ro"><?=$lang['admin']['api_allow_from'];?>:</label>
<div class="col-sm-9">
<textarea class="form-control textarea-code" rows="7" name="allow_from" id="allow_from_ro" <?=($api_ro['skip_ip_check'] == 1) ? 'disabled' : null;?> required><?=htmlspecialchars($api_ro['allow_from']);?></textarea>
<textarea class="form-control textarea-code" rows="7" name="allow_from" id="allow_from_ro" <?=(isset($api_ro['skip_ip_check']) && $api_ro['skip_ip_check'] == 1) ? 'disabled' : null;?> required><?=(isset($api_ro['allow_from'])) ? htmlspecialchars($api_ro['allow_from']) : '';?></textarea>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-9">
<label>
<input type="checkbox" name="skip_ip_check" id="skip_ip_check_ro" <?=($api_ro['skip_ip_check'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['api_skip_ip_check'];?>
<input type="checkbox" name="skip_ip_check" id="skip_ip_check_ro" <?=(isset($api_ro['skip_ip_check']) && $api_ro['skip_ip_check'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['api_skip_ip_check'];?>
</label>
</div>
</div>
@ -241,7 +241,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
<div class="form-group">
<div class="col-sm-offset-3 col-sm-9">
<label>
<input type="checkbox" name="active" <?=($api_ro['active'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['activate_api'];?>
<input type="checkbox" name="active" <?=(isset($api_ro['active']) && $api_ro['active'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['activate_api'];?>
</label>
</div>
</div>
@ -1174,6 +1174,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
</tr>
<?php
$app_links = customize('get', 'app_links');
if ($app_links) {
foreach ($app_links as $row) {
foreach ($row as $key => $val) {
?>
@ -1185,6 +1186,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
<?php
}
}
}
foreach ($MAILCOW_APPS as $app) {
?>
<tr>
@ -1433,7 +1435,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
</div>
<div class="panel-body">
<p><?=$lang['admin']['rspamd_global_filters_info'];?></p>
<div id="confirm_show_rspamd_global_filters" class="<?=($_SESSION['show_rspamd_global_filters'] === true) ? 'hidden' : '';?>">
<div id="confirm_show_rspamd_global_filters" class="<?=(isset($_SESSION['show_rspamd_global_filters']) && $_SESSION['show_rspamd_global_filters'] === true) ? 'hidden' : '';?>">
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<label>
@ -1442,7 +1444,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
</div>
</div>
</div>
<div id="rspamd_global_filters" class="<?=($_SESSION['show_rspamd_global_filters'] !== true) ? 'hidden' : '';?>">
<div id="rspamd_global_filters" class="<?=(isset($_SESSION['show_rspamd_global_filters']) && $_SESSION['show_rspamd_global_filters'] === true) ? 'hidden' : '';?>">
<hr>
<span class="anchor" id="regexmaps"></span>
<h4><?=$lang['admin']['regex_maps'];?></h4>

View File

@ -14,7 +14,6 @@
width: auto;
float: left;
margin-right: 10px;
margin-top: auto;
}

View File

@ -76,7 +76,7 @@ $clamd_status = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["SKIP_CLAMD"])) ?
<div class="progress">
<div class="progress-bar progress-bar-info" role="progressbar" style="width:<?=round($solr_status['jvm']['memory']['raw']['used%']);?>%"></div>
</div>
<p><?=$lang['debug']['jvm_memory_solr'];?>: <?=$solr_status['jvm']['memory']['total'] - $solr_status['jvm']['memory']['free'];?> / <?=$solr_status['jvm']['memory']['total'];?>
<p><?=$lang['debug']['jvm_memory_solr'];?>: <?=(int)$solr_status['jvm']['memory']['total'] - (int)$solr_status['jvm']['memory']['free'];?> / <?=$solr_status['jvm']['memory']['total'];?>
(<?=round($solr_status['jvm']['memory']['raw']['used%']);?>%)</p>
<hr>
<p><?=$lang['debug']['uptime'];?>: <?=round($solr_status['status']['dovecot-fts']['uptime'] / 1000 / 60 / 60);?>h</p>

View File

@ -0,0 +1 @@
asd

View File

@ -489,8 +489,14 @@ function logger($_data = false) {
$task = substr(strtoupper(md5(uniqid(rand(), true))), 0, 6);
foreach ($_data['return'] as $return) {
$type = $return['type'];
$msg = null;
if (isset($return['msg'])) {
$msg = json_encode($return['msg'], JSON_UNESCAPED_UNICODE);
}
$call = null;
if (isset($return['log'])) {
$call = json_encode($return['log'], JSON_UNESCAPED_UNICODE);
}
if (!empty($_SESSION["dual-login"]["username"])) {
$user = $_SESSION["dual-login"]["username"] . ' => ' . $_SESSION['mailcow_cc_username'];
$role = $_SESSION["dual-login"]["role"] . ' => ' . $_SESSION['mailcow_cc_role'];
@ -685,9 +691,11 @@ function alertbox_log_parser($_data) {
// Get type
$type = $return['type'];
// If a lang[type][msg] string exists, use it as message
if (is_string($lang[$return['type']][$return['msg']])) {
if (isset($return['type']) && isset($return['msg']) && !is_array($return['msg'])) {
if (isset($lang[$return['type']][$return['msg']])) {
$msg = $lang[$return['type']][$return['msg']];
}
}
// If msg is an array, use first element as language string and run printf on it with remaining array elements
elseif (is_array($return['msg'])) {
$msg = array_shift($return['msg']);
@ -1445,6 +1453,7 @@ function get_tfa($username = null) {
$stmt->execute(array(':username' => $username));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (isset($row["authmech"])) {
switch ($row["authmech"]) {
case "yubi_otp":
$data['name'] = "yubi_otp";
@ -1496,6 +1505,12 @@ function get_tfa($username = null) {
return $data;
break;
}
}
else {
$data['name'] = 'none';
$data['pretty'] = "-";
return $data;
}
}
function verify_tfa_login($username, $token) {
global $pdo;
@ -1651,7 +1666,10 @@ function admin_api($access, $action, $data = null) {
if ($action == "edit") {
$active = (!empty($data['active'])) ? 1 : 0;
$skip_ip_check = (isset($data['skip_ip_check'])) ? 1 : 0;
$allow_from = array();
if (isset($data['allow_from'])) {
$allow_from = array_map('trim', preg_split( "/( |,|;|\n)/", $data['allow_from']));
}
foreach ($allow_from as $key => $val) {
if (empty($val)) {
unset($allow_from[$key]);
@ -1738,7 +1756,9 @@ function admin_api($access, $action, $data = null) {
elseif ($action == "get") {
$stmt = $pdo->query("SELECT * FROM `api` WHERE `access` = '" . $access . "'");
$apidata = $stmt->fetch(PDO::FETCH_ASSOC);
if ($apidata !== false) {
$apidata['allow_from'] = str_replace(',', PHP_EOL, $apidata['allow_from']);
}
return $apidata;
}
$_SESSION['return'][] = array(

View File

@ -110,7 +110,7 @@
<?php foreach ($MAILCOW_APPS as $app) {
if (getenv('SKIP_SOGO') == "y" && preg_match('/^\/SOGo/i', $app['link'])) { continue; }
?>
<li title="<?= htmlspecialchars($app['description']); ?>"><a href="<?= htmlspecialchars($app['link']); ?>"><?= htmlspecialchars($app['name']); ?></a></li>
<li title="<?=(isset($app['description'])) ? htmlspecialchars($app['description']) : '';?>"><a href="<?=(isset($app['link'])) ? htmlspecialchars($app['link']) : '';?>"><?=(isset($app['name'])) ? htmlspecialchars($app['name']) : '';?></a></li>
<?php
}
$app_links = customize('get', 'app_links');

View File

@ -3,7 +3,7 @@
"robthree/twofactorauth": "^1.6",
"yubico/u2flib-server": "^1.0",
"phpmailer/phpmailer": "^6.1",
"php-mime-mail-parser/php-mime-mail-parser": "^5.0.5",
"php-mime-mail-parser/php-mime-mail-parser": "^7",
"soundasleep/html2text": "^0.5.0",
"ddeboer/imap": "^1.5",
"matthiasmullie/minify": "^1.3",

View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ffadb60e56b9e032d9a1777a5bf26477",
"content-hash": "50acd623ff29bb513cd29819f4537aa0",
"packages": [
{
"name": "bshaffer/oauth2-server-php",
@ -144,16 +144,16 @@
},
{
"name": "directorytree/ldaprecord",
"version": "v2.5.0",
"version": "v2.6.3",
"source": {
"type": "git",
"url": "https://github.com/DirectoryTree/LdapRecord.git",
"reference": "ff7a92615fdc3f8b7f3d347c2847ce7ce06db287"
"reference": "5c93ec6d1ef458290825a8b0a148946dce7c1e7a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/ff7a92615fdc3f8b7f3d347c2847ce7ce06db287",
"reference": "ff7a92615fdc3f8b7f3d347c2847ce7ce06db287",
"url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/5c93ec6d1ef458290825a8b0a148946dce7c1e7a",
"reference": "5c93ec6d1ef458290825a8b0a148946dce7c1e7a",
"shasum": ""
},
"require": {
@ -213,20 +213,20 @@
"type": "github"
}
],
"time": "2021-06-06T18:51:41+00:00"
"time": "2021-08-05T21:52:43+00:00"
},
{
"name": "illuminate/contracts",
"version": "v8.48.0",
"version": "v8.53.1",
"source": {
"type": "git",
"url": "https://github.com/illuminate/contracts.git",
"reference": "199fcedc161ba4a0b83feaddc4629f395dbf1641"
"reference": "504a34286a1b4c5421c43087d6bd4e176138f6fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/199fcedc161ba4a0b83feaddc4629f395dbf1641",
"reference": "199fcedc161ba4a0b83feaddc4629f395dbf1641",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/504a34286a1b4c5421c43087d6bd4e176138f6fb",
"reference": "504a34286a1b4c5421c43087d6bd4e176138f6fb",
"shasum": ""
},
"require": {
@ -261,7 +261,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-06-01T14:53:38+00:00"
"time": "2021-08-03T14:03:47+00:00"
},
{
"name": "matthiasmullie/minify",
@ -446,22 +446,23 @@
},
{
"name": "nesbot/carbon",
"version": "2.49.0",
"version": "2.51.1",
"source": {
"type": "git",
"url": "https://github.com/briannesbitt/Carbon.git",
"reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee"
"reference": "8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/93d9db91c0235c486875d22f1e08b50bdf3e6eee",
"reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922",
"reference": "8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^7.1.8 || ^8.0",
"symfony/polyfill-mbstring": "^1.0",
"symfony/polyfill-php80": "^1.16",
"symfony/translation": "^3.4 || ^4.0 || ^5.0"
},
"require-dev": {
@ -480,8 +481,8 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev",
"dev-3.x": "3.x-dev"
"dev-3.x": "3.x-dev",
"dev-master": "2.x-dev"
},
"laravel": {
"providers": [
@ -507,15 +508,15 @@
{
"name": "Brian Nesbitt",
"email": "brian@nesbot.com",
"homepage": "http://nesbot.com"
"homepage": "https://markido.com"
},
{
"name": "kylekatarnls",
"homepage": "http://github.com/kylekatarnls"
"homepage": "https://github.com/kylekatarnls"
}
],
"description": "An API extension for DateTime that supports 281 different languages.",
"homepage": "http://carbon.nesbot.com",
"homepage": "https://carbon.nesbot.com",
"keywords": [
"date",
"datetime",
@ -535,7 +536,7 @@
"type": "tidelift"
}
],
"time": "2021-06-02T07:31:40+00:00"
"time": "2021-07-28T13:16:28+00:00"
},
{
"name": "paragonie/random_compat",
@ -589,31 +590,30 @@
},
{
"name": "php-mime-mail-parser/php-mime-mail-parser",
"version": "5.0.5",
"version": "7.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-mime-mail-parser/php-mime-mail-parser.git",
"reference": "27983433aabeccee832573c3c56e6a4855e57745"
"reference": "9d09a017f3f103fec8456211a4a538b80e0eca0d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-mime-mail-parser/php-mime-mail-parser/zipball/27983433aabeccee832573c3c56e6a4855e57745",
"reference": "27983433aabeccee832573c3c56e6a4855e57745",
"url": "https://api.github.com/repos/php-mime-mail-parser/php-mime-mail-parser/zipball/9d09a017f3f103fec8456211a4a538b80e0eca0d",
"reference": "9d09a017f3f103fec8456211a4a538b80e0eca0d",
"shasum": ""
},
"require": {
"ext-mailparse": "*",
"php": "^7.1"
"php": "^7.2|^8.0"
},
"replace": {
"exorus/php-mime-mail-parser": "*",
"messaged/php-mime-mail-parser": "*"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.1",
"phpunit/php-token-stream": "^3.0",
"phpunit/phpunit": "^7.0",
"squizlabs/php_codesniffer": "^3.4"
"php-coveralls/php-coveralls": "^2.2",
"phpunit/phpunit": "^8.0",
"squizlabs/php_codesniffer": "^3.5"
},
"type": "library",
"autoload": {
@ -657,7 +657,7 @@
"role": "Developer"
}
],
"description": "A fully tested email parser for PHP 7.1+ (mailparse extension wrapper).",
"description": "A fully tested email parser for PHP 7.2+ (mailparse extension wrapper).",
"homepage": "https://github.com/php-mime-mail-parser/php-mime-mail-parser",
"keywords": [
"MimeMailParser",
@ -669,9 +669,15 @@
],
"support": {
"issues": "https://github.com/php-mime-mail-parser/php-mime-mail-parser/issues",
"source": "https://github.com/php-mime-mail-parser/php-mime-mail-parser/tree/master"
"source": "https://github.com/php-mime-mail-parser/php-mime-mail-parser/tree/7.0.0"
},
"time": "2019-09-23T11:57:58+00:00"
"funding": [
{
"url": "https://github.com/eXorus",
"type": "github"
}
],
"time": "2021-02-25T17:21:57+00:00"
},
{
"name": "phpmailer/phpmailer",
@ -1092,16 +1098,16 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.23.0",
"version": "v1.23.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1"
"reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
"reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6",
"reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6",
"shasum": ""
},
"require": {
@ -1152,7 +1158,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1"
},
"funding": [
{
@ -1168,20 +1174,20 @@
"type": "tidelift"
}
],
"time": "2021-05-27T09:27:20+00:00"
"time": "2021-05-27T12:26:48+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.23.0",
"version": "v1.23.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0"
"reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0",
"reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be",
"reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be",
"shasum": ""
},
"require": {
@ -1235,7 +1241,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1"
},
"funding": [
{
@ -1251,27 +1257,27 @@
"type": "tidelift"
}
],
"time": "2021-02-19T12:13:01+00:00"
"time": "2021-07-28T13:41:28+00:00"
},
{
"name": "symfony/translation",
"version": "v5.3.2",
"version": "v5.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "7e2603bcc598e14804c4d2359d8dc4ee3c40391b"
"reference": "d89ad7292932c2699cbe4af98d72c5c6bbc504c1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/7e2603bcc598e14804c4d2359d8dc4ee3c40391b",
"reference": "7e2603bcc598e14804c4d2359d8dc4ee3c40391b",
"url": "https://api.github.com/repos/symfony/translation/zipball/d89ad7292932c2699cbe4af98d72c5c6bbc504c1",
"reference": "d89ad7292932c2699cbe4af98d72c5c6bbc504c1",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php80": "^1.15",
"symfony/polyfill-php80": "^1.16",
"symfony/translation-contracts": "^2.3"
},
"conflict": {
@ -1285,7 +1291,7 @@
"symfony/translation-implementation": "2.3"
},
"require-dev": {
"psr/log": "~1.0",
"psr/log": "^1|^2|^3",
"symfony/config": "^4.4|^5.0",
"symfony/console": "^4.4|^5.0",
"symfony/dependency-injection": "^5.0",
@ -1330,7 +1336,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/translation/tree/v5.3.2"
"source": "https://github.com/symfony/translation/tree/v5.3.4"
},
"funding": [
{
@ -1346,7 +1352,7 @@
"type": "tidelift"
}
],
"time": "2021-06-06T09:51:56+00:00"
"time": "2021-07-25T09:39:16+00:00"
},
{
"name": "symfony/translation-contracts",
@ -1428,22 +1434,22 @@
},
{
"name": "symfony/var-dumper",
"version": "v5.3.2",
"version": "v5.3.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "905a22c68b292ffb6f20d7636c36b220d1fba5ae"
"reference": "3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/905a22c68b292ffb6f20d7636c36b220d1fba5ae",
"reference": "905a22c68b292ffb6f20d7636c36b220d1fba5ae",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0",
"reference": "3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php80": "^1.15"
"symfony/polyfill-php80": "^1.16"
},
"conflict": {
"phpunit/phpunit": "<5.4.3",
@ -1496,7 +1502,7 @@
"dump"
],
"support": {
"source": "https://github.com/symfony/var-dumper/tree/v5.3.2"
"source": "https://github.com/symfony/var-dumper/tree/v5.3.6"
},
"funding": [
{
@ -1512,7 +1518,7 @@
"type": "tidelift"
}
],
"time": "2021-06-06T09:51:56+00:00"
"time": "2021-07-27T01:56:02+00:00"
},
{
"name": "tightenco/collect",
@ -1618,5 +1624,5 @@
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.0.0"
"plugin-api-version": "2.1.0"
}

View File

@ -338,7 +338,7 @@ class ClassLoader
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return bool|null True if loaded, null otherwise
* @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
@ -347,6 +347,8 @@ class ClassLoader
return true;
}
return null;
}
/**

View File

@ -1,536 +1,337 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer;
use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
/**
* This class is copied in every Composer installed project and available to all
*
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
*
* To require it's presence, you can require `composer-runtime-api ^2.0`
*/
class InstalledVersions
{
private static $installed = array (
'root' =>
array (
'pretty_version' => '1.0.0+no-version-set',
'version' => '1.0.0.0',
'aliases' =>
array (
),
'reference' => NULL,
'name' => '__root__',
),
'versions' =>
array (
'__root__' =>
array (
'pretty_version' => '1.0.0+no-version-set',
'version' => '1.0.0.0',
'aliases' =>
array (
),
'reference' => NULL,
),
'bshaffer/oauth2-server-php' =>
array (
'pretty_version' => 'v1.11.1',
'version' => '1.11.1.0',
'aliases' =>
array (
),
'reference' => '5a0c8000d4763b276919e2106f54eddda6bc50fa',
),
'ddeboer/imap' =>
array (
'pretty_version' => '1.12.1',
'version' => '1.12.1.0',
'aliases' =>
array (
),
'reference' => 'dbed05ca67b93509345a820b2859de10c48948fb',
),
'directorytree/ldaprecord' =>
array (
'pretty_version' => 'v2.5.0',
'version' => '2.5.0.0',
'aliases' =>
array (
),
'reference' => 'ff7a92615fdc3f8b7f3d347c2847ce7ce06db287',
),
'exorus/php-mime-mail-parser' =>
array (
'replaced' =>
array (
0 => '*',
),
),
'illuminate/contracts' =>
array (
'pretty_version' => 'v8.48.0',
'version' => '8.48.0.0',
'aliases' =>
array (
),
'reference' => '199fcedc161ba4a0b83feaddc4629f395dbf1641',
),
'matthiasmullie/minify' =>
array (
'pretty_version' => '1.3.66',
'version' => '1.3.66.0',
'aliases' =>
array (
),
'reference' => '45fd3b0f1dfa2c965857c6d4a470bea52adc31a6',
),
'matthiasmullie/path-converter' =>
array (
'pretty_version' => '1.1.3',
'version' => '1.1.3.0',
'aliases' =>
array (
),
'reference' => 'e7d13b2c7e2f2268e1424aaed02085518afa02d9',
),
'messaged/php-mime-mail-parser' =>
array (
'replaced' =>
array (
0 => '*',
),
),
'mustangostang/spyc' =>
array (
'pretty_version' => '0.6.3',
'version' => '0.6.3.0',
'aliases' =>
array (
),
'reference' => '4627c838b16550b666d15aeae1e5289dd5b77da0',
),
'nesbot/carbon' =>
array (
'pretty_version' => '2.49.0',
'version' => '2.49.0.0',
'aliases' =>
array (
),
'reference' => '93d9db91c0235c486875d22f1e08b50bdf3e6eee',
),
'paragonie/random_compat' =>
array (
'pretty_version' => 'v9.99.100',
'version' => '9.99.100.0',
'aliases' =>
array (
),
'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
),
'php-mime-mail-parser/php-mime-mail-parser' =>
array (
'pretty_version' => '5.0.5',
'version' => '5.0.5.0',
'aliases' =>
array (
),
'reference' => '27983433aabeccee832573c3c56e6a4855e57745',
),
'phpmailer/phpmailer' =>
array (
'pretty_version' => 'v6.5.0',
'version' => '6.5.0.0',
'aliases' =>
array (
),
'reference' => 'a5b5c43e50b7fba655f793ad27303cd74c57363c',
),
'psr/container' =>
array (
'pretty_version' => '1.1.1',
'version' => '1.1.1.0',
'aliases' =>
array (
),
'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf',
),
'psr/log' =>
array (
'pretty_version' => '1.1.4',
'version' => '1.1.4.0',
'aliases' =>
array (
),
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
),
'psr/simple-cache' =>
array (
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
),
'robthree/twofactorauth' =>
array (
'pretty_version' => '1.8.0',
'version' => '1.8.0.0',
'aliases' =>
array (
),
'reference' => '30a38627ae1e7c9399dae67e265063cd6ec5276c',
),
'soundasleep/html2text' =>
array (
'pretty_version' => '0.5.0',
'version' => '0.5.0.0',
'aliases' =>
array (
),
'reference' => 'cdb89f6ffa2c4cc78f8ed9ea6ee0594a9133ccad',
),
'symfony/deprecation-contracts' =>
array (
'pretty_version' => 'v2.4.0',
'version' => '2.4.0.0',
'aliases' =>
array (
),
'reference' => '5f38c8804a9e97d23e0c8d63341088cd8a22d627',
),
'symfony/polyfill-mbstring' =>
array (
'pretty_version' => 'v1.23.0',
'version' => '1.23.0.0',
'aliases' =>
array (
),
'reference' => '2df51500adbaebdc4c38dea4c89a2e131c45c8a1',
),
'symfony/polyfill-php80' =>
array (
'pretty_version' => 'v1.23.0',
'version' => '1.23.0.0',
'aliases' =>
array (
),
'reference' => 'eca0bf41ed421bed1b57c4958bab16aa86b757d0',
),
'symfony/translation' =>
array (
'pretty_version' => 'v5.3.2',
'version' => '5.3.2.0',
'aliases' =>
array (
),
'reference' => '7e2603bcc598e14804c4d2359d8dc4ee3c40391b',
),
'symfony/translation-contracts' =>
array (
'pretty_version' => 'v2.4.0',
'version' => '2.4.0.0',
'aliases' =>
array (
),
'reference' => '95c812666f3e91db75385749fe219c5e494c7f95',
),
'symfony/translation-implementation' =>
array (
'provided' =>
array (
0 => '2.3',
),
),
'symfony/var-dumper' =>
array (
'pretty_version' => 'v5.3.2',
'version' => '5.3.2.0',
'aliases' =>
array (
),
'reference' => '905a22c68b292ffb6f20d7636c36b220d1fba5ae',
),
'tightenco/collect' =>
array (
'pretty_version' => 'v8.34.0',
'version' => '8.34.0.0',
'aliases' =>
array (
),
'reference' => 'b069783ab0c547bb894ebcf8e7f6024bb401f9d2',
),
'yubico/u2flib-server' =>
array (
'pretty_version' => '1.0.2',
'version' => '1.0.2.0',
'aliases' =>
array (
),
'reference' => '55d813acf68212ad2cadecde07551600d6971939',
),
),
);
private static $canGetVendors;
private static $installedByVendor = array();
private static $installed;
private static $canGetVendors;
private static $installedByVendor = array();
/**
* Returns a list of all package names which are present, either by being installed, replaced or provided
*
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackages()
{
$packages = array();
foreach (self::getInstalled() as $installed) {
$packages[] = array_keys($installed['versions']);
}
if (1 === \count($packages)) {
return $packages[0];
}
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
}
/**
* Returns a list of all package names with a specific type e.g. 'library'
*
* @param string $type
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackagesByType($type)
{
$packagesByType = array();
foreach (self::getInstalled() as $installed) {
foreach ($installed['versions'] as $name => $package) {
if (isset($package['type']) && $package['type'] === $type) {
$packagesByType[] = $name;
}
}
}
return $packagesByType;
}
public static function getInstalledPackages()
{
$packages = array();
foreach (self::getInstalled() as $installed) {
$packages[] = array_keys($installed['versions']);
}
if (1 === \count($packages)) {
return $packages[0];
}
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
}
public static function isInstalled($packageName)
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return true;
}
}
return false;
}
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints($constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
}
public static function getVersionRanges($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
$ranges = array();
if (isset($installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
}
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
}
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
}
if (array_key_exists('provided', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
}
return implode(' || ', $ranges);
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
public static function getVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['version'])) {
return null;
}
return $installed['versions'][$packageName]['version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
public static function getPrettyVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
return null;
}
return $installed['versions'][$packageName]['pretty_version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
public static function getReference($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['reference'])) {
return null;
}
return $installed['versions'][$packageName]['reference'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
public static function getRootPackage()
{
$installed = self::getInstalled();
return $installed[0]['root'];
}
public static function getRawData()
{
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
return self::$installed;
}
public static function getAllRawData()
{
return self::getInstalled();
}
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
private static function getInstalled()
{
if (null === self::$canGetVendors) {
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
}
$installed = array();
if (self::$canGetVendors) {
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
}
}
}
$installed[] = self::$installed;
return $installed;
}
/**
* Checks whether the given package is installed
*
* This also returns true if the package name is provided or replaced by another package
*
* @param string $packageName
* @param bool $includeDevRequirements
* @return bool
*/
public static function isInstalled($packageName, $includeDevRequirements = true)
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
}
}
return false;
}
/**
* Checks whether the given package satisfies a version constraint
*
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
*
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
*
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
* @param string $packageName
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
* @return bool
*/
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints($constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
}
/**
* Returns a version constraint representing all the range(s) which are installed for a given package
*
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
* whether a given version of a package is installed, and not just whether it exists
*
* @param string $packageName
* @return string Version constraint usable with composer/semver
*/
public static function getVersionRanges($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
$ranges = array();
if (isset($installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
}
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
}
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
}
if (array_key_exists('provided', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
}
return implode(' || ', $ranges);
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['version'])) {
return null;
}
return $installed['versions'][$packageName]['version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getPrettyVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
return null;
}
return $installed['versions'][$packageName]['pretty_version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
*/
public static function getReference($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['reference'])) {
return null;
}
return $installed['versions'][$packageName]['reference'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
*/
public static function getInstallPath($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @return array
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}
*/
public static function getRootPackage()
{
$installed = self::getInstalled();
return $installed[0]['root'];
}
/**
* Returns the raw installed.php data for custom implementations
*
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
* @return array[]
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}
*/
public static function getRawData()
{
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = include __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
return self::$installed;
}
/**
* Returns the raw data of all installed.php which are currently loaded for custom implementations
*
* @return array[]
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}>
*/
public static function getAllRawData()
{
return self::getInstalled();
}
/**
* Lets you reload the static array from another file
*
* This is only useful for complex integrations in which a project needs to use
* this class but then also needs to execute another project's autoloader in process,
* and wants to ensure both projects have access to their version of installed.php.
*
* A typical case would be PHPUnit, where it would need to make sure it reads all
* the data it needs from this class, then call reload() with
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
* the project in which it runs can then also use this class safely, without
* interference between PHPUnit's dependencies and the project's dependencies.
*
* @param array[] $data A vendor/composer/installed.php data set
* @return void
*
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>} $data
*/
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}>
*/
private static function getInstalled()
{
if (null === self::$canGetVendors) {
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
}
$installed = array();
if (self::$canGetVendors) {
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $installed[count($installed) - 1];
}
}
}
}
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = require __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
$installed[] = self::$installed;
return $installed;
}
}

View File

@ -6,8 +6,8 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',

View File

@ -7,8 +7,8 @@ namespace Composer\Autoload;
class ComposerStaticInit873464e4bd965a3168f133248b1b218b
{
public static $files = array (
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',

View File

@ -140,17 +140,17 @@
},
{
"name": "directorytree/ldaprecord",
"version": "v2.5.0",
"version_normalized": "2.5.0.0",
"version": "v2.6.3",
"version_normalized": "2.6.3.0",
"source": {
"type": "git",
"url": "https://github.com/DirectoryTree/LdapRecord.git",
"reference": "ff7a92615fdc3f8b7f3d347c2847ce7ce06db287"
"reference": "5c93ec6d1ef458290825a8b0a148946dce7c1e7a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/ff7a92615fdc3f8b7f3d347c2847ce7ce06db287",
"reference": "ff7a92615fdc3f8b7f3d347c2847ce7ce06db287",
"url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/5c93ec6d1ef458290825a8b0a148946dce7c1e7a",
"reference": "5c93ec6d1ef458290825a8b0a148946dce7c1e7a",
"shasum": ""
},
"require": {
@ -168,7 +168,7 @@
"phpunit/phpunit": "^8.0",
"spatie/ray": "^1.24"
},
"time": "2021-06-06T18:51:41+00:00",
"time": "2021-08-05T21:52:43+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -216,17 +216,17 @@
},
{
"name": "illuminate/contracts",
"version": "v8.48.0",
"version_normalized": "8.48.0.0",
"version": "v8.53.1",
"version_normalized": "8.53.1.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/contracts.git",
"reference": "199fcedc161ba4a0b83feaddc4629f395dbf1641"
"reference": "504a34286a1b4c5421c43087d6bd4e176138f6fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/199fcedc161ba4a0b83feaddc4629f395dbf1641",
"reference": "199fcedc161ba4a0b83feaddc4629f395dbf1641",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/504a34286a1b4c5421c43087d6bd4e176138f6fb",
"reference": "504a34286a1b4c5421c43087d6bd4e176138f6fb",
"shasum": ""
},
"require": {
@ -234,7 +234,7 @@
"psr/container": "^1.0",
"psr/simple-cache": "^1.0"
},
"time": "2021-06-01T14:53:38+00:00",
"time": "2021-08-03T14:03:47+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -453,23 +453,24 @@
},
{
"name": "nesbot/carbon",
"version": "2.49.0",
"version_normalized": "2.49.0.0",
"version": "2.51.1",
"version_normalized": "2.51.1.0",
"source": {
"type": "git",
"url": "https://github.com/briannesbitt/Carbon.git",
"reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee"
"reference": "8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/93d9db91c0235c486875d22f1e08b50bdf3e6eee",
"reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922",
"reference": "8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^7.1.8 || ^8.0",
"symfony/polyfill-mbstring": "^1.0",
"symfony/polyfill-php80": "^1.16",
"symfony/translation": "^3.4 || ^4.0 || ^5.0"
},
"require-dev": {
@ -482,15 +483,15 @@
"phpunit/phpunit": "^7.5.20 || ^8.5.14",
"squizlabs/php_codesniffer": "^3.4"
},
"time": "2021-06-02T07:31:40+00:00",
"time": "2021-07-28T13:16:28+00:00",
"bin": [
"bin/carbon"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev",
"dev-3.x": "3.x-dev"
"dev-3.x": "3.x-dev",
"dev-master": "2.x-dev"
},
"laravel": {
"providers": [
@ -517,15 +518,15 @@
{
"name": "Brian Nesbitt",
"email": "brian@nesbot.com",
"homepage": "http://nesbot.com"
"homepage": "https://markido.com"
},
{
"name": "kylekatarnls",
"homepage": "http://github.com/kylekatarnls"
"homepage": "https://github.com/kylekatarnls"
}
],
"description": "An API extension for DateTime that supports 281 different languages.",
"homepage": "http://carbon.nesbot.com",
"homepage": "https://carbon.nesbot.com",
"keywords": [
"date",
"datetime",
@ -602,34 +603,33 @@
},
{
"name": "php-mime-mail-parser/php-mime-mail-parser",
"version": "5.0.5",
"version_normalized": "5.0.5.0",
"version": "7.0.0",
"version_normalized": "7.0.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-mime-mail-parser/php-mime-mail-parser.git",
"reference": "27983433aabeccee832573c3c56e6a4855e57745"
"reference": "9d09a017f3f103fec8456211a4a538b80e0eca0d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-mime-mail-parser/php-mime-mail-parser/zipball/27983433aabeccee832573c3c56e6a4855e57745",
"reference": "27983433aabeccee832573c3c56e6a4855e57745",
"url": "https://api.github.com/repos/php-mime-mail-parser/php-mime-mail-parser/zipball/9d09a017f3f103fec8456211a4a538b80e0eca0d",
"reference": "9d09a017f3f103fec8456211a4a538b80e0eca0d",
"shasum": ""
},
"require": {
"ext-mailparse": "*",
"php": "^7.1"
"php": "^7.2|^8.0"
},
"replace": {
"exorus/php-mime-mail-parser": "*",
"messaged/php-mime-mail-parser": "*"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.1",
"phpunit/php-token-stream": "^3.0",
"phpunit/phpunit": "^7.0",
"squizlabs/php_codesniffer": "^3.4"
"php-coveralls/php-coveralls": "^2.2",
"phpunit/phpunit": "^8.0",
"squizlabs/php_codesniffer": "^3.5"
},
"time": "2019-09-23T11:57:58+00:00",
"time": "2021-02-25T17:21:57+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -673,7 +673,7 @@
"role": "Developer"
}
],
"description": "A fully tested email parser for PHP 7.1+ (mailparse extension wrapper).",
"description": "A fully tested email parser for PHP 7.2+ (mailparse extension wrapper).",
"homepage": "https://github.com/php-mime-mail-parser/php-mime-mail-parser",
"keywords": [
"MimeMailParser",
@ -683,6 +683,16 @@
"parser",
"php"
],
"support": {
"issues": "https://github.com/php-mime-mail-parser/php-mime-mail-parser/issues",
"source": "https://github.com/php-mime-mail-parser/php-mime-mail-parser/tree/7.0.0"
},
"funding": [
{
"url": "https://github.com/eXorus",
"type": "github"
}
],
"install-path": "../php-mime-mail-parser/php-mime-mail-parser"
},
{
@ -1120,17 +1130,17 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.23.0",
"version_normalized": "1.23.0.0",
"version": "v1.23.1",
"version_normalized": "1.23.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1"
"reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
"reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6",
"reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6",
"shasum": ""
},
"require": {
@ -1139,7 +1149,7 @@
"suggest": {
"ext-mbstring": "For best performance"
},
"time": "2021-05-27T09:27:20+00:00",
"time": "2021-05-27T12:26:48+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -1183,7 +1193,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1"
},
"funding": [
{
@ -1203,23 +1213,23 @@
},
{
"name": "symfony/polyfill-php80",
"version": "v1.23.0",
"version_normalized": "1.23.0.0",
"version": "v1.23.1",
"version_normalized": "1.23.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0"
"reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0",
"reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be",
"reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"time": "2021-02-19T12:13:01+00:00",
"time": "2021-07-28T13:41:28+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -1269,7 +1279,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1"
},
"funding": [
{
@ -1289,24 +1299,24 @@
},
{
"name": "symfony/translation",
"version": "v5.3.2",
"version_normalized": "5.3.2.0",
"version": "v5.3.4",
"version_normalized": "5.3.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "7e2603bcc598e14804c4d2359d8dc4ee3c40391b"
"reference": "d89ad7292932c2699cbe4af98d72c5c6bbc504c1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/7e2603bcc598e14804c4d2359d8dc4ee3c40391b",
"reference": "7e2603bcc598e14804c4d2359d8dc4ee3c40391b",
"url": "https://api.github.com/repos/symfony/translation/zipball/d89ad7292932c2699cbe4af98d72c5c6bbc504c1",
"reference": "d89ad7292932c2699cbe4af98d72c5c6bbc504c1",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php80": "^1.15",
"symfony/polyfill-php80": "^1.16",
"symfony/translation-contracts": "^2.3"
},
"conflict": {
@ -1320,7 +1330,7 @@
"symfony/translation-implementation": "2.3"
},
"require-dev": {
"psr/log": "~1.0",
"psr/log": "^1|^2|^3",
"symfony/config": "^4.4|^5.0",
"symfony/console": "^4.4|^5.0",
"symfony/dependency-injection": "^5.0",
@ -1336,7 +1346,7 @@
"symfony/config": "",
"symfony/yaml": ""
},
"time": "2021-06-06T09:51:56+00:00",
"time": "2021-07-25T09:39:16+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -1367,7 +1377,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/translation/tree/v5.3.2"
"source": "https://github.com/symfony/translation/tree/v5.3.4"
},
"funding": [
{
@ -1468,23 +1478,23 @@
},
{
"name": "symfony/var-dumper",
"version": "v5.3.2",
"version_normalized": "5.3.2.0",
"version": "v5.3.6",
"version_normalized": "5.3.6.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "905a22c68b292ffb6f20d7636c36b220d1fba5ae"
"reference": "3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/905a22c68b292ffb6f20d7636c36b220d1fba5ae",
"reference": "905a22c68b292ffb6f20d7636c36b220d1fba5ae",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0",
"reference": "3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php80": "^1.15"
"symfony/polyfill-php80": "^1.16"
},
"conflict": {
"phpunit/phpunit": "<5.4.3",
@ -1501,7 +1511,7 @@
"ext-intl": "To show region name in time zone dump",
"symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script"
},
"time": "2021-06-06T09:51:56+00:00",
"time": "2021-07-27T01:56:02+00:00",
"bin": [
"Resources/bin/var-dump-server"
],
@ -1539,7 +1549,7 @@
"dump"
],
"support": {
"source": "https://github.com/symfony/var-dumper/tree/v5.3.2"
"source": "https://github.com/symfony/var-dumper/tree/v5.3.6"
},
"funding": [
{

View File

@ -1,261 +1,257 @@
<?php return array (
'root' =>
array (
<?php return array(
'root' => array(
'pretty_version' => '1.0.0+no-version-set',
'version' => '1.0.0.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => NULL,
'name' => '__root__',
'dev' => true,
),
'versions' =>
array (
'__root__' =>
array (
'versions' => array(
'__root__' => array(
'pretty_version' => '1.0.0+no-version-set',
'version' => '1.0.0.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => NULL,
'dev_requirement' => false,
),
'bshaffer/oauth2-server-php' =>
array (
'bshaffer/oauth2-server-php' => array(
'pretty_version' => 'v1.11.1',
'version' => '1.11.1.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../bshaffer/oauth2-server-php',
'aliases' => array(),
'reference' => '5a0c8000d4763b276919e2106f54eddda6bc50fa',
'dev_requirement' => false,
),
'ddeboer/imap' =>
array (
'ddeboer/imap' => array(
'pretty_version' => '1.12.1',
'version' => '1.12.1.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../ddeboer/imap',
'aliases' => array(),
'reference' => 'dbed05ca67b93509345a820b2859de10c48948fb',
'dev_requirement' => false,
),
'directorytree/ldaprecord' =>
array (
'pretty_version' => 'v2.5.0',
'version' => '2.5.0.0',
'aliases' =>
array (
'directorytree/ldaprecord' => array(
'pretty_version' => 'v2.6.3',
'version' => '2.6.3.0',
'type' => 'library',
'install_path' => __DIR__ . '/../directorytree/ldaprecord',
'aliases' => array(),
'reference' => '5c93ec6d1ef458290825a8b0a148946dce7c1e7a',
'dev_requirement' => false,
),
'reference' => 'ff7a92615fdc3f8b7f3d347c2847ce7ce06db287',
),
'exorus/php-mime-mail-parser' =>
array (
'replaced' =>
array (
'exorus/php-mime-mail-parser' => array(
'dev_requirement' => false,
'replaced' => array(
0 => '*',
),
),
'illuminate/contracts' =>
array (
'pretty_version' => 'v8.48.0',
'version' => '8.48.0.0',
'aliases' =>
array (
'illuminate/contracts' => array(
'pretty_version' => 'v8.53.1',
'version' => '8.53.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../illuminate/contracts',
'aliases' => array(),
'reference' => '504a34286a1b4c5421c43087d6bd4e176138f6fb',
'dev_requirement' => false,
),
'reference' => '199fcedc161ba4a0b83feaddc4629f395dbf1641',
),
'matthiasmullie/minify' =>
array (
'matthiasmullie/minify' => array(
'pretty_version' => '1.3.66',
'version' => '1.3.66.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../matthiasmullie/minify',
'aliases' => array(),
'reference' => '45fd3b0f1dfa2c965857c6d4a470bea52adc31a6',
'dev_requirement' => false,
),
'matthiasmullie/path-converter' =>
array (
'matthiasmullie/path-converter' => array(
'pretty_version' => '1.1.3',
'version' => '1.1.3.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../matthiasmullie/path-converter',
'aliases' => array(),
'reference' => 'e7d13b2c7e2f2268e1424aaed02085518afa02d9',
'dev_requirement' => false,
),
'messaged/php-mime-mail-parser' =>
array (
'replaced' =>
array (
'messaged/php-mime-mail-parser' => array(
'dev_requirement' => false,
'replaced' => array(
0 => '*',
),
),
'mustangostang/spyc' =>
array (
'mustangostang/spyc' => array(
'pretty_version' => '0.6.3',
'version' => '0.6.3.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../mustangostang/spyc',
'aliases' => array(),
'reference' => '4627c838b16550b666d15aeae1e5289dd5b77da0',
'dev_requirement' => false,
),
'nesbot/carbon' =>
array (
'pretty_version' => '2.49.0',
'version' => '2.49.0.0',
'aliases' =>
array (
'nesbot/carbon' => array(
'pretty_version' => '2.51.1',
'version' => '2.51.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../nesbot/carbon',
'aliases' => array(),
'reference' => '8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922',
'dev_requirement' => false,
),
'reference' => '93d9db91c0235c486875d22f1e08b50bdf3e6eee',
),
'paragonie/random_compat' =>
array (
'paragonie/random_compat' => array(
'pretty_version' => 'v9.99.100',
'version' => '9.99.100.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../paragonie/random_compat',
'aliases' => array(),
'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
'dev_requirement' => false,
),
'php-mime-mail-parser/php-mime-mail-parser' =>
array (
'pretty_version' => '5.0.5',
'version' => '5.0.5.0',
'aliases' =>
array (
'php-mime-mail-parser/php-mime-mail-parser' => array(
'pretty_version' => '7.0.0',
'version' => '7.0.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../php-mime-mail-parser/php-mime-mail-parser',
'aliases' => array(),
'reference' => '9d09a017f3f103fec8456211a4a538b80e0eca0d',
'dev_requirement' => false,
),
'reference' => '27983433aabeccee832573c3c56e6a4855e57745',
),
'phpmailer/phpmailer' =>
array (
'phpmailer/phpmailer' => array(
'pretty_version' => 'v6.5.0',
'version' => '6.5.0.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../phpmailer/phpmailer',
'aliases' => array(),
'reference' => 'a5b5c43e50b7fba655f793ad27303cd74c57363c',
'dev_requirement' => false,
),
'psr/container' =>
array (
'psr/container' => array(
'pretty_version' => '1.1.1',
'version' => '1.1.1.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../psr/container',
'aliases' => array(),
'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf',
'dev_requirement' => false,
),
'psr/log' =>
array (
'psr/log' => array(
'pretty_version' => '1.1.4',
'version' => '1.1.4.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../psr/log',
'aliases' => array(),
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
'dev_requirement' => false,
),
'psr/simple-cache' =>
array (
'psr/simple-cache' => array(
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../psr/simple-cache',
'aliases' => array(),
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
'dev_requirement' => false,
),
'robthree/twofactorauth' =>
array (
'robthree/twofactorauth' => array(
'pretty_version' => '1.8.0',
'version' => '1.8.0.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../robthree/twofactorauth',
'aliases' => array(),
'reference' => '30a38627ae1e7c9399dae67e265063cd6ec5276c',
'dev_requirement' => false,
),
'soundasleep/html2text' =>
array (
'soundasleep/html2text' => array(
'pretty_version' => '0.5.0',
'version' => '0.5.0.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../soundasleep/html2text',
'aliases' => array(),
'reference' => 'cdb89f6ffa2c4cc78f8ed9ea6ee0594a9133ccad',
'dev_requirement' => false,
),
'symfony/deprecation-contracts' =>
array (
'symfony/deprecation-contracts' => array(
'pretty_version' => 'v2.4.0',
'version' => '2.4.0.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
'aliases' => array(),
'reference' => '5f38c8804a9e97d23e0c8d63341088cd8a22d627',
'dev_requirement' => false,
),
'symfony/polyfill-mbstring' =>
array (
'pretty_version' => 'v1.23.0',
'version' => '1.23.0.0',
'aliases' =>
array (
'symfony/polyfill-mbstring' => array(
'pretty_version' => 'v1.23.1',
'version' => '1.23.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
'aliases' => array(),
'reference' => '9174a3d80210dca8daa7f31fec659150bbeabfc6',
'dev_requirement' => false,
),
'reference' => '2df51500adbaebdc4c38dea4c89a2e131c45c8a1',
'symfony/polyfill-php80' => array(
'pretty_version' => 'v1.23.1',
'version' => '1.23.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
'aliases' => array(),
'reference' => '1100343ed1a92e3a38f9ae122fc0eb21602547be',
'dev_requirement' => false,
),
'symfony/polyfill-php80' =>
array (
'pretty_version' => 'v1.23.0',
'version' => '1.23.0.0',
'aliases' =>
array (
'symfony/translation' => array(
'pretty_version' => 'v5.3.4',
'version' => '5.3.4.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/translation',
'aliases' => array(),
'reference' => 'd89ad7292932c2699cbe4af98d72c5c6bbc504c1',
'dev_requirement' => false,
),
'reference' => 'eca0bf41ed421bed1b57c4958bab16aa86b757d0',
),
'symfony/translation' =>
array (
'pretty_version' => 'v5.3.2',
'version' => '5.3.2.0',
'aliases' =>
array (
),
'reference' => '7e2603bcc598e14804c4d2359d8dc4ee3c40391b',
),
'symfony/translation-contracts' =>
array (
'symfony/translation-contracts' => array(
'pretty_version' => 'v2.4.0',
'version' => '2.4.0.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/translation-contracts',
'aliases' => array(),
'reference' => '95c812666f3e91db75385749fe219c5e494c7f95',
'dev_requirement' => false,
),
'symfony/translation-implementation' =>
array (
'provided' =>
array (
'symfony/translation-implementation' => array(
'dev_requirement' => false,
'provided' => array(
0 => '2.3',
),
),
'symfony/var-dumper' =>
array (
'pretty_version' => 'v5.3.2',
'version' => '5.3.2.0',
'aliases' =>
array (
'symfony/var-dumper' => array(
'pretty_version' => 'v5.3.6',
'version' => '5.3.6.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/var-dumper',
'aliases' => array(),
'reference' => '3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0',
'dev_requirement' => false,
),
'reference' => '905a22c68b292ffb6f20d7636c36b220d1fba5ae',
),
'tightenco/collect' =>
array (
'tightenco/collect' => array(
'pretty_version' => 'v8.34.0',
'version' => '8.34.0.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../tightenco/collect',
'aliases' => array(),
'reference' => 'b069783ab0c547bb894ebcf8e7f6024bb401f9d2',
'dev_requirement' => false,
),
'yubico/u2flib-server' =>
array (
'yubico/u2flib-server' => array(
'pretty_version' => '1.0.2',
'version' => '1.0.2.0',
'aliases' =>
array (
),
'type' => 'library',
'install_path' => __DIR__ . '/../yubico/u2flib-server',
'aliases' => array(),
'reference' => '55d813acf68212ad2cadecde07551600d6971939',
'dev_requirement' => false,
),
),
);

View File

@ -7,8 +7,9 @@ assignees: ''
---
**Environment (please complete the following information):**
<!-- Please update the below information with your environment. -->
**Environment:**
- LDAP Server Type: [e.g. ActiveDirectory / OpenLDAP / FreeIPA]
- PHP Version: [e.g. 7.2 / 7.3 / 7.4]
- PHP Version: [e.g. 7.3 / 7.4 / 8.0]
**Describe the bug:**

View File

@ -10,3 +10,8 @@ assignees: ''
<!-- ISSUE WILL BE CLOSED WITHOUT SPONSORSHIP: -->
<!-- https://github.com/sponsors/stevebauman -->
<!-- Thank you for your understanding. -->
<!-- Please update the below information with your environment. -->
**Environment:**
- LDAP Server Type: [e.g. ActiveDirectory / OpenLDAP / FreeIPA]
- PHP Version: [e.g. 7.3 / 7.4 / 8.0]

View File

@ -8,13 +8,14 @@ on:
jobs:
run-tests:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
php: [8.0, 7.4, 7.3]
name: P${{ matrix.php }}
name: ${{ matrix.os }} - P${{ matrix.php }}
steps:
- name: Checkout code
@ -34,7 +35,7 @@ jobs:
coverage: none
- name: Install dependencies
run: composer update --prefer-dist --no-interaction --no-suggest
run: composer update --prefer-dist --no-interaction
- name: Execute tests
run: vendor/bin/phpunit

View File

@ -2,19 +2,20 @@
namespace LdapRecord\Configuration\Validators;
use LdapRecord\Configuration\ConfigurationException;
class ArrayValidator extends Validator
{
/**
* The validation exception message.
*
* @var string
*/
protected $message = 'Option [:option] must be an array.';
/**
* @inheritdoc
*/
public function validate()
public function passes()
{
if (! is_array($this->value)) {
throw new ConfigurationException("Option {$this->key} must be an array.");
}
return true;
return is_array($this->value);
}
}

View File

@ -2,19 +2,20 @@
namespace LdapRecord\Configuration\Validators;
use LdapRecord\Configuration\ConfigurationException;
class BooleanValidator extends Validator
{
/**
* The validation exception message.
*
* @var string
*/
protected $message = 'Option [:option] must be a boolean.';
/**
* @inheritdoc
*/
public function validate()
public function passes()
{
if (! is_bool($this->value)) {
throw new ConfigurationException("Option {$this->key} must be a boolean.");
}
return true;
return is_bool($this->value);
}
}

View File

@ -2,19 +2,20 @@
namespace LdapRecord\Configuration\Validators;
use LdapRecord\Configuration\ConfigurationException;
class IntegerValidator extends Validator
{
/**
* The validation exception message.
*
* @var string
*/
protected $message = 'Option [:option] must be an integer.';
/**
* @inheritdoc
*/
public function validate()
public function passes()
{
if (! is_numeric($this->value)) {
throw new ConfigurationException("Option {$this->key} must be an integer.");
}
return true;
return is_numeric($this->value);
}
}

View File

@ -2,19 +2,20 @@
namespace LdapRecord\Configuration\Validators;
use LdapRecord\Configuration\ConfigurationException;
class StringOrNullValidator extends Validator
{
/**
* The validation exception message.
*
* @var string
*/
protected $message = 'Option [:option] must be a string or null.';
/**
* @inheritdoc
*/
public function validate()
public function passes()
{
if (is_string($this->value) || is_null($this->value)) {
return true;
}
throw new ConfigurationException("Option {$this->key} must be a string or null.");
return is_string($this->value) || is_null($this->value);
}
}

View File

@ -2,6 +2,8 @@
namespace LdapRecord\Configuration\Validators;
use LdapRecord\Configuration\ConfigurationException;
abstract class Validator
{
/**
@ -18,6 +20,13 @@ abstract class Validator
*/
protected $value;
/**
* The validation exception message.
*
* @var string
*/
protected $message;
/**
* Constructor.
*
@ -31,11 +40,39 @@ abstract class Validator
}
/**
* Validates the configuration value.
*
* @throws \LdapRecord\Configuration\ConfigurationException When the value given fails validation.
* Determine if the validation rule passes.
*
* @return bool
*/
abstract public function validate();
abstract public function passes();
/**
* Validate the configuration value.
*
* @throws ConfigurationException
*
* @return bool
*/
public function validate()
{
if (! $this->passes()) {
$this->fail();
}
return true;
}
/**
* Throw a configuration exception.
*
* @throws ConfigurationException
*
* @return void
*/
protected function fail()
{
throw new ConfigurationException(
str_replace(':option', $this->key, $this->message)
);
}
}

View File

@ -74,7 +74,7 @@ class Connection
/**
* The authentication guard resolver.
*
* @var \Closure
* @var Closure
*/
protected $authGuardResolver;

View File

@ -0,0 +1,320 @@
<?php
namespace LdapRecord;
use BadMethodCallException;
use LdapRecord\Events\Dispatcher;
use LdapRecord\Events\DispatcherInterface;
use LdapRecord\Events\Logger;
use Psr\Log\LoggerInterface;
class ConnectionManager
{
/**
* The logger instance.
*
* @var LoggerInterface|null
*/
protected $logger;
/**
* The event dispatcher instance.
*
* @var DispatcherInterface|null
*/
protected $dispatcher;
/**
* The added LDAP connections.
*
* @var Connection[]
*/
protected $connections = [];
/**
* The name of the default connection.
*
* @var string
*/
protected $default = 'default';
/**
* The events to register listeners for during initialization.
*
* @var array
*/
protected $listen = [
'LdapRecord\Auth\Events\*',
'LdapRecord\Query\Events\*',
'LdapRecord\Models\Events\*',
];
/**
* The method calls to proxy for compatibility.
*
* To be removed in the next major version.
*
* @var array
*/
protected $proxy = [
'reset' => 'flush',
'addConnection' => 'add',
'getConnection' => 'get',
'allConnections' => 'all',
'removeConnection' => 'remove',
'getDefaultConnection' => 'getDefault',
'setDefaultConnection' => 'setDefault',
'getEventDispatcher' => 'dispatcher',
'setEventDispatcher' => 'setDispatcher',
];
/**
* Constructor.
*
* @return void
*/
public function __construct()
{
$this->dispatcher = new Dispatcher();
}
/**
* Forward missing method calls onto the instance.
*
* @param string $method
* @param mixed $args
*
* @return mixed
*/
public function __call($method, $args)
{
$method = $this->proxy[$method] ?? $method;
if (! method_exists($this, $method)) {
throw new BadMethodCallException(sprintf(
'Call to undefined method %s::%s()',
static::class,
$method
));
}
return $this->{$method}(...$args);
}
/**
* Add a new connection.
*
* @param Connection $connection
* @param string|null $name
*
* @return $this
*/
public function add(Connection $connection, $name = null)
{
$this->connections[$name ?? $this->default] = $connection;
if ($this->dispatcher) {
$connection->setDispatcher($this->dispatcher);
}
return $this;
}
/**
* Remove a connection.
*
* @param $name
*
* @return $this
*/
public function remove($name)
{
unset($this->connections[$name]);
return $this;
}
/**
* Get all of the connections.
*
* @return Connection[]
*/
public function all()
{
return $this->connections;
}
/**
* Get a connection by name or return the default.
*
* @param string|null $name
*
* @throws ContainerException If the given connection does not exist.
*
* @return Connection
*/
public function get($name = null)
{
if ($this->exists($name = $name ?? $this->default)) {
return $this->connections[$name];
}
throw new ContainerException("The LDAP connection [$name] does not exist.");
}
/**
* Return the default connection.
*
* @return Connection
*/
public function getDefault()
{
return $this->get($this->default);
}
/**
* Get the default connection name.
*
* @return string
*/
public function getDefaultConnectionName()
{
return $this->default;
}
/**
* Checks if the connection exists.
*
* @param string $name
*
* @return bool
*/
public function exists($name)
{
return array_key_exists($name, $this->connections);
}
/**
* Set the default connection name.
*
* @param string $name
*
* @return $this
*/
public function setDefault($name = null)
{
$this->default = $name;
return $this;
}
/**
* Flush the manager of all instances and connections.
*
* @return $this
*/
public function flush()
{
$this->logger = null;
$this->connections = [];
$this->dispatcher = new Dispatcher();
return $this;
}
/**
* Get the logger instance.
*
* @return LoggerInterface|null
*/
public function getLogger()
{
return $this->logger;
}
/**
* Set the event logger to use.
*
* @param LoggerInterface $logger
*
* @return void
*/
public function setLogger(LoggerInterface $logger)
{
$this->logger = $logger;
$this->initEventLogger();
}
/**
* Initialize the event logger.
*
* @return void
*/
public function initEventLogger()
{
$logger = $this->newEventLogger();
foreach ($this->listen as $event) {
$this->dispatcher->listen($event, function ($eventName, $events) use ($logger) {
foreach ($events as $event) {
$logger->log($event);
}
});
}
}
/**
* Make a new event logger instance.
*
* @return Logger
*/
protected function newEventLogger()
{
return new Logger($this->logger);
}
/**
* Unset the logger instance.
*
* @return void
*/
public function unsetLogger()
{
$this->logger = null;
}
/**
* Get the event dispatcher.
*
* @return DispatcherInterface|null
*/
public function dispatcher()
{
return $this->dispatcher;
}
/**
* Set the event dispatcher.
*
* @param DispatcherInterface $dispatcher
*
* @return void
*/
public function setDispatcher(DispatcherInterface $dispatcher)
{
$this->dispatcher = $dispatcher;
}
/**
* Unset the event dispatcher.
*
* @return void
*/
public function unsetEventDispatcher()
{
$this->dispatcher = null;
}
}

View File

@ -2,11 +2,21 @@
namespace LdapRecord;
use LdapRecord\Events\Dispatcher;
use LdapRecord\Events\DispatcherInterface;
use LdapRecord\Events\Logger;
use Psr\Log\LoggerInterface;
/**
* @method static $this reset()
* @method static Connection[] all()
* @method static Connection[] allConnections()
* @method static Connection getDefaultConnection()
* @method static Connection get(string|null $name = null)
* @method static Connection getConnection(string|null $name = null)
* @method static bool exists(string $name)
* @method static $this remove(string|null $name = null)
* @method static $this removeConnection(string|null $name = null)
* @method static $this setDefault(string|null $name = null)
* @method static $this setDefaultConnection(string|null $name = null)
* @method static $this add(Connection $connection, string|null $name = null)
* @method static $this addConnection(Connection $connection, string|null $name = null)
*/
class Container
{
/**
@ -17,44 +27,37 @@ class Container
protected static $instance;
/**
* The logger instance.
* The connection manager instance.
*
* @var LoggerInterface|null
* @var ConnectionManager
*/
protected $logger;
protected $manager;
/**
* The event dispatcher instance.
*
* @var DispatcherInterface|null
*/
protected $dispatcher;
/**
* The added connections in the container instance.
*
* @var Connection[]
*/
protected $connections = [];
/**
* The name of the default connection.
*
* @var string
*/
protected $default = 'default';
/**
* The events to register listeners for during initialization.
* The methods to passthru, for compatibility.
*
* @var array
*/
protected $listen = [
'LdapRecord\Auth\Events\*',
'LdapRecord\Query\Events\*',
'LdapRecord\Models\Events\*',
protected $passthru = [
'reset', 'flush',
'add', 'addConnection',
'remove', 'removeConnection',
'setDefault', 'setDefaultConnection',
];
/**
* Forward missing static calls onto the current instance.
*
* @param string $method
* @param mixed $args
*
* @return mixed
*/
public static function __callStatic($method, $args)
{
return static::getInstance()->{$method}(...$args);
}
/**
* Get or set the current instance of the container.
*
@ -88,320 +91,37 @@ class Container
}
/**
* Add a connection to the container.
*
* @param Connection $connection
* @param string|null $name
*
* @return static
*/
public static function addConnection(Connection $connection, $name = null)
{
return static::getInstance()->add($connection, $name);
}
/**
* Remove a connection from the container.
*
* @param string $name
* Constructor.
*
* @return void
*/
public static function removeConnection($name)
public function __construct()
{
static::getInstance()->remove($name);
$this->manager = new ConnectionManager();
}
/**
* Get a connection by name or return the default.
* Forward missing method calls onto the connection manager.
*
* @param string|null $name
* @param string $method
* @param mixed $args
*
* @throws ContainerException If the given connection does not exist.
*
* @return Connection
* @return mixed
*/
public static function getConnection($name = null)
public function __call($method, $args)
{
return static::getInstance()->get($name);
$value = $this->manager->{$method}(...$args);
return in_array($method, $this->passthru) ? $this : $value;
}
/**
* Set the default connection name.
* Get the connection manager.
*
* @param string|null $name
*
* @return static
* @return ConnectionManager
*/
public static function setDefaultConnection($name = null)
public function manager()
{
return static::getInstance()->setDefault($name);
}
/**
* Get the default connection.
*
* @return Connection
*/
public static function getDefaultConnection()
{
return static::getInstance()->getDefault();
}
/**
* Flush all of the added connections and reset the container.
*
* @return $this
*/
public static function reset()
{
return static::getInstance()->flush();
}
/**
* Get the container dispatcher instance.
*
* @return DispatcherInterface
*/
public static function getEventDispatcher()
{
$instance = static::getInstance();
if (! ($dispatcher = $instance->dispatcher())) {
$instance->setDispatcher($dispatcher = new Dispatcher());
}
return $dispatcher;
}
/**
* Set the container dispatcher instance.
*
* @param DispatcherInterface $dispatcher
*
* @return void
*/
public static function setEventDispatcher(DispatcherInterface $dispatcher)
{
static::getInstance()->setDispatcher($dispatcher);
}
/**
* Get the container dispatcher instance.
*
* @return DispatcherInterface|null
*/
public function dispatcher()
{
return $this->dispatcher;
}
/**
* Set the container dispatcher instance.
*
* @param DispatcherInterface $dispatcher
*
* @return void
*/
public function setDispatcher(DispatcherInterface $dispatcher)
{
$this->dispatcher = $dispatcher;
}
/**
* Unset the event dispatcher instance.
*
* @return void
*/
public function unsetEventDispatcher()
{
$this->dispatcher = null;
}
/**
* Get the logger instance.
*
* @return LoggerInterface|null
*/
public function getLogger()
{
return $this->logger;
}
/**
* Set the event logger to use.
*
* @param LoggerInterface $logger
*
* @return void
*/
public function setLogger(LoggerInterface $logger)
{
$this->logger = $logger;
$this->initEventLogger();
}
/**
* Initializes the event logger.
*
* @return void
*/
public function initEventLogger()
{
$dispatcher = $this->getEventDispatcher();
$logger = $this->newEventLogger();
foreach ($this->listen as $event) {
$dispatcher->listen($event, function ($eventName, $events) use ($logger) {
foreach ($events as $event) {
$logger->log($event);
}
});
}
}
/**
* Returns a new event logger instance.
*
* @return Logger
*/
protected function newEventLogger()
{
return new Logger($this->logger);
}
/**
* Unset the logger instance.
*
* @return void
*/
public function unsetLogger()
{
$this->logger = null;
}
/**
* Add a new connection into the container.
*
* @param Connection $connection
* @param string|null $name
*
* @return $this
*/
public function add(Connection $connection, $name = null)
{
$this->connections[$name ?? $this->default] = $connection;
if ($this->dispatcher) {
$connection->setDispatcher($this->dispatcher);
}
return $this;
}
/**
* Remove a connection from the container.
*
* @param $name
*
* @return $this
*/
public function remove($name)
{
if ($this->exists($name)) {
unset($this->connections[$name]);
}
return $this;
}
/**
* Return all of the connections from the container.
*
* @return Connection[]
*/
public function all()
{
return $this->connections;
}
/**
* Get a connection by name or return the default.
*
* @param string|null $name
*
* @throws ContainerException If the given connection does not exist.
*
* @return Connection
*/
public function get($name = null)
{
if ($this->exists($name = $name ?? $this->default)) {
return $this->connections[$name];
}
throw new ContainerException("The LDAP connection [$name] does not exist.");
}
/**
* Return the default connection.
*
* @return Connection
*/
public function getDefault()
{
return $this->get($this->default);
}
/**
* Get the default connection name.
*
* @return string
*/
public function getDefaultConnectionName()
{
return $this->default;
}
/**
* Checks if the connection exists.
*
* @param $name
*
* @return bool
*/
public function exists($name)
{
return array_key_exists($name, $this->connections);
}
/**
* Set the default connection name.
*
* @param string $name
*
* @return $this
*/
public function setDefault($name = null)
{
$this->default = $name;
return $this;
}
/**
* Flush the container of all instances and connections.
*
* @return $this
*/
public function flush()
{
$this->connections = [];
$this->dispatcher = null;
$this->logger = null;
return $this;
return $this->manager;
}
}

View File

@ -118,7 +118,7 @@ class Logger
$message = "LDAP ({$connection->getHost()})"
." - Operation: {$this->getOperationName($event)}"
." - Base DN: {$query->getDn()}"
." - Base DN: {$query->getBaseDn()}"
." - Filter: {$query->getQuery()}"
." - Selected: ({$selected})"
." - Time Elapsed: {$event->getTime()}";

View File

@ -6,10 +6,8 @@ use Closure;
use ErrorException;
use Exception;
abstract class LdapBase implements LdapInterface
trait HandlesConnection
{
use DetectsErrors;
/**
* The LDAP host that is currently connected.
*
@ -136,7 +134,7 @@ abstract class LdapBase implements LdapInterface
*/
public function getProtocol()
{
return $this->isUsingSSL() ? $this::PROTOCOL_SSL : $this::PROTOCOL;
return $this->isUsingSSL() ? LdapInterface::PROTOCOL_SSL : LdapInterface::PROTOCOL;
}
/**
@ -214,7 +212,7 @@ abstract class LdapBase implements LdapInterface
/**
* Determine if the current PHP version supports server controls.
*
* @deprecated
* @deprecated since v2.5.0
*
* @return bool
*/
@ -236,8 +234,8 @@ abstract class LdapBase implements LdapInterface
// If an attempt to connect via SSL protocol is being performed,
// and we are still using the default port, we will swap it
// for the default SSL port, for developer convenience.
if ($this->isUsingSSL() && $port == static::PORT) {
$port = static::PORT_SSL;
if ($this->isUsingSSL() && $port == LdapInterface::PORT) {
$port = LdapInterface::PORT_SSL;
}
// The blank space here is intentional. PHP's LDAP extension

View File

@ -2,8 +2,10 @@
namespace LdapRecord;
class Ldap extends LdapBase
class Ldap implements LdapInterface
{
use HandlesConnection, DetectsErrors;
/**
* @inheritdoc
*/
@ -17,9 +19,9 @@ class Ldap extends LdapBase
/**
* Retrieves the first entry from a search result.
*
* @link http://php.net/manual/en/function.ldap-first-entry.php
* @see http://php.net/manual/en/function.ldap-first-entry.php
*
* @param resource $searchResult
* @param resource $searchResults
*
* @return resource
*/
@ -33,7 +35,7 @@ class Ldap extends LdapBase
/**
* Retrieves the next entry from a search result.
*
* @link http://php.net/manual/en/function.ldap-next-entry.php
* @see http://php.net/manual/en/function.ldap-next-entry.php
*
* @param resource $entry
*
@ -49,7 +51,7 @@ class Ldap extends LdapBase
/**
* Retrieves the ldap entry's attributes.
*
* @link http://php.net/manual/en/function.ldap-get-attributes.php
* @see http://php.net/manual/en/function.ldap-get-attributes.php
*
* @param resource $entry
*
@ -65,9 +67,9 @@ class Ldap extends LdapBase
/**
* Returns the number of entries from a search result.
*
* @link http://php.net/manual/en/function.ldap-count-entries.php
* @see http://php.net/manual/en/function.ldap-count-entries.php
*
* @param resource $searchResult
* @param resource $searchResults
*
* @return int
*/
@ -81,7 +83,7 @@ class Ldap extends LdapBase
/**
* Compare value of attribute found in entry specified with DN.
*
* @link http://php.net/manual/en/function.ldap-compare.php
* @see http://php.net/manual/en/function.ldap-compare.php
*
* @param string $dn
* @param string $attribute
@ -125,7 +127,7 @@ class Ldap extends LdapBase
/**
* Get all binary values from the specified result entry.
*
* @link http://php.net/manual/en/function.ldap-get-values-len.php
* @see http://php.net/manual/en/function.ldap-get-values-len.php
*
* @param $entry
* @param $attribute
@ -160,7 +162,7 @@ class Ldap extends LdapBase
/**
* Set a callback function to do re-binds on referral chasing.
*
* @link http://php.net/manual/en/function.ldap-set-rebind-proc.php
* @see http://php.net/manual/en/function.ldap-set-rebind-proc.php
*
* @param callable $callback
*
@ -224,9 +226,9 @@ class Ldap extends LdapBase
$deref,
$serverControls
) {
return $this->supportsServerControlsInMethods() && ! empty($serverControls)
? ldap_search($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref, $serverControls)
: ldap_search($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref);
return empty($serverControls)
? ldap_search($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref)
: ldap_search($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref, $serverControls);
});
}
@ -245,9 +247,9 @@ class Ldap extends LdapBase
$deref,
$serverControls
) {
return $this->supportsServerControlsInMethods() && ! empty($serverControls)
? ldap_list($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref, $serverControls)
: ldap_list($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref);
return empty($serverControls)
? ldap_list($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref)
: ldap_list($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref, $serverControls);
});
}
@ -266,9 +268,9 @@ class Ldap extends LdapBase
$deref,
$serverControls
) {
return $this->supportsServerControlsInMethods() && ! empty($serverControls)
? ldap_read($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref, $serverControls)
: ldap_read($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref);
return empty($serverControls)
? ldap_read($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref)
: ldap_read($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref, $serverControls);
});
}
@ -285,9 +287,9 @@ class Ldap extends LdapBase
&$referrals,
&$serverControls
) {
return $this->supportsServerControlsInMethods() && ! empty($serverControls)
? ldap_parse_result($this->connection, $result, $errorCode, $dn, $errorMessage, $referrals, $serverControls)
: ldap_parse_result($this->connection, $result, $errorCode, $dn, $errorMessage, $referrals);
return empty($serverControls)
? ldap_parse_result($this->connection, $result, $errorCode, $dn, $errorMessage, $referrals)
: ldap_parse_result($this->connection, $result, $errorCode, $dn, $errorMessage, $referrals, $serverControls);
});
}
@ -419,9 +421,7 @@ class Ldap extends LdapBase
*/
public function errNo()
{
return $this->connection
? ldap_errno($this->connection)
: null;
return $this->connection ? ldap_errno($this->connection) : null;
}
/**

View File

@ -136,9 +136,9 @@ interface LdapInterface
/**
* Retrieve the entries from a search result.
*
* @link http://php.net/manual/en/function.ldap-get-entries.php
* @see http://php.net/manual/en/function.ldap-get-entries.php
*
* @param resource $searchResult
* @param resource $searchResults
*
* @return array
*/
@ -147,7 +147,7 @@ interface LdapInterface
/**
* Retrieve the last error on the current connection.
*
* @link http://php.net/manual/en/function.ldap-error.php
* @see http://php.net/manual/en/function.ldap-error.php
*
* @return string|null
*/
@ -167,7 +167,7 @@ interface LdapInterface
/**
* Set an option on the current connection.
*
* @link http://php.net/manual/en/function.ldap-set-option.php
* @see http://php.net/manual/en/function.ldap-set-option.php
*
* @param int $option
* @param mixed $value
@ -188,7 +188,7 @@ interface LdapInterface
/**
* Get the value for the LDAP option.
*
* @link https://www.php.net/manual/en/function.ldap-get-option.php
* @see https://www.php.net/manual/en/function.ldap-get-option.php
*
* @param int $option
* @param mixed $value
@ -200,7 +200,7 @@ interface LdapInterface
/**
* Starts a connection using TLS.
*
* @link http://php.net/manual/en/function.ldap-start-tls.php
* @see http://php.net/manual/en/function.ldap-start-tls.php
*
* @throws LdapRecordException
*
@ -211,7 +211,7 @@ interface LdapInterface
/**
* Connects to the specified hostname using the specified port.
*
* @link http://php.net/manual/en/function.ldap-start-tls.php
* @see http://php.net/manual/en/function.ldap-start-tls.php
*
* @param string|array $hosts
* @param int $port
@ -225,7 +225,7 @@ interface LdapInterface
*
* Returns false if no connection is present.
*
* @link http://php.net/manual/en/function.ldap-close.php
* @see http://php.net/manual/en/function.ldap-close.php
*
* @return bool
*/
@ -234,7 +234,7 @@ interface LdapInterface
/**
* Performs a search on the current connection.
*
* @link http://php.net/manual/en/function.ldap-search.php
* @see http://php.net/manual/en/function.ldap-search.php
*
* @param string $dn
* @param string $filter
@ -252,11 +252,11 @@ interface LdapInterface
/**
* Performs a single level search on the current connection.
*
* @link http://php.net/manual/en/function.ldap-list.php
* @see http://php.net/manual/en/function.ldap-list.php
*
* @param string $dn
* @param string $filter
* @param array $attributes
* @param array $fields
* @param bool $onlyAttributes
* @param int $size
* @param int $time
@ -270,7 +270,7 @@ interface LdapInterface
/**
* Reads an entry on the current connection.
*
* @link http://php.net/manual/en/function.ldap-read.php
* @see http://php.net/manual/en/function.ldap-read.php
*
* @param string $dn
* @param string $filter
@ -288,7 +288,7 @@ interface LdapInterface
/**
* Extract information from an LDAP result.
*
* @link https://www.php.net/manual/en/function.ldap-parse-result.php
* @see https://www.php.net/manual/en/function.ldap-parse-result.php
*
* @param resource $result
* @param int $errorCode
@ -305,7 +305,7 @@ interface LdapInterface
* Binds to the current connection using the specified username and password.
* If sasl is true, the current connection is bound using SASL.
*
* @link http://php.net/manual/en/function.ldap-bind.php
* @see http://php.net/manual/en/function.ldap-bind.php
*
* @param string $username
* @param string $password
@ -319,7 +319,7 @@ interface LdapInterface
/**
* Adds an entry to the current connection.
*
* @link http://php.net/manual/en/function.ldap-add.php
* @see http://php.net/manual/en/function.ldap-add.php
*
* @param string $dn
* @param array $entry
@ -333,7 +333,7 @@ interface LdapInterface
/**
* Deletes an entry on the current connection.
*
* @link http://php.net/manual/en/function.ldap-delete.php
* @see http://php.net/manual/en/function.ldap-delete.php
*
* @param string $dn
*
@ -346,7 +346,7 @@ interface LdapInterface
/**
* Modify the name of an entry on the current connection.
*
* @link http://php.net/manual/en/function.ldap-rename.php
* @see http://php.net/manual/en/function.ldap-rename.php
*
* @param string $dn
* @param string $newRdn
@ -362,7 +362,7 @@ interface LdapInterface
/**
* Modifies an existing entry on the current connection.
*
* @link http://php.net/manual/en/function.ldap-modify.php
* @see http://php.net/manual/en/function.ldap-modify.php
*
* @param string $dn
* @param array $entry
@ -376,7 +376,7 @@ interface LdapInterface
/**
* Batch modifies an existing entry on the current connection.
*
* @link http://php.net/manual/en/function.ldap-modify-batch.php
* @see http://php.net/manual/en/function.ldap-modify-batch.php
*
* @param string $dn
* @param array $values
@ -390,7 +390,7 @@ interface LdapInterface
/**
* Add attribute values to current attributes.
*
* @link http://php.net/manual/en/function.ldap-mod-add.php
* @see http://php.net/manual/en/function.ldap-mod-add.php
*
* @param string $dn
* @param array $entry
@ -404,7 +404,7 @@ interface LdapInterface
/**
* Replaces attribute values with new ones.
*
* @link http://php.net/manual/en/function.ldap-mod-replace.php
* @see http://php.net/manual/en/function.ldap-mod-replace.php
*
* @param string $dn
* @param array $entry
@ -418,7 +418,7 @@ interface LdapInterface
/**
* Delete attribute values from current attributes.
*
* @link http://php.net/manual/en/function.ldap-mod-del.php
* @see http://php.net/manual/en/function.ldap-mod-del.php
*
* @param string $dn
* @param array $entry
@ -432,7 +432,7 @@ interface LdapInterface
/**
* Send LDAP pagination control.
*
* @link http://php.net/manual/en/function.ldap-control-paged-result.php
* @see http://php.net/manual/en/function.ldap-control-paged-result.php
*
* @param int $pageSize
* @param bool $isCritical
@ -445,7 +445,7 @@ interface LdapInterface
/**
* Retrieve the LDAP pagination cookie.
*
* @link http://php.net/manual/en/function.ldap-control-paged-result-response.php
* @see http://php.net/manual/en/function.ldap-control-paged-result-response.php
*
* @param resource $result
* @param string $cookie
@ -457,7 +457,7 @@ interface LdapInterface
/**
* Frees up the memory allocated internally to store the result.
*
* @link https://www.php.net/manual/en/function.ldap-free-result.php
* @see https://www.php.net/manual/en/function.ldap-free-result.php
*
* @param resource $result
*
@ -466,10 +466,9 @@ interface LdapInterface
public function freeResult($result);
/**
* Returns the error number of the last command
* executed on the current connection.
* Returns the error number of the last command executed.
*
* @link http://php.net/manual/en/function.ldap-errno.php
* @see http://php.net/manual/en/function.ldap-errno.php
*
* @return int|null
*/
@ -478,7 +477,7 @@ interface LdapInterface
/**
* Returns the error string of the specified error number.
*
* @link http://php.net/manual/en/function.ldap-err2str.php
* @see http://php.net/manual/en/function.ldap-err2str.php
*
* @param int $number
*
@ -510,6 +509,8 @@ interface LdapInterface
/**
* Determine if the current PHP version supports server controls.
*
* @deprecated since v2.5.0
*
* @return bool
*/
public function supportsServerControlsInMethods();

View File

@ -326,7 +326,7 @@ class AccountControl
*
* For information about how to programmatically set this permission, visit the following link:
*
* @link http://msdn2.microsoft.com/en-us/library/aa746398.aspx
* @see http://msdn2.microsoft.com/en-us/library/aa746398.aspx
*
* @return $this
*/

View File

@ -3,6 +3,7 @@
namespace LdapRecord\Models\Attributes;
use LdapRecord\EscapesValues;
use LdapRecord\Support\Arr;
class DistinguishedName
{
@ -60,7 +61,7 @@ class DistinguishedName
}
/**
* Make a new Distinguished Name instance.
* Make a new distinguished name instance.
*
* @param string|null $value
*
@ -158,19 +159,15 @@ class DistinguishedName
}
/**
* Get the Distinguished Name values without attributes.
* Get the distinguished name values without attributes.
*
* @return array
*/
public function values()
{
$components = $this->components();
$values = [];
foreach ($components as $rdn) {
[,$value] = static::explodeRdn($rdn);
foreach ($this->multi() as [, $value]) {
$values[] = static::unescape($value);
}
@ -178,35 +175,45 @@ class DistinguishedName
}
/**
* Get the Distinguished Name components with attributes.
* Get the distinguished name attributes without values.
*
* @return array
*/
public function attributes()
{
$attributes = [];
foreach ($this->multi() as [$attribute]) {
$attributes[] = $attribute;
}
return $attributes;
}
/**
* Get the distinguished name components with attributes.
*
* @return array
*/
public function components()
{
$rdns = static::explode($this->value);
$components = [];
foreach ($rdns as $rdn) {
[$attribute, $value] = static::explodeRdn($rdn);
// When a Distinguished Name is exploded, the values are automatically
foreach ($this->multi() as [$attribute, $value]) {
// When a distinguished name is exploded, the values are automatically
// escaped. This cannot be opted out of. Here we will unescape
// the attribute value, then re-escape it to its original
// representation from the server using the "dn" flag.
$value = $this->escape(static::unescape($value))->dn();
$components[] = static::makeRdn([
$attribute, $value,
]);
$components[] = static::makeRdn([$attribute, $value]);
}
return $components;
}
/**
* Convert the DN into an associative array.
* Convert the distinguished name into an associative array.
*
* @return array
*/
@ -214,9 +221,7 @@ class DistinguishedName
{
$map = [];
foreach ($this->components() as $rdn) {
[$attribute, $value] = static::explodeRdn($rdn);
foreach ($this->multi() as [$attribute, $value]) {
$attribute = $this->normalize($attribute);
array_key_exists($attribute, $map)
@ -228,31 +233,71 @@ class DistinguishedName
}
/**
* Get the name value.
* Split the RDNs into a multi-dimensional array.
*
* @return array
*/
public function multi()
{
return array_map(function ($rdn) {
return static::explodeRdn($rdn);
}, $this->rdns());
}
/**
* Split the distinguished name into an array of unescaped RDN's.
*
* @return array
*/
public function rdns()
{
return static::explode($this->value);
}
/**
* Get the first RDNs value.
*
* @return string|null
*/
public function name()
{
$values = $this->values();
return reset($values) ?: null;
return Arr::first($this->values());
}
/**
* Get the relative Distinguished name.
* Get the first RDNs attribute.
*
* @return string|null
*/
public function head()
{
return Arr::first($this->attributes());
}
/**
* Get the relative distinguished name.
*
* @return string|null
*/
public function relative()
{
$components = $this->components();
return reset($components) ?: null;
return Arr::first($this->components());
}
/**
* Get the parent Distinguished name.
* Alias of relative().
*
* Get the first RDN from the distinguished name.
*
* @return string|null
*/
public function first()
{
return $this->relative();
}
/**
* Get the parent distinguished name.
*
* @return string|null
*/
@ -266,7 +311,7 @@ class DistinguishedName
}
/**
* Determine if the current Distinguished Name is a parent of the given child.
* Determine if the current distinguished name is a parent of the given child.
*
* @param DistinguishedName $child
*
@ -278,7 +323,7 @@ class DistinguishedName
}
/**
* Determine if the current Distinguished Name is a child of the given parent.
* Determine if the current distinguished name is a child of the given parent.
*
* @param DistinguishedName $parent
*
@ -299,7 +344,7 @@ class DistinguishedName
}
/**
* Determine if the current Distinguished Name is an ancestor of the descendant.
* Determine if the current distinguished name is an ancestor of the descendant.
*
* @param DistinguishedName $descendant
*
@ -311,7 +356,7 @@ class DistinguishedName
}
/**
* Determine if the current Distinguished Name is a descendant of the ancestor.
* Determine if the current distinguished name is a descendant of the ancestor.
*
* @param DistinguishedName $ancestor
*
@ -336,7 +381,7 @@ class DistinguishedName
}
/**
* Compare whether the two Distinguished Name values are equal.
* Compare whether the two distinguished name values are equal.
*
* @param array $values
* @param array $other

View File

@ -45,7 +45,7 @@ class DistinguishedNameBuilder
*/
public function __call($method, $args)
{
return $this->get()->{$method}($args);
return $this->get()->{$method}(...$args);
}
/**

View File

@ -19,7 +19,7 @@ class Guid
*
* @author Chad Sikorra <Chad.Sikorra@gmail.com>
*
* @link https://github.com/ldaptools/ldaptools
* @see https://github.com/ldaptools/ldaptools
*
* @var array
*/
@ -36,7 +36,7 @@ class Guid
*
* @author Chad Sikorra <Chad.Sikorra@gmail.com>
*
* @link https://github.com/ldaptools/ldaptools
* @see https://github.com/ldaptools/ldaptools
*
* @var array
*/
@ -142,7 +142,7 @@ class Guid
*
* @author Chad Sikorra <Chad.Sikorra@gmail.com>
*
* @link https://github.com/ldaptools/ldaptools
* @see https://github.com/ldaptools/ldaptools
*
* @param string $hex The full hex string.
* @param array $sections An array of start and length (unless octet is true, then length is always 2).

View File

@ -185,7 +185,15 @@ trait HasPassword
*/
protected function validateSecureConnection()
{
if (! $this->getConnection()->getLdapConnection()->canChangePasswords()) {
$connection = $this->getConnection();
if ($connection->isConnected()) {
$secure = $connection->getLdapConnection()->canChangePasswords();
} else {
$secure = $connection->getConfiguration()->get('use_ssl') || $connection->getConfiguration()->get('use_tls');
}
if (! $secure) {
throw new ConnectionException(
'You must be connected to your LDAP server with TLS or SSL to perform this operation.'
);

View File

@ -5,7 +5,7 @@ namespace LdapRecord\Models\Concerns;
/**
* @author Taylor Otwell
*
* @link https://laravel.com
* @see https://laravel.com
*/
trait HidesAttributes
{

View File

@ -767,6 +767,18 @@ abstract class Model implements ArrayAccess, JsonSerializable
return $this->newDn($dn ?? $this->dn)->name();
}
/**
* Get the head attribute of the model, or the given DN.
*
* @param string|null $dn
*
* @return string|null
*/
public function getHead($dn = null)
{
return $this->newDn($dn ?? $this->dn)->head();
}
/**
* Get the RDN of the model, of the given DN.
*
@ -803,10 +815,20 @@ abstract class Model implements ArrayAccess, JsonSerializable
return new DistinguishedName($dn);
}
/**
* Get the model's object GUID key.
*
* @return void
*/
public function getObjectGuidKey()
{
return $this->guidKey;
}
/**
* Get the model's binary object GUID.
*
* @link https://msdn.microsoft.com/en-us/library/ms679021(v=vs.85).aspx
* @see https://msdn.microsoft.com/en-us/library/ms679021(v=vs.85).aspx
*
* @return string|null
*/
@ -952,8 +974,8 @@ abstract class Model implements ArrayAccess, JsonSerializable
protected function performInsert()
{
// Here we will populate the models object classes if it
// does not already have any. An LDAP object cannot
// be successfully created without them set.
// does not already have any set. An LDAP object cannot
// be successfully created in the server without them.
if (! $this->hasAttribute('objectclass')) {
$this->setAttribute('objectclass', static::$objectClasses);
}
@ -961,17 +983,18 @@ abstract class Model implements ArrayAccess, JsonSerializable
$query = $this->newQuery();
// If the model does not currently have a distinguished
// name, we will attempt to create one automatically
// using the current query builders DN as a base.
// name, we will attempt to generate one automatically
// using the current query builder's DN as the base.
if (empty($this->getDn())) {
$this->setDn($this->getCreatableDn());
}
$this->fireModelEvent(new Events\Creating($this));
// Here we perform the insert of the object in the directory.
// We will also filter out any empty attribute values here,
// otherwise the LDAP server will return an error message.
// Here we perform the insert of new object in the directory,
// but filter out any empty attributes before sending them
// to the server. LDAP servers will throw an exception if
// attributes have been given empty or null values.
$query->insert($this->getDn(), array_filter($this->getAttributes()));
$this->fireModelEvent(new Events\Created($this));

View File

@ -2,6 +2,7 @@
namespace LdapRecord\Models\Relations;
use Closure;
use LdapRecord\DetectsErrors;
use LdapRecord\LdapRecordException;
use LdapRecord\Models\Model;
@ -107,6 +108,21 @@ class HasMany extends OneToMany
return $result;
}
/**
* Chunk the relation results using the given callback.
*
* @param int $pageSize
* @param Closure $callback
*
* @return void
*/
public function chunk($pageSize, Closure $callback)
{
$this->getRelationQuery()->chunk($pageSize, function ($entries) use ($callback) {
$callback($this->transformResults($entries));
});
}
/**
* Get the relationships results.
*

View File

@ -89,7 +89,7 @@ abstract class OneToMany extends Relation
public function getResults()
{
$results = $this->recursive
? $this->getRecursiveResults($this->getRelationResults())
? $this->getRecursiveResults()
: $this->getRelationResults();
return $results->merge(
@ -142,46 +142,45 @@ abstract class OneToMany extends Relation
/**
* Get the results for the models relation recursively.
*
* @param Collection $models The models to retrieve nested relation results from
* @param string[] $loaded The distinguished names of models already loaded
*
* @return Collection
*/
protected function getRecursiveResults(Collection $models, array &$loaded = [])
protected function getRecursiveResults(array $loaded = [])
{
return $models->unless(empty($loaded), function ($models) use ($loaded) {
$results = $this->getRelationResults()->reject(function (Model $model) use ($loaded) {
// Here we will exclude the models that we have already
// gathered the recursive results for so we don't run
// loaded the recursive results for so we don't run
// into issues with circular relations in LDAP.
return $models->reject(function (Model $model) use ($loaded) {
return in_array($model->getDn(), $loaded);
});
})->each(function (Model $model) use (&$loaded, $models) {
foreach ($results as $model) {
$loaded[] = $model->getDn();
// Next, we will call the same relation method on each
// returned model to retrieve its related models and
// merge them into our final resulting collection.
$this->getRecursiveResults(
$this->getRecursiveRelationResults($model),
$loaded
)->each(function (Model $related) use ($models) {
$models->add($related);
});
});
// Finally, we will fetch the related models relations,
// passing along our loaded models, to ensure we do
// not attempt fetching already loaded relations.
$results = $results->merge(
$this->getRecursiveRelationResults($model, $loaded)
);
}
return $results;
}
/**
* Get the recursive relation results for given model.
*
* @param Model $model
* @param array $loaded
*
* @return Collection
*/
protected function getRecursiveRelationResults(Model $model)
protected function getRecursiveRelationResults(Model $model, array $loaded)
{
return method_exists($model, $this->relationName)
? $model->{$this->relationName}()->recursive()->get()
? $model->{$this->relationName}()->getRecursiveResults($loaded)
: $model->newCollection();
}
}

View File

@ -14,7 +14,7 @@ interface ActiveDirectory extends TypeInterface
/**
* Returns the model's hex object SID.
*
* @link https://msdn.microsoft.com/en-us/library/ms679024(v=vs.85).aspx
* @see https://msdn.microsoft.com/en-us/library/ms679024(v=vs.85).aspx
*
* @return string
*/

View File

@ -44,12 +44,36 @@ class ArrayCacheStore implements CacheInterface
{
$this->storage[$key] = [
'value' => $value,
'expiresAt' => $this->parseDateInterval($ttl),
'expiresAt' => $this->calculateExpiration($ttl),
];
return true;
}
/**
* Get the expiration time of the key.
*
* @param int $seconds
*
* @return int
*/
protected function calculateExpiration($seconds)
{
return $this->toTimestamp($seconds);
}
/**
* Get the UNIX timestamp for the given number of seconds.
*
* @param int $seconds
*
* @return int
*/
protected function toTimestamp($seconds)
{
return $seconds > 0 ? $this->availableAt($seconds) : 0;
}
/**
* @inheritdoc
*/

View File

@ -51,7 +51,13 @@ class Cache
*/
public function put($key, $value, $ttl = null)
{
return $this->store->set($key, $value, $this->expiresAt($ttl));
$seconds = $this->secondsUntil($ttl);
if ($seconds <= 0) {
return $this->delete($key);
}
return $this->store->set($key, $value, $seconds);
}
/**

View File

@ -9,18 +9,34 @@ use DateTimeInterface;
/**
* @author Taylor Otwell
*
* @link https://laravel.com
* @see https://laravel.com
*/
trait InteractsWithTime
{
/**
* Get the "expires at" UNIX timestamp.
* Get the number of seconds until the given DateTime.
*
* @param DateTimeInterface|DateInterval|int $delay
*
* @return int
*/
protected function expiresAt($delay = 0)
protected function secondsUntil($delay)
{
$delay = $this->parseDateInterval($delay);
return $delay instanceof DateTimeInterface
? max(0, $delay->getTimestamp() - $this->currentTime())
: (int) $delay;
}
/**
* Get the "available at" UNIX timestamp.
*
* @param DateTimeInterface|DateInterval|int $delay
*
* @return int
*/
protected function availableAt($delay = 0)
{
$delay = $this->parseDateInterval($delay);

View File

@ -5,7 +5,7 @@ namespace LdapRecord\Query\Pagination;
use LdapRecord\LdapInterface;
/**
* @deprecated
* @deprecated since v2.5.0
*/
class DeprecatedPaginator extends AbstractPaginator
{

View File

@ -32,7 +32,11 @@ class ConnectionFake extends Connection
*/
public static function make(array $config = [], $ldap = LdapFake::class)
{
return new static($config, new $ldap());
$connection = new static($config, new $ldap());
$connection->configure();
return $connection;
}
/**

View File

@ -207,7 +207,7 @@ class LdapExpectation
public function getMethod()
{
if (is_null($this->method)) {
throw new UnexpectedValueException('The [$method] property cannot be null.');
throw new UnexpectedValueException('An expectation must have a method.');
}
return $this->method;
@ -226,7 +226,7 @@ class LdapExpectation
/**
* Get the expected arguments.
*
* @return array
* @return Constraint[]
*/
public function getExpectedArgs()
{

View File

@ -4,13 +4,17 @@ namespace LdapRecord\Testing;
use Exception;
use LdapRecord\DetailedError;
use LdapRecord\LdapBase;
use LdapRecord\DetectsErrors;
use LdapRecord\HandlesConnection;
use LdapRecord\LdapInterface;
use LdapRecord\Support\Arr;
use PHPUnit\Framework\Assert as PHPUnit;
use PHPUnit\Framework\Constraint\Constraint;
class LdapFake extends LdapBase
class LdapFake implements LdapInterface
{
use HandlesConnection, DetectsErrors;
/**
* The expectations of the LDAP fake.
*
@ -101,7 +105,7 @@ class LdapFake extends LdapBase
*
* @return bool
*/
protected function hasExpectations($method)
public function hasExpectations($method)
{
return count($this->getExpectations($method)) > 0;
}
@ -113,7 +117,7 @@ class LdapFake extends LdapBase
*
* @return LdapExpectation[]|mixed
*/
protected function getExpectations($method)
public function getExpectations($method)
{
return $this->expectations[$method] ?? [];
}
@ -126,7 +130,7 @@ class LdapFake extends LdapBase
*
* @return void
*/
protected function removeExpectation($method, $key)
public function removeExpectation($method, $key)
{
unset($this->expectations[$method][$key]);
}
@ -230,7 +234,7 @@ class LdapFake extends LdapBase
{
return $this->hasExpectations('isUsingSSL')
? $this->resolveExpectation('isUsingSSL')
: parent::isUsingSSL();
: $this->useSSL;
}
/**
@ -240,7 +244,7 @@ class LdapFake extends LdapBase
{
return $this->hasExpectations('isUsingTLS')
? $this->resolveExpectation('isUsingTLS')
: parent::isUsingTLS();
: $this->useTLS;
}
/**
@ -250,7 +254,7 @@ class LdapFake extends LdapBase
{
return $this->hasExpectations('isBound')
? $this->resolveExpectation('isBound')
: parent::isBound();
: $this->bound;
}
/**
@ -453,7 +457,7 @@ class LdapFake extends LdapBase
*
* @return mixed
*/
protected function resolveExpectation($method, $args = [])
protected function resolveExpectation($method, array $args = [])
{
foreach ($this->getExpectations($method) as $key => $expectation) {
$this->assertMethodArgumentsMatch($method, $expectation->getExpectedArgs(), $args);
@ -501,7 +505,7 @@ class LdapFake extends LdapBase
*
* @return void
*/
protected function assertMethodArgumentsMatch($method, $expectedArgs = [], $methodArgs = [])
protected function assertMethodArgumentsMatch($method, array $expectedArgs = [], array $methodArgs = [])
{
foreach ($expectedArgs as $key => $constraint) {
$argNumber = $key + 1;

View File

@ -55,8 +55,8 @@ class Utilities
*
* @author Chad Sikorra
*
* @link https://github.com/ChadSikorra
* @link https://stackoverflow.com/questions/39533560/php-ldap-get-user-sid
* @see https://github.com/ChadSikorra
* @see https://stackoverflow.com/questions/39533560/php-ldap-get-user-sid
*
* @param string $value The Binary SID
*

View File

@ -2,7 +2,9 @@
namespace Illuminate\Contracts\Support;
interface MessageBag extends Arrayable
use Countable;
interface MessageBag extends Arrayable, Countable
{
/**
* Get the keys present in the message bag.
@ -97,11 +99,4 @@ interface MessageBag extends Arrayable
* @return bool
*/
public function isNotEmpty();
/**
* Get the number of messages in the container.
*
* @return int
*/
public function count();
}

View File

@ -7,30 +7,24 @@
"time",
"DateTime"
],
"homepage": "http://carbon.nesbot.com",
"support": {
"issues": "https://github.com/briannesbitt/Carbon/issues",
"source": "https://github.com/briannesbitt/Carbon"
},
"homepage": "https://carbon.nesbot.com",
"license": "MIT",
"authors": [
{
"name": "Brian Nesbitt",
"email": "brian@nesbot.com",
"homepage": "http://nesbot.com"
"homepage": "https://markido.com"
},
{
"name": "kylekatarnls",
"homepage": "http://github.com/kylekatarnls"
"homepage": "https://github.com/kylekatarnls"
}
],
"prefer-stable": true,
"minimum-stability": "dev",
"bin": ["bin/carbon"],
"require": {
"php": "^7.1.8 || ^8.0",
"ext-json": "*",
"symfony/polyfill-mbstring": "^1.0",
"symfony/polyfill-php80": "^1.16",
"symfony/translation": "^3.4 || ^4.0 || ^5.0"
},
"require-dev": {
@ -43,43 +37,14 @@
"phpunit/phpunit": "^7.5.20 || ^8.5.14",
"squizlabs/php_codesniffer": "^3.4"
},
"autoload": {
"psr-4": {
"Carbon\\": "src/Carbon/"
}
},
"autoload-dev": {
"files": [
"tests/Laravel/ServiceProvider.php"
],
"psr-4": {
"Tests\\": "tests/"
}
},
"config": {
"process-timeout": 0,
"sort-packages": true
},
"scripts": {
"test": [
"@phpunit",
"@style-check"
],
"style-check": [
"@phpcs",
"@phpstan",
"@phpmd"
],
"phpunit": "phpunit --verbose",
"phpcs": "php-cs-fixer fix -v --diff --dry-run",
"phpstan": "phpstan analyse --configuration phpstan.neon",
"phpmd": "phpmd src text /phpmd.xml",
"phpdoc": "php phpdoc.php"
},
"extra": {
"branch-alias": {
"dev-master": "2.x-dev",
"dev-3.x": "3.x-dev"
"dev-3.x": "3.x-dev",
"dev-master": "2.x-dev"
},
"laravel": {
"providers": [
@ -91,5 +56,43 @@
"extension.neon"
]
}
},
"autoload": {
"psr-4": {
"Carbon\\": "src/Carbon/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
},
"files": [
"tests/Laravel/ServiceProvider.php"
]
},
"minimum-stability": "dev",
"prefer-stable": true,
"bin": [
"bin/carbon"
],
"scripts": {
"phpcs": "php-cs-fixer fix -v --diff --dry-run",
"phpdoc": "php phpdoc.php",
"phpmd": "phpmd src text /phpmd.xml",
"phpstan": "phpstan analyse --configuration phpstan.neon",
"phpunit": "phpunit --verbose",
"style-check": [
"@phpcs",
"@phpstan",
"@phpmd"
],
"test": [
"@phpunit",
"@style-check"
]
},
"support": {
"issues": "https://github.com/briannesbitt/Carbon/issues",
"source": "https://github.com/briannesbitt/Carbon"
}
}

View File

@ -1,154 +0,0 @@
# Contributing to Carbon
## Issue Contributions
Please report any security issue using [Tidelift security contact](https://tidelift.com/security).
Tidelift will coordinate the fix and disclosure.
Please don't disclose security bugs publicly until they have been handled by us.
For any other bug or issue, please click this link and follow the template:
[Create new issue](https://github.com/briannesbitt/Carbon/issues/new)
You may think this template does not apply to your case but please think again. A long description will never be as
clear as a code chunk with the output you expect from it (for either bug report or new features).
## Code Contributions
### Where to begin
We use the label **good first issue** to tag issues that could be a good fit for new contributors, see if there are such issues now following this link:
https://github.com/briannesbitt/Carbon/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22
Else, check the roadmap to see what we plan to do in next releases:
https://github.com/briannesbitt/Carbon/issues/1681
### Develop locally, then submit changes
Fork the [GitHub project](https://github.com/briannesbitt/Carbon) and download it locally:
```shell
git clone https://github.com/<username>/Carbon.git
cd Carbon
git remote add upstream https://github.com/briannesbitt/Carbon.git
```
Replace `<username>` with your GitHub username.
Then, you can work on the master or create a specific branch for your development:
```shell
git checkout -b my-feature-branch -t origin/master
```
You can now edit the "Carbon" directory contents.
Before committing, please set your name and your e-mail (use the same e-mail address as in your GitHub account):
```shell
git config --global user.name "Your Name"
git config --global user.email "your.email.address@example.com"
```
The ```--global``` argument will apply this setting for all your git repositories, remove it to set only your Carbon
fork with those settings.
Now you can commit your modifications as you usually do with git:
```shell
git add --all
git commit -m "The commit message log"
```
If your patch fixes an open issue, please insert ```#``` immediately followed by the issue number:
```shell
git commit -m "#21 Fix this or that"
```
Use git rebase (not git merge) to sync your work from time to time:
```shell
git fetch origin
git rebase origin/master
```
Please add some tests for bug fixes and features (so it will ensure next developments will not break your code),
then check all is right with phpunit:
Install PHP if you haven't yet, then install composer:
https://getcomposer.org/download/
Update dependencies:
```
./composer.phar update
```
Or if you installed composer globally:
```
composer update
```
Then call phpunit:
```
./vendor/bin/phpunit
```
Make sure all tests succeed before submitting your pull-request, else we will not be able to merge it.
Push your work on your remote GitHub fork with:
```
git push origin my-feature-branch
```
Go to https://github.com/yourusername/Carbon and select your feature branch. Click the 'Pull Request' button and fill
out the form.
We will review it within a few days. And we thank you in advance for your help.
## Versioning
### Note about Semantic Versioning and breaking changes
As a developer, you must understand every change is a breaking change. What is a bug for someone
is expected in someone else's workflow. The consequence of a change strongly depends on the usage.
[Semantic Versioning](https://semver.org/) relies to public API. In PHP, the public API of a class is its public
methods. However, if you extend a class, you can access protected methods, then if you use reflexion, you can
access private methods. So anything can become a public API if you force it to be. That doesn't mean we should handle
any possible usage, else we would have to publish a major release for each change and it would no longer make sense.
So before any complain about a breaking change, be warned, we do not guarantee a strict Semantic Versioning as you
may expect, we're following a pragmatic interpretation of Semantic Versioning that allows the software to evolve in a
reliable way with reasonable maintenance effort.
Concretely, we consider a change as breaking if it makes fail one of our unit test. We will do our best to avoid
incompatibilities with libraries that extends Carbon classes (such as Laravel that is continuously tested thanks to
Travis CI, [see the compatibility matrix](https://github.com/kylekatarnls/carbon-laravel/tree/master#carbon-1-dev-version-1next)).
If you're the owner of a library that strongly depends on Carbon, we recommend you to run unit tests daily requiring
`"nesbot/carbon": "dev-master"` (for `^2`) or `"nesbot/carbon": "dev-version-1.next"` (for `^1`), this way you can
detect incompatibilities earlier and report it to us before we tag a release. We'll pay attention and try to fix it to
make update to next minor releases as soft as possible.
We reserve the right to publish emergency patches within 24 hours after a release if a tag that does not respect
this pattern would have been released despite our vigilance. In this very rare and particular case, we would mark the
tag as broken on GitHub and backward compatibility would be based on previous stable tag.
Last, you must understand that Carbon extends PHP natives classes, that means Carbon can be impacted by any change
that occurs in the date/time API of PHP. We watch new PHP versions and handle those changes as quickly as possible
when detected, but as PHP does not follow the semantic versioning pattern, it basically means any releases (including
patches) can have unexpected consequences on Carbon methods results.
### Long term support
To benefit the better support, require Carbon using major version range (`^1` or `^2`). By requiring `1.26.*`,
`~1.26.0` or limited range such as `>=1.20 <1.33`, you fall to low priority support (only security and critical issues
will be fixed), our prior support goes to next minor releases of each major version. It applies to bug fixes and
low-cost features. Other new features will only be added in the last stable release. At the opposite, we recommend you
to restrain to a major number, as there is no compatibility guarantee from a major version to the next. It means
requiring `>=2`, as it allows any newer version, will probably leads to errors on releasing our next major version.
Open milestones can be patched if a minor bug is detected while if you're on a closed milestone, we'll more likely
ask you to update first to an open one. See currently open milestones:
https://github.com/briannesbitt/Carbon/milestones

View File

@ -1,46 +0,0 @@
<?xml version="1.0"?>
<ruleset name="Mess detection rules for Carbon"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0
http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="
http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>
Mess detection rules for Carbon
</description>
<rule ref="rulesets/codesize.xml">
<exclude name="CyclomaticComplexity" />
<exclude name="NPathComplexity" />
<exclude name="ExcessiveMethodLength" />
<exclude name="ExcessiveClassLength" />
<exclude name="ExcessivePublicCount" />
<exclude name="TooManyMethods" />
<exclude name="TooManyPublicMethods" />
<exclude name="ExcessiveClassComplexity" />
</rule>
<rule ref="rulesets/cleancode.xml">
<exclude name="BooleanArgumentFlag" />
<exclude name="StaticAccess" />
<exclude name="IfStatementAssignment" />
<exclude name="UndefinedVariable" />
<exclude name="ErrorControlOperator" />
</rule>
<rule ref="rulesets/controversial.xml" />
<rule ref="rulesets/design.xml">
<exclude name="EvalExpression" />
<exclude name="CouplingBetweenObjects" />
<exclude name="CountInLoopExpression" />
</rule>
<rule ref="rulesets/design.xml/CouplingBetweenObjects">
<properties>
<property name="maximum" value="25" />
</properties>
</rule>
<rule ref="rulesets/naming.xml/ShortVariable">
<properties>
<property name="exceptions" value="ci,id,to,tz" />
</properties>
</rule>
<rule ref="rulesets/unusedcode.xml" />
</ruleset>

View File

@ -8,7 +8,7 @@
[![PHPStan](https://img.shields.io/badge/PHPStan-enabled-44CC11.svg?longCache=true&style=flat-square)](https://github.com/phpstan/phpstan)
[![Tidelift](https://tidelift.com/badges/github/briannesbitt/Carbon)](https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme)
An international PHP extension for DateTime. [http://carbon.nesbot.com](http://carbon.nesbot.com)
An international PHP extension for DateTime. [https://carbon.nesbot.com](https://carbon.nesbot.com)
```php
<?php
@ -84,7 +84,7 @@ printf("Now: %s", Carbon::now());
### Without Composer
Why are you not using [composer](http://getcomposer.org/)? Download the Carbon [latest release](https://github.com/briannesbitt/Carbon/releases) and put the contents of the ZIP archive into a directory in your project. Then require the file `autoload.php` to get all classes and dependencies loaded on need.
Why are you not using [composer](https://getcomposer.org/)? Download the Carbon [latest release](https://github.com/briannesbitt/Carbon/releases) and put the contents of the ZIP archive into a directory in your project. Then require the file `autoload.php` to get all classes and dependencies loaded on need.
```php
<?php
@ -97,7 +97,7 @@ printf("Now: %s", Carbon::now());
## Docs
[http://carbon.nesbot.com/docs](http://carbon.nesbot.com/docs)
[https://carbon.nesbot.com/docs](https://carbon.nesbot.com/docs)
## Security contact information
@ -122,7 +122,7 @@ This project exists thanks to all the people who contribute.
Support this project by becoming a sponsor. Your logo will show up here with a link to your website.
<a href="https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme" target="_blank"><img src="https://carbon.nesbot.com/tidelift-brand.png" width="256" height="64"></a>
<a href="https://onlinecasinohex.ca/?utm_source=opencollective&amp;utm_medium=github&amp;utm_campaign=Carbon" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/0/avatar.svg" width="192" height="64"></a>
<a href="https://onlinecasinohex.ca/?utm_source=opencollective&amp;utm_medium=github&amp;utm_campaign=Carbon" target="_blank"><img src="https://images.opencollective.com/hexcasinoca/2da3af2/logo/256.png" width="85" height="64"></a>
<a href="https://opencollective.com/Carbon/sponsor/0/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/Carbon/sponsor/1/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/Carbon/sponsor/2/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/2/avatar.svg"></a>

View File

@ -555,6 +555,11 @@ class CarbonImmutable extends DateTimeImmutable implements CarbonInterface
return 145261681241552;
}
// Remove if https://bugs.php.net/bug.php?id=81107 is fixed
if (version_compare(PHP_VERSION, '8.1.0-dev', '>=')) {
return 1118290769066902787;
}
return PHP_INT_MAX;
}
@ -567,6 +572,11 @@ class CarbonImmutable extends DateTimeImmutable implements CarbonInterface
return -135908816449551;
}
// Remove if https://bugs.php.net/bug.php?id=81107 is fixed
if (version_compare(PHP_VERSION, '8.1.0-dev', '>=')) {
return -1118290769066898816;
}
return max(PHP_INT_MIN, -9223372036854773760);
}
}

View File

@ -26,6 +26,7 @@ use DateTimeInterface;
use DateTimeZone;
use JsonSerializable;
use ReflectionException;
use ReturnTypeWillChange;
use Throwable;
/**
@ -721,6 +722,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @return static
*/
#[ReturnTypeWillChange]
public static function __set_state($dump);
/**
@ -755,6 +757,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @return static
*/
#[ReturnTypeWillChange]
public function add($unit, $value = 1, $overflow = null);
/**
@ -830,6 +833,16 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*/
public function average($date = null);
/**
* Clone the current instance if it's mutable.
*
* This method is convenient to ensure you don't mutate the initial object
* but avoid to make a useless copy of it if it's already immutable.
*
* @return static
*/
public function avoidMutation();
/**
* Determines if the instance is between two others.
*
@ -1066,6 +1079,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @return static|false
*/
#[ReturnTypeWillChange]
public static function createFromFormat($format, $time, $tz = null);
/**
@ -1946,7 +1960,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
/**
* Format the instance with the current locale. You can set the current
* locale using setlocale() http://php.net/setlocale.
* locale using setlocale() https://php.net/setlocale.
*
* @param string $format
*
@ -2135,6 +2149,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
/**
* {@inheritdoc}
*/
#[ReturnTypeWillChange]
public static function getLastErrors();
/**
@ -3007,6 +3022,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @return array|string
*/
#[ReturnTypeWillChange]
public function jsonSerialize();
/**
@ -3317,6 +3333,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @see https://php.net/manual/en/datetime.modify.php
*/
#[ReturnTypeWillChange]
public function modify($modify);
/**
@ -3700,6 +3717,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @return static
*/
#[ReturnTypeWillChange]
public function setDate($year, $month, $day);
/**
@ -3764,6 +3782,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @return static
*/
#[ReturnTypeWillChange]
public function setISODate($year, $week, $day = 1);
/**
@ -3834,6 +3853,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @return static
*/
#[ReturnTypeWillChange]
public function setTime($hour, $minute, $second = 0, $microseconds = 0);
/**
@ -3863,6 +3883,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @return static
*/
#[ReturnTypeWillChange]
public function setTimestamp($unixTimestamp);
/**
@ -3872,6 +3893,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @return static
*/
#[ReturnTypeWillChange]
public function setTimezone($value);
/**
@ -4213,6 +4235,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @return static
*/
#[ReturnTypeWillChange]
public function sub($unit, $value = 1, $overflow = null);
public function subRealUnit($unit, $value = 1);
@ -4751,7 +4774,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @param string $key
* @param array $parameters
* @param null $number
* @param string|int|float|null $number
* @param \Symfony\Component\Translation\TranslatorInterface $translator
*
* @return string
@ -4808,7 +4831,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
public static function translateWith(\Symfony\Component\Translation\TranslatorInterface $translator, string $key, array $parameters = [], $number = null): string;
/**
* Format as ->format() do (using date replacements patterns from http://php.net/manual/fr/function.date.php)
* Format as ->format() do (using date replacements patterns from https://php.net/manual/en/function.date.php)
* but translate words whenever possible (months, day names, etc.) using the current locale.
*
* @param string $format
@ -4991,6 +5014,8 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @param Closure|static|string|false|null $testNow real or mock Carbon instance
* @param Closure|null $callback
*
* @return mixed
*/
public static function withTestNow($testNow = null, $callback = null);

View File

@ -353,7 +353,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
$spec = $years;
if (!\is_string($spec) || \floatval($years) || preg_match('/^[0-9.]/', $years)) {
if (!\is_string($spec) || (float) $years || preg_match('/^[0-9.]/', $years)) {
$spec = static::PERIOD_PREFIX;
$spec .= $years > 0 ? $years.static::PERIOD_YEARS : '';
@ -380,7 +380,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
parent::__construct($spec);
if (!\is_null($microseconds)) {
if ($microseconds !== null) {
$this->f = $microseconds / Carbon::MICROSECONDS_PER_SECOND;
}
}
@ -536,7 +536,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
}
$interval = mb_substr($interval, mb_strlen($match[0]));
$instance->$unit += \intval($match[0]);
$instance->$unit += (int) ($match[0]);
continue;
}
@ -546,7 +546,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
"'$expected'",
$nextCharacter,
'Allowed substitutes for interval formats are '.implode(', ', array_keys(static::$formats))."\n".
'See https://www.php.net/manual/en/function.date.php for their meaning'
'See https://php.net/manual/en/function.date.php for their meaning'
);
}
@ -679,8 +679,8 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
preg_match_all($pattern, $intervalDefinition, $parts, PREG_SET_ORDER);
while ([$part, $value, $unit] = array_shift($parts)) {
$intValue = \intval($value);
$fraction = \floatval($value) - $intValue;
$intValue = (int) $value;
$fraction = (float) $value - $intValue;
// Fix calculation precision
switch (round($fraction, 6)) {
@ -964,7 +964,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
*
* @return static
*
* @link http://php.net/manual/en/dateinterval.createfromdatestring.php
* @link https://php.net/manual/en/dateinterval.createfromdatestring.php
*/
#[ReturnTypeWillChange]
public static function createFromDateString($time)
@ -996,7 +996,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
*/
public function get($name)
{
if (substr($name, 0, 5) === 'total') {
if (str_starts_with($name, 'total')) {
return $this->total(substr($name, 5));
}
@ -1360,7 +1360,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
$minimumUnit = 's';
extract($this->getForHumansInitialVariables($syntax, $short));
if (\is_null($syntax)) {
if ($syntax === null) {
$syntax = CarbonInterface::DIFF_ABSOLUTE;
}
@ -1368,7 +1368,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
$parts = INF;
}
if (\is_null($options)) {
if ($options === null) {
$options = static::getHumanDiffOptions();
}
@ -1860,7 +1860,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
[$value, $unit] = [$unit, $value];
}
return $this->add($unit, -\floatval($value));
return $this->add($unit, -(float) $value);
}
/**
@ -2104,7 +2104,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
public static function compareDateIntervals(DateInterval $first, DateInterval $second)
{
$current = Carbon::now();
$passed = $current->copy()->add($second);
$passed = $current->avoidMutation()->add($second);
$current->add($first);
if ($current < $passed) {
@ -2242,12 +2242,12 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
'years' => $this->years,
'months' => $this->months,
'weeks' => (int) ($this->d / $daysPerWeek),
'dayz' => (int) ($this->d % $daysPerWeek),
'dayz' => $this->d % $daysPerWeek,
'hours' => $this->hours,
'minutes' => $this->minutes,
'seconds' => $this->seconds,
'milliseconds' => (int) ($this->microseconds / Carbon::MICROSECONDS_PER_MILLISECOND),
'microseconds' => (int) ($this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND),
'microseconds' => $this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND,
];
if (isset($factors['dayz']) && $factors['dayz'][0] !== 'weeks') {

View File

@ -32,6 +32,7 @@ use InvalidArgumentException;
use Iterator;
use JsonSerializable;
use ReflectionException;
use ReturnTypeWillChange;
use RuntimeException;
/**
@ -875,7 +876,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
*/
public function setOptions($options)
{
if (!\is_int($options) && !\is_null($options)) {
if (!\is_int($options) && $options !== null) {
throw new InvalidPeriodParameterException('Invalid options.');
}
@ -962,7 +963,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
*/
public function getStartDate(string $rounding = null)
{
$date = $this->startDate->copy();
$date = $this->startDate->avoidMutation();
return $rounding ? $date->round($this->getDateInterval(), $rounding) : $date;
}
@ -980,7 +981,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
return null;
}
$date = $this->endDate->copy();
$date = $this->endDate->avoidMutation();
return $rounding ? $date->round($this->getDateInterval(), $rounding) : $date;
}
@ -1220,7 +1221,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
*/
public function setRecurrences($recurrences)
{
if (!is_numeric($recurrences) && !\is_null($recurrences) || $recurrences < 0) {
if (!is_numeric($recurrences) && $recurrences !== null || $recurrences < 0) {
throw new InvalidPeriodParameterException('Invalid number of recurrences.');
}
@ -1276,7 +1277,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
*/
public function setEndDate($date, $inclusive = null)
{
if (!\is_null($date) && !$date = ([$this->dateClass, 'make'])($date)) {
if ($date !== null && !$date = ([$this->dateClass, 'make'])($date)) {
throw new InvalidPeriodDateException('Invalid end date.');
}
@ -1523,7 +1524,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
{
$state = [
$this->key,
$this->current ? $this->current->copy() : null,
$this->current ? $this->current->avoidMutation() : null,
$this->validationResult,
];
@ -1722,7 +1723,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
$date = $this->getEndFromRecurrences() ?? $this->iterateUntilEnd();
if ($date && $rounding) {
$date = $date->copy()->round($this->getDateInterval(), $rounding);
$date = $date->avoidMutation()->round($this->getDateInterval(), $rounding);
}
return $date;
@ -1743,13 +1744,13 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
if ($this->recurrences === INF) {
$start = $this->getStartDate();
return $start < $start->copy()->add($this->getDateInterval())
return $start < $start->avoidMutation()->add($this->getDateInterval())
? CarbonImmutable::endOfTime()
: CarbonImmutable::startOfTime();
}
if ($this->filters === [[static::RECURRENCES_FILTER, null]]) {
return $this->getStartDate()->copy()->add(
return $this->getStartDate()->avoidMutation()->add(
$this->getDateInterval()->times(
$this->recurrences - ($this->isStartExcluded() ? 0 : 1)
)
@ -1795,13 +1796,8 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
$range = static::create($range);
}
$thisDates = [$this->getStartDate(), $this->calculateEnd()];
sort($thisDates);
[$start, $end] = $thisDates;
$rangeDates = [$range->getStartDate(), $range->calculateEnd()];
sort($rangeDates);
[$rangeStart, $rangeEnd] = $rangeDates;
[$start, $end] = $this->orderCouple($this->getStartDate(), $this->calculateEnd());
[$rangeStart, $rangeEnd] = $this->orderCouple($range->getStartDate(), $range->calculateEnd());
return $end > $rangeStart && $rangeEnd > $start;
}
@ -2168,6 +2164,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
*
* @return CarbonInterface[]
*/
#[ReturnTypeWillChange]
public function jsonSerialize()
{
return $this->toArray();
@ -2283,7 +2280,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
*/
protected function isCarbonPredicateMethod($callable)
{
return \is_string($callable) && substr($callable, 0, 2) === 'is' &&
return \is_string($callable) && str_starts_with($callable, 'is') &&
(method_exists($this->dateClass, $callable) || ([$this->dateClass, 'hasMacro'])($callable));
}
@ -2384,7 +2381,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
foreach ($this->filters as $tuple) {
$result = \call_user_func(
$tuple[0],
$current->copy(),
$current->avoidMutation(),
$this->key,
$this
);
@ -2493,4 +2490,9 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
? static::instance($period)
: static::create($period, ...$arguments);
}
private function orderCouple($first, $second): array
{
return $first > $second ? [$second, $first] : [$first, $second];
}
}

View File

@ -33,7 +33,7 @@ class CarbonTimeZone extends DateTimeZone
protected static function getDateTimeZoneNameFromMixed($timezone)
{
if (\is_null($timezone)) {
if ($timezone === null) {
return date_default_timezone_get();
}

View File

@ -37,7 +37,7 @@ trait CarbonTypeConverter
return $type;
}
if (strpos($type, '(') !== false) {
if (str_contains($type, '(')) {
return preg_replace('/\(\d+\)/', "($precision)", $type);
}
@ -95,7 +95,7 @@ trait CarbonTypeConverter
return $value;
}
if ($value instanceof DateTimeInterface || $value instanceof CarbonInterface) {
if ($value instanceof DateTimeInterface) {
return $value->format('Y-m-d H:i:s.u');
}

View File

@ -215,7 +215,7 @@ use ReflectionMethod;
* You should rather use the ->settings() method.
* Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
* are available for quarters, years, decade, centuries, millennia (singular and plural forms).
* @method Carbon withTestNow($testNow = null, $callback = null) Temporarily sets a static date to be used within the callback.
* @method mixed withTestNow($testNow = null, $callback = null) Temporarily sets a static date to be used within the callback.
* Using setTestNow to set the date, executing the callback, then
* clearing the test instance.
* /!\ Use this method for unit tests only.
@ -229,7 +229,7 @@ class Factory
protected $settings = [];
public function __construct(array $settings = [], string $className = null)
public function __construct(array $settings = [], ?string $className = null)
{
if ($className) {
$this->className = $className;

View File

@ -214,7 +214,7 @@ use Closure;
* You should rather use the ->settings() method.
* Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
* are available for quarters, years, decade, centuries, millennia (singular and plural forms).
* @method CarbonImmutable withTestNow($testNow = null, $callback = null) Temporarily sets a static date to be used within the callback.
* @method mixed withTestNow($testNow = null, $callback = null) Temporarily sets a static date to be used within the callback.
* Using setTestNow to set the date, executing the callback, then
* clearing the test instance.
* /!\ Use this method for unit tests only.

View File

@ -11,7 +11,7 @@
// @codeCoverageIgnoreStart
if (class_exists('Symfony\\Component\\Translation\\PluralizationRules')) {
\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
}, 'be');
}
// @codeCoverageIgnoreEnd

View File

@ -11,7 +11,7 @@
/*
* Authors:
* - Ankur Group, http://www.ankurbangla.org, http://www.bengalinux.org Taneem Ahmed, Jamil Ahmed taneem@bengalinux.org, jamil@bengalinux.org
* - Ankur Group, Taneem Ahmed, Jamil Ahmed
*/
return array_replace_recursive(require __DIR__.'/bn.php', [
'formats' => [

View File

@ -41,7 +41,7 @@ return [
's' => ':count seg.',
'ago' => 'hai :time',
'from_now' => function ($time) {
if (substr($time, 0, 2) === 'un') {
if (str_starts_with($time, 'un')) {
return "n$time";
}

View File

@ -169,8 +169,8 @@ return [
return $number.'-ე';
},
'months' => ['იანვარს', 'თებერვალს', 'მარტს', 'აპრილის', 'მაისს', 'ივნისს', 'ივლისს', 'აგვისტს', 'სექტემბერს', 'ოქტომბერს', 'ნოემბერს', 'დეკემბერს'],
'months_standalone' => ['იანვარი', 'თებერვალი', 'მარტი', 'აპრილი', 'მაისი', 'ივნისი', 'ივლისი', 'აგვისტო', 'სექტემბერი', 'ოქტომბერი', 'ნოემბერი', 'დეკემბერი'],
'months' => ['იანვარი', 'თებერვალი', 'მარტი', 'აპრილი', 'მაისი', 'ივნისი', 'ივლისი', 'აგვისტო', 'სექტემბერი', 'ოქტომბერი', 'ნოემბერი', 'დეკემბერი'],
'months_standalone' => ['იანვარს', 'თებერვალს', 'მარტს', 'აპრილს', 'მაისს', 'ივნისს', 'ივლისს', 'აგვისტოს', 'სექტემბერს', 'ოქტომბერს', 'ნოემბერს', 'დეკემბერს'],
'months_short' => ['იან', 'თებ', 'მარ', 'აპრ', 'მაი', 'ივნ', 'ივლ', 'აგვ', 'სექ', 'ოქტ', 'ნოე', 'დეკ'],
'months_regexp' => '/(D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
'weekdays' => ['კვირას', 'ორშაბათს', 'სამშაბათს', 'ოთხშაბათს', 'ხუთშაბათს', 'პარასკევს', 'შაბათს'],

View File

@ -69,7 +69,7 @@ return [
'diff_after_tomorrow' => 'overmorgen',
'diff_before_yesterday' => 'eergisteren',
'period_recurrences' => ':count keer',
'period_interval' => function ($interval) {
'period_interval' => function (string $interval = '') {
/** @var string $output */
$output = preg_replace('/^(een|één|1)\s+/', '', $interval);

View File

@ -82,7 +82,7 @@ return [
'weekdays' => ['dimenge', 'diluns', 'dimars', 'dimècres', 'dijòus', 'divendres', 'dissabte'],
'weekdays_short' => ['dg', 'dl', 'dm', 'dc', 'dj', 'dv', 'ds'],
'weekdays_min' => ['dg', 'dl', 'dm', 'dc', 'dj', 'dv', 'ds'],
'ordinal' => function ($number, $period) {
'ordinal' => function ($number, string $period = '') {
$ordinal = [1 => 'èr', 2 => 'nd'][(int) $number] ?? 'en';
// feminine for year, week, hour, minute, second

View File

@ -29,7 +29,7 @@
return [
'year' => ':count rok|:count lata|:count lat',
'a_year' => 'rok|:count lata|:count lat',
'y' => ':count r|:count l',
'y' => ':count r|:count l|:count l',
'month' => ':count miesiąc|:count miesiące|:count miesięcy',
'a_month' => 'miesiąc|:count miesiące|:count miesięcy',
'm' => ':count mies.',

View File

@ -11,7 +11,7 @@
// @codeCoverageIgnoreStart
if (class_exists('Symfony\\Component\\Translation\\PluralizationRules')) {
\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
}, 'sh');
}
// @codeCoverageIgnoreEnd

View File

@ -11,7 +11,7 @@
/*
* Authors:
* - ubuntu Myanmar LoCo Team http://www.ubuntu-mm.net Bone Pyae Sone bone.burma@mail.com
* - ubuntu Myanmar LoCo Team https://ubuntu-mm.net Bone Pyae Sone bone.burma@mail.com
*/
return array_replace_recursive(require __DIR__.'/en.php', [
'formats' => [

View File

@ -11,6 +11,7 @@
namespace Carbon;
use JsonSerializable;
use ReturnTypeWillChange;
class Language implements JsonSerializable
{
@ -332,6 +333,7 @@ class Language implements JsonSerializable
*
* @return string
*/
#[ReturnTypeWillChange]
public function jsonSerialize()
{
return $this->getIsoDescription();

View File

@ -622,7 +622,7 @@ trait Comparison
if (!isset($units[$unit])) {
if (isset($this->$unit)) {
return $this->$unit === $this->resolveCarbon($date)->$unit;
return $this->resolveCarbon($date)->$unit === $this->$unit;
}
if ($this->localStrictModeEnabled ?? static::isStrictModeEnabled()) {
@ -949,7 +949,7 @@ trait Comparison
$tester = trim($tester);
if (preg_match('/^\d+$/', $tester)) {
return $this->year === \intval($tester);
return $this->year === (int) $tester;
}
if (preg_match('/^\d{3,}-\d{1,2}$/', $tester)) {
@ -964,9 +964,9 @@ trait Comparison
/* @var CarbonInterface $max */
$median = static::parse('5555-06-15 12:30:30.555555')->modify($modifier);
$current = $this->copy();
$current = $this->avoidMutation();
/* @var CarbonInterface $other */
$other = $this->copy()->modify($modifier);
$other = $this->avoidMutation()->modify($modifier);
if ($current->eq($other)) {
return true;
@ -1001,7 +1001,7 @@ trait Comparison
];
foreach ($units as $unit => [$minimum, $startUnit]) {
if ($median->$unit === $minimum) {
if ($minimum === $median->$unit) {
$current = $current->startOf($startUnit);
break;

View File

@ -38,7 +38,7 @@ trait Converter
*
* @var string|Closure|null
*/
protected static $toStringFormat = null;
protected static $toStringFormat;
/**
* Reset the format used to the default when type juggling a Carbon instance to a string
@ -324,7 +324,9 @@ trait Converter
*/
public function toIso8601ZuluString($unitPrecision = 'second')
{
return $this->copy()->utc()->rawFormat('Y-m-d\T'.static::getTimeFormatByPrecision($unitPrecision).'\Z');
return $this->avoidMutation()
->utc()
->rawFormat('Y-m-d\T'.static::getTimeFormatByPrecision($unitPrecision).'\Z');
}
/**
@ -452,7 +454,7 @@ trait Converter
*/
public function toRfc7231String()
{
return $this->copy()
return $this->avoidMutation()
->setTimezone('GMT')
->rawFormat(\defined('static::RFC7231_FORMAT') ? static::RFC7231_FORMAT : CarbonInterface::RFC7231_FORMAT);
}
@ -512,7 +514,7 @@ trait Converter
*/
public function toString()
{
return $this->copy()->locale('en')->isoFormat('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
return $this->avoidMutation()->locale('en')->isoFormat('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
}
/**
@ -537,7 +539,7 @@ trait Converter
$yearFormat = $this->year < 0 || $this->year > 9999 ? 'YYYYYY' : 'YYYY';
$tzFormat = $keepOffset ? 'Z' : '[Z]';
$date = $keepOffset ? $this : $this->copy()->utc();
$date = $keepOffset ? $this : $this->avoidMutation()->utc();
return $date->isoFormat("$yearFormat-MM-DD[T]HH:mm:ss.SSSSSS$tzFormat");
}

View File

@ -77,7 +77,7 @@ trait Creator
}
// Work-around for PHP bug https://bugs.php.net/bug.php?id=67127
if (strpos((string) .1, '.') === false) {
if (!str_contains((string) .1, '.')) {
$locale = setlocale(LC_NUMERIC, '0');
setlocale(LC_NUMERIC, 'C');
}
@ -592,7 +592,7 @@ trait Creator
// @codeCoverageIgnoreEnd
if ($originalTz === null) {
return parent::createFromFormat($format, "$time");
return parent::createFromFormat($format, (string) $time);
}
$tz = \is_int($originalTz)
@ -605,7 +605,7 @@ trait Creator
return false;
}
return parent::createFromFormat($format, "$time", $tz);
return parent::createFromFormat($format, (string) $time, $tz);
}
/**

View File

@ -27,6 +27,7 @@ use Closure;
use DateInterval;
use DatePeriod;
use DateTime;
use DateTimeImmutable;
use DateTimeInterface;
use DateTimeZone;
use InvalidArgumentException;
@ -630,7 +631,7 @@ trait Date
*
* @return CarbonTimeZone
*
* @link http://php.net/manual/en/datetime.gettimezone.php
* @link https://php.net/manual/en/datetime.gettimezone.php
*/
#[ReturnTypeWillChange]
public function getTimezone()
@ -683,6 +684,23 @@ trait Date
return clone $this;
}
/**
* Clone the current instance if it's mutable.
*
* This method is convenient to ensure you don't mutate the initial object
* but avoid to make a useless copy of it if it's already immutable.
*
* @return static
*/
public function avoidMutation(): self
{
if ($this instanceof DateTimeImmutable) {
return $this;
}
return clone $this;
}
/**
* Returns a present instance in the same timezone.
*
@ -774,7 +792,7 @@ trait Date
public function carbonize($date = null)
{
if ($date instanceof DateInterval) {
return $this->copy()->add($date);
return $this->avoidMutation()->add($date);
}
if ($date instanceof DatePeriod || $date instanceof CarbonPeriod) {
@ -872,7 +890,7 @@ trait Date
switch (true) {
case isset($formats[$name]):
$format = $formats[$name];
$method = substr($format, 0, 1) === '%' ? 'formatLocalized' : 'rawFormat';
$method = str_starts_with($format, '%') ? 'formatLocalized' : 'rawFormat';
$value = $this->$method($format);
return is_numeric($value) ? (int) $value : $value;
@ -927,11 +945,11 @@ trait Date
// @property-read int 51 through 53
case $name === 'weeksInYear':
return (int) $this->weeksInYear();
return $this->weeksInYear();
// @property-read int 51 through 53
case $name === 'isoWeeksInYear':
return (int) $this->isoWeeksInYear();
return $this->isoWeeksInYear();
// @property-read int 1 through 5
case $name === 'weekOfMonth':
@ -939,7 +957,7 @@ trait Date
// @property-read int 1 through 5
case $name === 'weekNumberInMonth':
return (int) ceil(($this->day + $this->copy()->startOfMonth()->dayOfWeekIso - 1) / static::DAYS_PER_WEEK);
return (int) ceil(($this->day + $this->avoidMutation()->startOfMonth()->dayOfWeekIso - 1) / static::DAYS_PER_WEEK);
// @property-read int 0 through 6
case $name === 'firstWeekDay':
@ -951,7 +969,7 @@ trait Date
// @property int 1 through 366
case $name === 'dayOfYear':
return 1 + \intval($this->rawFormat('z'));
return 1 + (int) ($this->rawFormat('z'));
// @property-read int 365 or 366
case $name === 'daysInYear':
@ -1013,7 +1031,7 @@ trait Date
// @property-read bool checks if the timezone is local, true if local, false otherwise
case $name === 'local':
return $this->getOffset() === $this->copy()->setTimezone(date_default_timezone_get())->getOffset();
return $this->getOffset() === $this->avoidMutation()->setTimezone(date_default_timezone_get())->getOffset();
// @property-read bool checks if the timezone is UTC, true if UTC, false otherwise
case $name === 'utc':
@ -1114,7 +1132,7 @@ trait Date
case 'microseconds':
case 'microsecond':
case 'micro':
if (substr($name, 0, 5) === 'milli') {
if (str_starts_with($name, 'milli')) {
$value *= 1000;
}
@ -1309,7 +1327,7 @@ trait Date
{
$dayOfYear = $this->dayOfYear;
return \is_null($value) ? $dayOfYear : $this->addDays($value - $dayOfYear);
return $value === null ? $dayOfYear : $this->addDays($value - $dayOfYear);
}
/**
@ -1321,9 +1339,9 @@ trait Date
*/
public function weekday($value = null)
{
$dayOfWeek = ($this->dayOfWeek + 7 - \intval($this->getTranslationMessage('first_day_of_week') ?? 0)) % 7;
$dayOfWeek = ($this->dayOfWeek + 7 - (int) ($this->getTranslationMessage('first_day_of_week') ?? 0)) % 7;
return \is_null($value) ? $dayOfWeek : $this->addDays($value - $dayOfWeek);
return $value === null ? $dayOfWeek : $this->addDays($value - $dayOfWeek);
}
/**
@ -1337,7 +1355,7 @@ trait Date
{
$dayOfWeekIso = $this->dayOfWeekIso;
return \is_null($value) ? $dayOfWeekIso : $this->addDays($value - $dayOfWeekIso);
return $value === null ? $dayOfWeekIso : $this->addDays($value - $dayOfWeekIso);
}
/**
@ -1352,11 +1370,11 @@ trait Date
public function setUnitNoOverflow($valueUnit, $value, $overflowUnit)
{
try {
$original = $this->copy();
$original = $this->avoidMutation();
/** @var static $date */
$date = $this->$valueUnit($value);
$end = $original->copy()->endOf($overflowUnit);
$start = $original->copy()->startOf($overflowUnit);
$end = $original->avoidMutation()->endOf($overflowUnit);
$start = $original->avoidMutation()->startOf($overflowUnit);
if ($date < $start) {
$date = $date->setDateTimeFrom($start);
} elseif ($date > $end) {
@ -1509,7 +1527,7 @@ trait Date
*/
public function setTimeFromTimeString($time)
{
if (strpos($time, ':') === false) {
if (!str_contains($time, ':')) {
$time .= ':0';
}
@ -1791,7 +1809,7 @@ trait Date
/**
* Format the instance with the current locale. You can set the current
* locale using setlocale() http://php.net/setlocale.
* locale using setlocale() https://php.net/setlocale.
*
* @param string $format
*
@ -1900,7 +1918,7 @@ trait Date
's' => 'second',
'ss' => ['getPaddedUnit', ['second']],
'S' => function (CarbonInterface $date) {
return \strval((string) floor($date->micro / 100000));
return (string) floor($date->micro / 100000);
},
'SS' => function (CarbonInterface $date) {
return str_pad((string) floor($date->micro / 10000), 2, '0', STR_PAD_LEFT);
@ -1999,15 +2017,15 @@ trait Date
*
* @return string
*/
public function ordinal(string $key, string $period = null): string
public function ordinal(string $key, ?string $period = null): string
{
$number = $this->$key;
$result = $this->translate('ordinal', [
':number' => $number,
':period' => $period,
':period' => (string) $period,
]);
return \strval($result === 'ordinal' ? $number : $result);
return (string) ($result === 'ordinal' ? $number : $result);
}
/**
@ -2070,7 +2088,7 @@ trait Date
*
* @return string
*/
public function isoFormat(string $format, string $originalFormat = null): string
public function isoFormat(string $format, ?string $originalFormat = null): string
{
$result = '';
$length = mb_strlen($format);
@ -2149,7 +2167,7 @@ trait Date
}
$format = mb_substr($format, 0, $i).$sequence.mb_substr($format, $i + mb_strlen($code));
$i += mb_strlen("$sequence") - 1;
$i += mb_strlen((string) $sequence) - 1;
$length = mb_strlen($format);
$char = $sequence;
}
@ -2179,7 +2197,7 @@ trait Date
'S' => function ($date) {
$day = $date->rawFormat('j');
return str_replace("$day", '', $date->isoFormat('Do'));
return str_replace((string) $day, '', $date->isoFormat('Do'));
},
'w' => true,
'z' => true,
@ -2219,7 +2237,7 @@ trait Date
}
/**
* Format as ->format() do (using date replacements patterns from http://php.net/manual/fr/function.date.php)
* Format as ->format() do (using date replacements patterns from https://php.net/manual/en/function.date.php)
* but translate words whenever possible (months, day names, etc.) using the current locale.
*
* @param string $format
@ -2519,7 +2537,7 @@ trait Date
$unit = rtrim($method, 's');
if (substr($unit, 0, 2) === 'is') {
if (str_starts_with($unit, 'is')) {
$word = substr($unit, 2);
if (\in_array($word, static::$days)) {
@ -2557,7 +2575,7 @@ trait Date
if ($action === 'add' || $action === 'sub') {
$unit = substr($unit, 3);
if (substr($unit, 0, 4) === 'Real') {
if (str_starts_with($unit, 'Real')) {
$unit = static::singularUnit(substr($unit, 4));
return $this->{"${action}RealUnit"}($unit, ...$parameters);
@ -2599,7 +2617,7 @@ trait Date
}
}
if (substr($unit, 0, 9) === 'isCurrent') {
if (str_starts_with($unit, 'isCurrent')) {
try {
return $this->isCurrentUnit(strtolower(substr($unit, 9)));
} catch (BadComparisonUnitException | BadMethodCallException $exception) {
@ -2607,7 +2625,7 @@ trait Date
}
}
if (substr($method, -5) === 'Until') {
if (str_ends_with($method, 'Until')) {
try {
$unit = static::singularUnit(substr($method, 0, -5));

View File

@ -121,7 +121,17 @@ trait Difference
#[ReturnTypeWillChange]
public function diff($date = null, $absolute = false)
{
return parent::diff($this->resolveCarbon($date), (bool) $absolute);
$other = $this->resolveCarbon($date);
// Can be removed if https://github.com/derickr/timelib/pull/110
// is merged
// @codeCoverageIgnoreStart
if (version_compare(PHP_VERSION, '8.1.0-dev', '>=') && $other->tz !== $this->tz) {
$other = $other->avoidMutation()->tz($this->tz);
}
// @codeCoverageIgnoreEnd
return parent::diff($other, (bool) $absolute);
}
/**
@ -540,14 +550,14 @@ trait Difference
}
$monthsDiff = $start->diffInMonths($end);
/** @var Carbon|CarbonImmutable $floorEnd */
$floorEnd = $start->copy()->addMonths($monthsDiff);
$floorEnd = $start->avoidMutation()->addMonths($monthsDiff);
if ($floorEnd >= $end) {
return $sign * $monthsDiff;
}
/** @var Carbon|CarbonImmutable $startOfMonthAfterFloorEnd */
$startOfMonthAfterFloorEnd = $floorEnd->copy()->addMonth()->startOfMonth();
$startOfMonthAfterFloorEnd = $floorEnd->avoidMutation()->addMonth()->startOfMonth();
if ($startOfMonthAfterFloorEnd > $end) {
return $sign * ($monthsDiff + $floorEnd->floatDiffInDays($end) / $floorEnd->daysInMonth);
@ -575,14 +585,14 @@ trait Difference
}
$yearsDiff = $start->diffInYears($end);
/** @var Carbon|CarbonImmutable $floorEnd */
$floorEnd = $start->copy()->addYears($yearsDiff);
$floorEnd = $start->avoidMutation()->addYears($yearsDiff);
if ($floorEnd >= $end) {
return $sign * $yearsDiff;
}
/** @var Carbon|CarbonImmutable $startOfYearAfterFloorEnd */
$startOfYearAfterFloorEnd = $floorEnd->copy()->addYear()->startOfYear();
$startOfYearAfterFloorEnd = $floorEnd->avoidMutation()->addYear()->startOfYear();
if ($startOfYearAfterFloorEnd > $end) {
return $sign * ($yearsDiff + $floorEnd->floatDiffInDays($end) / $floorEnd->daysInYear);
@ -641,7 +651,7 @@ trait Difference
public function floatDiffInRealDays($date = null, $absolute = true)
{
$date = $this->resolveUTC($date);
$utc = $this->copy()->utc();
$utc = $this->avoidMutation()->utc();
$hoursDiff = $utc->floatDiffInRealHours($date, $absolute);
return ($hoursDiff < 0 ? -1 : 1) * $utc->diffInDays($date) + fmod($hoursDiff, static::HOURS_PER_DAY) / static::HOURS_PER_DAY;
@ -679,14 +689,14 @@ trait Difference
}
$monthsDiff = $start->diffInMonths($end);
/** @var Carbon|CarbonImmutable $floorEnd */
$floorEnd = $start->copy()->addMonths($monthsDiff);
$floorEnd = $start->avoidMutation()->addMonths($monthsDiff);
if ($floorEnd >= $end) {
return $sign * $monthsDiff;
}
/** @var Carbon|CarbonImmutable $startOfMonthAfterFloorEnd */
$startOfMonthAfterFloorEnd = $floorEnd->copy()->addMonth()->startOfMonth();
$startOfMonthAfterFloorEnd = $floorEnd->avoidMutation()->addMonth()->startOfMonth();
if ($startOfMonthAfterFloorEnd > $end) {
return $sign * ($monthsDiff + $floorEnd->floatDiffInRealDays($end) / $floorEnd->daysInMonth);
@ -714,14 +724,14 @@ trait Difference
}
$yearsDiff = $start->diffInYears($end);
/** @var Carbon|CarbonImmutable $floorEnd */
$floorEnd = $start->copy()->addYears($yearsDiff);
$floorEnd = $start->avoidMutation()->addYears($yearsDiff);
if ($floorEnd >= $end) {
return $sign * $yearsDiff;
}
/** @var Carbon|CarbonImmutable $startOfYearAfterFloorEnd */
$startOfYearAfterFloorEnd = $floorEnd->copy()->addYear()->startOfYear();
$startOfYearAfterFloorEnd = $floorEnd->avoidMutation()->addYear()->startOfYear();
if ($startOfYearAfterFloorEnd > $end) {
return $sign * ($yearsDiff + $floorEnd->floatDiffInRealDays($end) / $floorEnd->daysInYear);
@ -737,7 +747,7 @@ trait Difference
*/
public function secondsSinceMidnight()
{
return $this->diffInSeconds($this->copy()->startOfDay());
return $this->diffInSeconds($this->avoidMutation()->startOfDay());
}
/**
@ -747,7 +757,7 @@ trait Difference
*/
public function secondsUntilEndOfDay()
{
return $this->diffInSeconds($this->copy()->endOfDay());
return $this->diffInSeconds($this->avoidMutation()->endOfDay());
}
/**
@ -1106,9 +1116,9 @@ trait Difference
public function calendar($referenceTime = null, array $formats = [])
{
/** @var CarbonInterface $current */
$current = $this->copy()->startOfDay();
$current = $this->avoidMutation()->startOfDay();
/** @var CarbonInterface $other */
$other = $this->resolveCarbon($referenceTime)->copy()->setTimezone($this->getTimezone())->startOfDay();
$other = $this->resolveCarbon($referenceTime)->avoidMutation()->setTimezone($this->getTimezone())->startOfDay();
$diff = $other->diffInDays($current, false);
$format = $diff < -6 ? 'sameElse' : (
$diff < -1 ? 'lastWeek' : (
@ -1126,6 +1136,6 @@ trait Difference
$format = $format($current, $other) ?? '';
}
return $this->isoFormat(\strval($format));
return $this->isoFormat((string) $format);
}
}

View File

@ -64,7 +64,7 @@ trait IntervalStep
$carbonDate = $dateTime instanceof CarbonInterface ? $dateTime : $this->resolveCarbon($dateTime);
if ($this->step) {
return $carbonDate->setDateTimeFrom(($this->step)($carbonDate->copy(), $negated));
return $carbonDate->setDateTimeFrom(($this->step)($carbonDate->avoidMutation(), $negated));
}
if ($negated) {

View File

@ -168,7 +168,7 @@ trait Localization
*
* @return string
*/
public static function getTranslationMessageWith($translator, string $key, string $locale = null, string $default = null)
public static function getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null)
{
if (!($translator instanceof TranslatorBagInterface && $translator instanceof TranslatorInterface)) {
throw new InvalidTypeException(
@ -196,7 +196,7 @@ trait Localization
*
* @return string
*/
public function getTranslationMessage(string $key, string $locale = null, string $default = null, $translator = null)
public function getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null)
{
return static::getTranslationMessageWith($translator ?: $this->getLocalTranslator(), $key, $locale, $default);
}
@ -239,12 +239,12 @@ trait Localization
*
* @param string $key
* @param array $parameters
* @param null $number
* @param string|int|float|null $number
* @param \Symfony\Component\Translation\TranslatorInterface $translator
*
* @return string
*/
public function translate(string $key, array $parameters = [], $number = null, TranslatorInterface $translator = null, bool $altNumbers = false): string
public function translate(string $key, array $parameters = [], $number = null, ?TranslatorInterface $translator = null, bool $altNumbers = false): string
{
$translation = static::translateWith($translator ?: $this->getLocalTranslator(), $key, $parameters, $number);
@ -302,7 +302,7 @@ trait Localization
return $result;
}
return "$number";
return (string) $number;
}
/**

View File

@ -224,11 +224,11 @@ trait Modifiers
*/
public function nthOfMonth($nth, $dayOfWeek)
{
$date = $this->copy()->firstOfMonth();
$date = $this->avoidMutation()->firstOfMonth();
$check = $date->rawFormat('Y-m');
$date = $date->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
return $date->rawFormat('Y-m') === $check ? $this->modify("$date") : false;
return $date->rawFormat('Y-m') === $check ? $this->modify((string) $date) : false;
}
/**
@ -274,12 +274,12 @@ trait Modifiers
*/
public function nthOfQuarter($nth, $dayOfWeek)
{
$date = $this->copy()->day(1)->month($this->quarter * static::MONTHS_PER_QUARTER);
$date = $this->avoidMutation()->day(1)->month($this->quarter * static::MONTHS_PER_QUARTER);
$lastMonth = $date->month;
$year = $date->year;
$date = $date->firstOfQuarter()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
return ($lastMonth < $date->month || $year !== $date->year) ? false : $this->modify("$date");
return ($lastMonth < $date->month || $year !== $date->year) ? false : $this->modify((string) $date);
}
/**
@ -325,9 +325,9 @@ trait Modifiers
*/
public function nthOfYear($nth, $dayOfWeek)
{
$date = $this->copy()->firstOfYear()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
$date = $this->avoidMutation()->firstOfYear()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
return $this->year === $date->year ? $this->modify("$date") : false;
return $this->year === $date->year ? $this->modify((string) $date) : false;
}
/**
@ -454,7 +454,7 @@ trait Modifiers
{
return $this->modify(preg_replace_callback('/^(next|previous|last)\s+(\d{1,2}(h|am|pm|:\d{1,2}(:\d{1,2})?))$/i', function ($match) {
$match[2] = str_replace('h', ':00', $match[2]);
$test = $this->copy()->modify($match[2]);
$test = $this->avoidMutation()->modify($match[2]);
$method = $match[1] === 'next' ? 'lt' : 'gt';
$match[1] = $test->$method($this) ? $match[1].' day' : 'today';

View File

@ -17,5 +17,5 @@ trait ObjectInitialisation
*
* @var string
*/
protected $constructedObjectId = null;
protected $constructedObjectId;
}

View File

@ -151,21 +151,21 @@ trait Options
*
* @var string|callable|null
*/
protected static $formatFunction = null;
protected static $formatFunction;
/**
* Function to call instead of createFromFormat.
*
* @var string|callable|null
*/
protected static $createFromFormatFunction = null;
protected static $createFromFormatFunction;
/**
* Function to call instead of parse.
*
* @var string|callable|null
*/
protected static $parseFunction = null;
protected static $parseFunction;
/**
* Indicates if months should be calculated with overflow.
@ -173,7 +173,7 @@ trait Options
*
* @var bool|null
*/
protected $localMonthsOverflow = null;
protected $localMonthsOverflow;
/**
* Indicates if years should be calculated with overflow.
@ -181,7 +181,7 @@ trait Options
*
* @var bool|null
*/
protected $localYearsOverflow = null;
protected $localYearsOverflow;
/**
* Indicates if the strict mode is in use.
@ -189,49 +189,49 @@ trait Options
*
* @var bool|null
*/
protected $localStrictModeEnabled = null;
protected $localStrictModeEnabled;
/**
* Options for diffForHumans and forHumans methods.
*
* @var bool|null
*/
protected $localHumanDiffOptions = null;
protected $localHumanDiffOptions;
/**
* Format to use on string cast.
*
* @var string|null
*/
protected $localToStringFormat = null;
protected $localToStringFormat;
/**
* Format to use on JSON serialization.
*
* @var string|null
*/
protected $localSerializer = null;
protected $localSerializer;
/**
* Instance-specific macros.
*
* @var array|null
*/
protected $localMacros = null;
protected $localMacros;
/**
* Instance-specific generic macros.
*
* @var array|null
*/
protected $localGenericMacros = null;
protected $localGenericMacros;
/**
* Function to call instead of format.
*
* @var string|callable|null
*/
protected $localFormatFunction = null;
protected $localFormatFunction;
/**
* @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
@ -449,7 +449,7 @@ trait Options
protected function addExtraDebugInfos(&$infos): void
{
if ($this instanceof CarbonInterface || $this instanceof DateTimeInterface) {
if ($this instanceof DateTimeInterface) {
try {
if (!isset($infos['date'])) {
$infos['date'] = $this->format(CarbonInterface::MOCK_DATETIME_FORMAT);

View File

@ -194,7 +194,10 @@ trait Rounding
*/
public function roundWeek($weekStartsAt = null)
{
return $this->closest($this->copy()->floorWeek($weekStartsAt), $this->copy()->ceilWeek($weekStartsAt));
return $this->closest(
$this->avoidMutation()->floorWeek($weekStartsAt),
$this->avoidMutation()->ceilWeek($weekStartsAt)
);
}
/**
@ -219,7 +222,7 @@ trait Rounding
public function ceilWeek($weekStartsAt = null)
{
if ($this->isMutable()) {
$startOfWeek = $this->copy()->startOfWeek($weekStartsAt);
$startOfWeek = $this->avoidMutation()->startOfWeek($weekStartsAt);
return $startOfWeek != $this ?
$this->startOfWeek($weekStartsAt)->addWeek() :
@ -230,6 +233,6 @@ trait Rounding
return $startOfWeek != $this ?
$startOfWeek->addWeek() :
$this->copy();
$this->avoidMutation();
}
}

View File

@ -12,6 +12,7 @@ namespace Carbon\Traits;
use Carbon\Exceptions\InvalidFormatException;
use ReturnTypeWillChange;
use Throwable;
/**
* Trait Serialization.
@ -53,7 +54,15 @@ trait Serialization
*
* @var string|null
*/
protected $dumpLocale = null;
protected $dumpLocale;
/**
* Embed date properties to dump in a dedicated variables so it won't overlap native
* DateTime ones.
*
* @var array|null
*/
protected $dumpDateProperties;
/**
* Return a serialized string of the instance.
@ -76,7 +85,7 @@ trait Serialization
*/
public static function fromSerialized($value)
{
$instance = @unserialize("$value");
$instance = @unserialize((string) $value);
if (!$instance instanceof static) {
throw new InvalidFormatException("Invalid serialized value: $value");
@ -114,7 +123,7 @@ trait Serialization
*/
public function __sleep()
{
$properties = $this->dumpProperties;
$properties = $this->getSleepProperties();
if ($this->localTranslator ?? null) {
$properties[] = 'dumpLocale';
@ -131,7 +140,15 @@ trait Serialization
public function __wakeup()
{
if (get_parent_class() && method_exists(parent::class, '__wakeup')) {
// @codeCoverageIgnoreStart
try {
parent::__wakeup();
} catch (Throwable $exception) {
// FatalError occurs when calling msgpack_unpack() in PHP 7.4 or later.
['date' => $date, 'timezone' => $timezone] = $this->dumpDateProperties;
parent::__construct($date, unserialize($timezone));
}
// @codeCoverageIgnoreEnd
}
$this->constructedObjectId = spl_object_hash($this);
@ -149,6 +166,7 @@ trait Serialization
*
* @return array|string
*/
#[ReturnTypeWillChange]
public function jsonSerialize()
{
$serializer = $this->localSerializer ?? static::$serializer;
@ -194,4 +212,26 @@ trait Serialization
return $this;
}
private function getSleepProperties(): array
{
$properties = $this->dumpProperties;
// @codeCoverageIgnoreStart
if (!\extension_loaded('msgpack')) {
return $properties;
}
if (isset($this->constructedObjectId)) {
$this->dumpDateProperties = [
'date' => $this->format('Y-m-d H:i:s.u'),
'timezone' => serialize($this->timezone ?? null),
];
$properties[] = 'dumpDateProperties';
}
return $properties;
// @codeCoverageIgnoreEnd
}
}

View File

@ -63,12 +63,16 @@ trait Test
*
* @param Closure|static|string|false|null $testNow real or mock Carbon instance
* @param Closure|null $callback
*
* @return mixed
*/
public static function withTestNow($testNow = null, $callback = null)
{
static::setTestNow($testNow);
$callback();
$result = $callback();
static::setTestNow();
return $result;
}
/**

View File

@ -45,6 +45,7 @@ trait Timestamp
$delta = floor($decimal / static::MICROSECONDS_PER_SECOND);
$integer += $delta;
$decimal -= $delta * static::MICROSECONDS_PER_SECOND;
$decimal = str_pad((string) $decimal, 6, '0', STR_PAD_LEFT);
return static::rawCreateFromFormat('U u', "$integer $decimal");
}
@ -136,6 +137,16 @@ trait Timestamp
return $this->getPreciseTimestamp(3);
}
/**
* Returns the timestamp with millisecond precision.
*
* @return int
*/
public function getTimestampMs()
{
return (int) $this->getPreciseTimestamp(3);
}
/**
* @alias getTimestamp
*
@ -166,15 +177,15 @@ trait Timestamp
$numbers = number_format($numbers, $decimals, '.', '');
}
$sign = substr($numbers, 0, 1) === '-' ? -1 : 1;
$sign = str_starts_with($numbers, '-') ? -1 : 1;
$integer = 0;
$decimal = 0;
foreach (preg_split('`[^0-9.]+`', $numbers) as $chunk) {
[$integerPart, $decimalPart] = explode('.', "$chunk.");
$integer += \intval($integerPart);
$decimal += \floatval("0.$decimalPart");
$integer += (int) $integerPart;
$decimal += (float) ("0.$decimalPart");
}
$overflow = floor($decimal);

View File

@ -48,7 +48,7 @@ trait Units
$seconds = (int) floor($diff / static::MICROSECONDS_PER_SECOND);
$time += $seconds;
$diff -= $seconds * static::MICROSECONDS_PER_SECOND;
$microtime = str_pad("$diff", 6, '0', STR_PAD_LEFT);
$microtime = str_pad((string) $diff, 6, '0', STR_PAD_LEFT);
$tz = $this->tz;
return $this->tz('UTC')->modify("@$time.$microtime")->tz($tz);
@ -201,6 +201,21 @@ trait Units
$unit = CarbonInterval::make($unit);
}
// Can be removed if https://bugs.php.net/bug.php?id=81106
// is fixed
// @codeCoverageIgnoreStart
if (
$unit instanceof DateInterval &&
version_compare(PHP_VERSION, '8.1.0-dev', '>=') &&
($unit->f < 0 || $unit->f >= 1)
) {
$unit = clone $unit;
$seconds = floor($unit->f);
$unit->f -= $seconds;
$unit->s += (int) $seconds;
}
// @codeCoverageIgnoreEnd
if ($unit instanceof CarbonConverterInterface) {
return $this->resolveCarbon($unit->convertDate($this, false));
}
@ -233,8 +248,8 @@ trait Units
{
$date = $this;
if (!is_numeric($value) || !\floatval($value)) {
return $date->isMutable() ? $date : $date->copy();
if (!is_numeric($value) || !(float) $value) {
return $date->isMutable() ? $date : $date->avoidMutation();
}
$metaUnits = [
@ -377,7 +392,7 @@ trait Units
[$value, $unit] = [$unit, $value];
}
return $this->addUnit($unit, -\floatval($value), $overflow);
return $this->addUnit($unit, -(float) $value, $overflow);
}
/**

View File

@ -27,7 +27,7 @@ namespace Carbon\Traits;
* @method static addWeeks(int $weeks = 1)
* @method static copy()
* @method static dayOfYear(int $dayOfYear)
* @method string getTranslationMessage(string $key, string $locale = null, string $default = null, $translator = null)
* @method string getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null)
* @method static next(int|string $day = null)
* @method static startOfWeek(int $day = 1)
* @method static subWeeks(int $weeks = 1)
@ -75,7 +75,7 @@ trait Week
$year = (int) round($year);
if ($this->weekYear(null, $dayOfWeek, $dayOfYear) === $year) {
return $this->copy();
return $this->avoidMutation();
}
$week = $this->week(null, $dayOfWeek, $dayOfYear);
@ -103,13 +103,13 @@ trait Week
$year = $this->year;
$day = $this->dayOfYear;
$date = $this->copy()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
$date = $this->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
if ($date->year === $year && $day < $date->dayOfYear) {
return $year - 1;
}
$date = $this->copy()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
$date = $this->avoidMutation()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
if ($date->year === $year && $day >= $date->dayOfYear) {
return $year + 1;
@ -151,12 +151,12 @@ trait Week
$dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0;
$dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1;
$year = $this->year;
$start = $this->copy()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
$start = $this->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
$startDay = $start->dayOfYear;
if ($start->year !== $year) {
$startDay -= $start->daysInYear;
}
$end = $this->copy()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
$end = $this->avoidMutation()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
$endDay = $end->dayOfYear;
if ($end->year !== $year) {
$endDay += $this->daysInYear;
@ -186,8 +186,8 @@ trait Week
return $date->addWeeks(round($week) - $this->week(null, $dayOfWeek, $dayOfYear));
}
$start = $date->copy()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
$end = $date->copy()->startOfWeek($dayOfWeek);
$start = $date->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
$end = $date->avoidMutation()->startOfWeek($dayOfWeek);
if ($start > $end) {
$start = $start->subWeeks(26)->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
}

View File

@ -148,7 +148,7 @@ class Translator extends Translation\Translator
*/
public function trans($id, array $parameters = [], $domain = null, $locale = null)
{
if (null === $domain) {
if ($domain === null) {
$domain = 'messages';
}
@ -326,7 +326,7 @@ class Translator extends Translation\Translator
$previousLocale = $this->getLocale();
if ($previousLocale === $locale) {
if ($previousLocale === $locale && isset($this->messages[$locale])) {
return true;
}
@ -355,7 +355,7 @@ class Translator extends Translation\Translator
}
// If subtag (ex: en_CA) first load the macro (ex: en) to have a fallback
if (strpos($locale, '_') !== false &&
if (str_contains($locale, '_') &&
$this->loadMessagesFromFile($macroLocale = preg_replace('/^([^_]+).*$/', '$1', $locale))
) {
parent::setLocale($macroLocale);

View File

@ -0,0 +1,60 @@
name: CI
on: [push]
jobs:
tests:
runs-on: ubuntu-latest
strategy:
matrix:
php: [7.2, 7.3, 7.4, 8.0]
dependency-version: [prefer-lowest, prefer-stable]
steps:
- name: Checkout code
uses: actions/checkout@v1
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: mailparse
coverage: none
- name: Install dependencies
run: composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction --no-suggest --no-progress
- name: Execute tests
run: vendor/bin/phpunit
php-cs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v1
- name: Install dependencies
run: composer update --no-progress --ignore-platform-reqs
- name: Execute phpcs
run: vendor/bin/phpcs src tests --standard=psr2
coverage:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v1
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
extensions: mailparse
- name: Install dependencies
run: composer update --prefer-dist --no-interaction --no-suggest --no-progress
- name: Execute code coverage
run: |
vendor/bin/phpunit --coverage-clover=coverage.xml --whitelist src
bash <(curl -s https://codecov.io/bash) -t ${{ secrets.COVERALLS_REPO_TOKEN }}

View File

@ -1,6 +1,6 @@
# php-mime-mail-parser
A fully tested email parser for PHP 7.1+ (mailparse extension wrapper).
A fully tested email parser for PHP 7.2+ (mailparse extension wrapper).
It's the most effective php email parser around in terms of performance, foreign character encoding, attachment handling, and ease of use.
Internet Message Format RFC [822](https://tools.ietf.org/html/rfc822), [2822](https://tools.ietf.org/html/rfc2822), [5322](https://tools.ietf.org/html/rfc5322).
@ -23,7 +23,7 @@ Yes. All known issues have been reproduced, fixed and tested.
We use GitHub Actions, Codecov, Codacy to help ensure code quality. You can see real-time statistics below:
[![Actions Status](https://wdp9fww0r9.execute-api.us-west-2.amazonaws.com/production/badge/php-mime-mail-parser/php-mime-mail-parser?style=flat-square)](https://wdp9fww0r9.execute-api.us-west-2.amazonaws.com/production/results/php-mime-mail-parser/php-mime-mail-parser)
[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fphp-mime-mail-parser%2Fphp-mime-mail-parser%2Fbadge%3Fref%3Dmaster&style=flat-square)](https://actions-badge.atrox.dev/php-mime-mail-parser/php-mime-mail-parser/goto?ref=master)
[![Coverage](https://img.shields.io/codecov/c/gh/php-mime-mail-parser/php-mime-mail-parser?style=flat-square)](https://codecov.io/gh/php-mime-mail-parser/php-mime-mail-parser)
[![Code Quality](https://img.shields.io/codacy/grade/4e0e44fee21147ddbdd18ff976251875?style=flat-square)](https://app.codacy.com/app/php-mime-mail-parser/php-mime-mail-parser)
@ -40,9 +40,9 @@ To install the latest version of PHP MIME Mail Parser, run the command below:
The following versions of PHP are supported:
* PHP 7.1
* PHP 7.2
* PHP 7.3
* PHP 7.4
Previous Versions:
@ -53,6 +53,7 @@ Previous Versions:
| PHP 5.5 | php-mime-mail-parser 2.11.1 |
| PHP 5.6 | php-mime-mail-parser 3.0.4 |
| PHP 7.0 | php-mime-mail-parser 3.0.4 |
| PHP 7.1 | php-mime-mail-parser 5.0.5 |
Make sure you have the mailparse extension (http://php.net/manual/en/book.mailparse.php) properly installed. The command line `php -m | grep mailparse` need to return "mailparse".

View File

@ -1,7 +1,7 @@
{
"name": "php-mime-mail-parser/php-mime-mail-parser",
"type": "library",
"description": "A fully tested email parser for PHP 7.1+ (mailparse extension wrapper).",
"description": "A fully tested email parser for PHP 7.2+ (mailparse extension wrapper).",
"keywords": ["mime", "mail", "mailparse", "MimeMailParser", "parser", "php"],
"homepage": "https://github.com/php-mime-mail-parser/php-mime-mail-parser",
"license": "MIT",
@ -42,14 +42,13 @@
"url":"https://github.com/php-mime-mail-parser/php-mime-mail-parser.git"
},
"require": {
"php": "^7.1",
"php": "^7.2|^8.0",
"ext-mailparse": "*"
},
"require-dev": {
"phpunit/phpunit": "^7.0",
"phpunit/php-token-stream": "^3.0",
"php-coveralls/php-coveralls": "^2.1",
"squizlabs/php_codesniffer": "^3.4"
"phpunit/phpunit": "^8.0",
"php-coveralls/php-coveralls": "^2.2",
"squizlabs/php_codesniffer": "^3.5"
},
"replace": {
"exorus/php-mime-mail-parser": "*",

View File

@ -69,14 +69,15 @@ final class Mbstring
{
public const MB_CASE_FOLD = \PHP_INT_MAX;
private static $encodingList = ['ASCII', 'UTF-8'];
private static $language = 'neutral';
private static $internalEncoding = 'UTF-8';
private static $caseFold = [
private const CASE_FOLD = [
['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"],
['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'],
];
private static $encodingList = ['ASCII', 'UTF-8'];
private static $language = 'neutral';
private static $internalEncoding = 'UTF-8';
public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
{
if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
@ -300,7 +301,7 @@ final class Mbstring
$map = $upper;
} else {
if (self::MB_CASE_FOLD === $mode) {
$s = str_replace(self::$caseFold[0], self::$caseFold[1], $s);
$s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s);
}
static $lower = null;

View File

@ -16,7 +16,7 @@ This component provides features added to PHP 8.0 core:
- [`get_resource_id`](https://php.net/get_resource_id)
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).
License
=======

View File

@ -26,13 +26,13 @@ if (!function_exists('preg_last_error_msg')) {
function preg_last_error_msg(): string { return p\Php80::preg_last_error_msg(); }
}
if (!function_exists('str_contains')) {
function str_contains(string $haystack, string $needle): bool { return p\Php80::str_contains($haystack, $needle); }
function str_contains(?string $haystack, ?string $needle): bool { return p\Php80::str_contains($haystack ?? '', $needle ?? ''); }
}
if (!function_exists('str_starts_with')) {
function str_starts_with(string $haystack, string $needle): bool { return p\Php80::str_starts_with($haystack, $needle); }
function str_starts_with(?string $haystack, ?string $needle): bool { return p\Php80::str_starts_with($haystack ?? '', $needle ?? ''); }
}
if (!function_exists('str_ends_with')) {
function str_ends_with(string $haystack, string $needle): bool { return p\Php80::str_ends_with($haystack, $needle); }
function str_ends_with(?string $haystack, ?string $needle): bool { return p\Php80::str_ends_with($haystack ?? '', $needle ?? ''); }
}
if (!function_exists('get_debug_type')) {
function get_debug_type($value): string { return p\Php80::get_debug_type($value); }

View File

@ -94,13 +94,13 @@ EOF
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$provider = $this->providers->get($input->getArgument('provider'));
if (!$this->enabledLocales) {
throw new InvalidArgumentException('You must define "framework.translator.enabled_locales" or "framework.translator.providers.%s.locales" config key in order to work with translation providers.');
throw new InvalidArgumentException(sprintf('You must define "framework.translator.enabled_locales" or "framework.translator.providers.%s.locales" config key in order to work with translation providers.', parse_url($provider, \PHP_URL_SCHEME)));
}
$io = new SymfonyStyle($input, $output);
$provider = $this->providers->get($input->getArgument('provider'));
$domains = $input->getOption('domains');
$locales = $input->getOption('locales');
$force = $input->getOption('force');

View File

@ -64,6 +64,9 @@ class TranslatorPathsPass extends AbstractRecursivePass
foreach ($this->paths as $class => $_) {
if (($r = $container->getReflectionClass($class)) && !$r->isInterface()) {
$paths[] = $r->getFileName();
foreach ($r->getTraits() as $trait) {
$paths[] = $trait->getFileName();
}
}
}
if ($paths) {

View File

@ -141,8 +141,8 @@ class XliffFileDumper extends FileDumper
$xliff->setAttribute('trgLang', str_replace('_', '-', $messages->getLocale()));
$xliffFile = $xliff->appendChild($dom->createElement('file'));
if (MessageCatalogue::INTL_DOMAIN_SUFFIX === substr($domain, -($suffixLength = \strlen(MessageCatalogue::INTL_DOMAIN_SUFFIX)))) {
$xliffFile->setAttribute('id', substr($domain, 0, -$suffixLength).'.'.$messages->getLocale());
if (str_ends_with($domain, MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
$xliffFile->setAttribute('id', substr($domain, 0, -\strlen(MessageCatalogue::INTL_DOMAIN_SUFFIX)).'.'.$messages->getLocale());
} else {
$xliffFile->setAttribute('id', $domain.'.'.$messages->getLocale());
}
@ -198,6 +198,6 @@ class XliffFileDumper extends FileDumper
private function hasMetadataArrayInfo(string $key, array $metadata = null): bool
{
return null !== $metadata && \array_key_exists($key, $metadata) && ($metadata[$key] instanceof \Traversable || \is_array($metadata[$key]));
return is_iterable($metadata[$key] ?? null);
}
}

View File

@ -13,7 +13,7 @@ namespace Symfony\Component\Translation\Exception;
class IncompleteDsnException extends InvalidArgumentException
{
public function __construct(string $message, string $dsn = null, ?\Throwable $previous = null)
public function __construct(string $message, string $dsn = null, \Throwable $previous = null)
{
if ($dsn) {
$message = sprintf('Invalid "%s" provider DSN: ', $dsn).$message;

View File

@ -16,7 +16,7 @@ namespace Symfony\Component\Translation\Exception;
*/
class MissingRequiredOptionException extends IncompleteDsnException
{
public function __construct(string $option, string $dsn = null, ?\Throwable $previous = null)
public function __construct(string $option, string $dsn = null, \Throwable $previous = null)
{
$message = sprintf('The option "%s" is required but missing.', $option);

View File

@ -29,8 +29,6 @@ class ChainExtractor implements ExtractorInterface
/**
* Adds a loader to the translation extractor.
*
* @param string $format The format of the loader
*/
public function addExtractor(string $format, ExtractorInterface $extractor)
{

View File

@ -24,14 +24,12 @@ interface ExtractorInterface
/**
* Extracts translation messages from files, a file or a directory to the catalogue.
*
* @param string|string[] $resource Files, a file or a directory
* @param string|iterable<string> $resource Files, a file or a directory
*/
public function extract($resource, MessageCatalogue $catalogue);
/**
* Sets the prefix that should be used for new found messages.
*
* @param string $prefix The prefix
*/
public function setPrefix(string $prefix);
}

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