[Web] Update composer deps

master
andryyy 2021-06-23 08:05:09 +02:00
parent d156a93a84
commit 5035e5bb42
No known key found for this signature in database
GPG Key ID: 8EC34FF2794E25EF
136 changed files with 3020 additions and 805 deletions

View File

@ -144,16 +144,16 @@
},
{
"name": "directorytree/ldaprecord",
"version": "v2.4.6",
"version": "v2.5.0",
"source": {
"type": "git",
"url": "https://github.com/DirectoryTree/LdapRecord.git",
"reference": "824a49feae4da52a522b3ec60ecad508b8f4ed23"
"reference": "ff7a92615fdc3f8b7f3d347c2847ce7ce06db287"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/824a49feae4da52a522b3ec60ecad508b8f4ed23",
"reference": "824a49feae4da52a522b3ec60ecad508b8f4ed23",
"url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/ff7a92615fdc3f8b7f3d347c2847ce7ce06db287",
"reference": "ff7a92615fdc3f8b7f3d347c2847ce7ce06db287",
"shasum": ""
},
"require": {
@ -161,15 +161,15 @@
"ext-ldap": "*",
"illuminate/contracts": "^5.0|^6.0|^7.0|^8.0",
"nesbot/carbon": "^1.0|^2.0",
"php": ">=7.2",
"php": ">=7.3",
"psr/log": "^1.0",
"psr/simple-cache": "^1.0",
"tightenco/collect": "^5.6|^6.0|^7.0|^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0",
"mockery/mockery": "^1.0",
"phpunit/phpunit": "^8.0"
"phpunit/phpunit": "^8.0",
"spatie/ray": "^1.24"
},
"type": "library",
"autoload": {
@ -213,20 +213,20 @@
"type": "github"
}
],
"time": "2021-05-11T13:29:46+00:00"
"time": "2021-06-06T18:51:41+00:00"
},
{
"name": "illuminate/contracts",
"version": "v8.42.1",
"version": "v8.48.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/contracts.git",
"reference": "68036b4fb17ad40a599323bda3f2c0845c8100d8"
"reference": "199fcedc161ba4a0b83feaddc4629f395dbf1641"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/68036b4fb17ad40a599323bda3f2c0845c8100d8",
"reference": "68036b4fb17ad40a599323bda3f2c0845c8100d8",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/199fcedc161ba4a0b83feaddc4629f395dbf1641",
"reference": "199fcedc161ba4a0b83feaddc4629f395dbf1641",
"shasum": ""
},
"require": {
@ -261,7 +261,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-05-18T12:49:19+00:00"
"time": "2021-06-01T14:53:38+00:00"
},
{
"name": "matthiasmullie/minify",
@ -446,16 +446,16 @@
},
{
"name": "nesbot/carbon",
"version": "2.48.0",
"version": "2.49.0",
"source": {
"type": "git",
"url": "https://github.com/briannesbitt/Carbon.git",
"reference": "d3c447f21072766cddec3522f9468a5849a76147"
"reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/d3c447f21072766cddec3522f9468a5849a76147",
"reference": "d3c447f21072766cddec3522f9468a5849a76147",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/93d9db91c0235c486875d22f1e08b50bdf3e6eee",
"reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee",
"shasum": ""
},
"require": {
@ -535,7 +535,7 @@
"type": "tidelift"
}
],
"time": "2021-05-07T10:08:30+00:00"
"time": "2021-06-02T07:31:40+00:00"
},
{
"name": "paragonie/random_compat",
@ -675,16 +675,16 @@
},
{
"name": "phpmailer/phpmailer",
"version": "v6.4.1",
"version": "v6.5.0",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "9256f12d8fb0cd0500f93b19e18c356906cbed3d"
"reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/9256f12d8fb0cd0500f93b19e18c356906cbed3d",
"reference": "9256f12d8fb0cd0500f93b19e18c356906cbed3d",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a5b5c43e50b7fba655f793ad27303cd74c57363c",
"reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c",
"shasum": ""
},
"require": {
@ -739,7 +739,7 @@
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.4.1"
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.5.0"
},
"funding": [
{
@ -747,7 +747,7 @@
"type": "github"
}
],
"time": "2021-04-29T12:25:04+00:00"
"time": "2021-06-16T14:33:43+00:00"
},
{
"name": "psr/container",
@ -1024,17 +1024,84 @@
"time": "2017-04-19T22:01:50+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.22.1",
"name": "symfony/deprecation-contracts",
"version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "5232de97ee3b75b0360528dae24e73db49566ab1"
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/5232de97ee3b75b0360528dae24e73db49566ab1",
"reference": "5232de97ee3b75b0360528dae24e73db49566ab1",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627",
"reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-03-23T23:28:01+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
"reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
"shasum": ""
},
"require": {
@ -1046,7 +1113,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.22-dev"
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1085,7 +1152,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.1"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.0"
},
"funding": [
{
@ -1101,20 +1168,20 @@
"type": "tidelift"
}
],
"time": "2021-01-22T09:19:47+00:00"
"time": "2021-05-27T09:27:20+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.22.1",
"version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91"
"reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91",
"reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0",
"reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0",
"shasum": ""
},
"require": {
@ -1123,7 +1190,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.22-dev"
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1168,7 +1235,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0"
},
"funding": [
{
@ -1184,24 +1251,25 @@
"type": "tidelift"
}
],
"time": "2021-01-07T16:49:33+00:00"
"time": "2021-02-19T12:13:01+00:00"
},
{
"name": "symfony/translation",
"version": "v5.2.9",
"version": "v5.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "61af68dba333e2d376a325a29c2a3f2a605b4876"
"reference": "7e2603bcc598e14804c4d2359d8dc4ee3c40391b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/61af68dba333e2d376a325a29c2a3f2a605b4876",
"reference": "61af68dba333e2d376a325a29c2a3f2a605b4876",
"url": "https://api.github.com/repos/symfony/translation/zipball/7e2603bcc598e14804c4d2359d8dc4ee3c40391b",
"reference": "7e2603bcc598e14804c4d2359d8dc4ee3c40391b",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php80": "^1.15",
"symfony/translation-contracts": "^2.3"
@ -1224,6 +1292,7 @@
"symfony/finder": "^4.4|^5.0",
"symfony/http-kernel": "^5.0",
"symfony/intl": "^4.4|^5.0",
"symfony/polyfill-intl-icu": "^1.21",
"symfony/service-contracts": "^1.1.2|^2",
"symfony/yaml": "^4.4|^5.0"
},
@ -1261,7 +1330,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/translation/tree/v5.2.9"
"source": "https://github.com/symfony/translation/tree/v5.3.2"
},
"funding": [
{
@ -1277,7 +1346,7 @@
"type": "tidelift"
}
],
"time": "2021-05-16T13:07:46+00:00"
"time": "2021-06-06T09:51:56+00:00"
},
{
"name": "symfony/translation-contracts",
@ -1359,16 +1428,16 @@
},
{
"name": "symfony/var-dumper",
"version": "v5.2.8",
"version": "v5.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "d693200a73fae179d27f8f1b16b4faf3e8569eba"
"reference": "905a22c68b292ffb6f20d7636c36b220d1fba5ae"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/d693200a73fae179d27f8f1b16b4faf3e8569eba",
"reference": "d693200a73fae179d27f8f1b16b4faf3e8569eba",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/905a22c68b292ffb6f20d7636c36b220d1fba5ae",
"reference": "905a22c68b292ffb6f20d7636c36b220d1fba5ae",
"shasum": ""
},
"require": {
@ -1427,7 +1496,7 @@
"dump"
],
"support": {
"source": "https://github.com/symfony/var-dumper/tree/v5.2.8"
"source": "https://github.com/symfony/var-dumper/tree/v5.3.2"
},
"funding": [
{
@ -1443,7 +1512,7 @@
"type": "tidelift"
}
],
"time": "2021-05-07T13:42:21+00:00"
"time": "2021-06-06T09:51:56+00:00"
},
{
"name": "tightenco/collect",

View File

@ -66,12 +66,12 @@ private static $installed = array (
),
'directorytree/ldaprecord' =>
array (
'pretty_version' => 'v2.4.6',
'version' => '2.4.6.0',
'pretty_version' => 'v2.5.0',
'version' => '2.5.0.0',
'aliases' =>
array (
),
'reference' => '824a49feae4da52a522b3ec60ecad508b8f4ed23',
'reference' => 'ff7a92615fdc3f8b7f3d347c2847ce7ce06db287',
),
'exorus/php-mime-mail-parser' =>
array (
@ -82,12 +82,12 @@ private static $installed = array (
),
'illuminate/contracts' =>
array (
'pretty_version' => 'v8.42.1',
'version' => '8.42.1.0',
'pretty_version' => 'v8.48.0',
'version' => '8.48.0.0',
'aliases' =>
array (
),
'reference' => '68036b4fb17ad40a599323bda3f2c0845c8100d8',
'reference' => '199fcedc161ba4a0b83feaddc4629f395dbf1641',
),
'matthiasmullie/minify' =>
array (
@ -125,12 +125,12 @@ private static $installed = array (
),
'nesbot/carbon' =>
array (
'pretty_version' => '2.48.0',
'version' => '2.48.0.0',
'pretty_version' => '2.49.0',
'version' => '2.49.0.0',
'aliases' =>
array (
),
'reference' => 'd3c447f21072766cddec3522f9468a5849a76147',
'reference' => '93d9db91c0235c486875d22f1e08b50bdf3e6eee',
),
'paragonie/random_compat' =>
array (
@ -152,12 +152,12 @@ private static $installed = array (
),
'phpmailer/phpmailer' =>
array (
'pretty_version' => 'v6.4.1',
'version' => '6.4.1.0',
'pretty_version' => 'v6.5.0',
'version' => '6.5.0.0',
'aliases' =>
array (
),
'reference' => '9256f12d8fb0cd0500f93b19e18c356906cbed3d',
'reference' => 'a5b5c43e50b7fba655f793ad27303cd74c57363c',
),
'psr/container' =>
array (
@ -204,32 +204,41 @@ private static $installed = array (
),
'reference' => 'cdb89f6ffa2c4cc78f8ed9ea6ee0594a9133ccad',
),
'symfony/polyfill-mbstring' =>
'symfony/deprecation-contracts' =>
array (
'pretty_version' => 'v1.22.1',
'version' => '1.22.1.0',
'pretty_version' => 'v2.4.0',
'version' => '2.4.0.0',
'aliases' =>
array (
),
'reference' => '5232de97ee3b75b0360528dae24e73db49566ab1',
'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.22.1',
'version' => '1.22.1.0',
'pretty_version' => 'v1.23.0',
'version' => '1.23.0.0',
'aliases' =>
array (
),
'reference' => 'dc3063ba22c2a1fd2f45ed856374d79114998f91',
'reference' => 'eca0bf41ed421bed1b57c4958bab16aa86b757d0',
),
'symfony/translation' =>
array (
'pretty_version' => 'v5.2.9',
'version' => '5.2.9.0',
'pretty_version' => 'v5.3.2',
'version' => '5.3.2.0',
'aliases' =>
array (
),
'reference' => '61af68dba333e2d376a325a29c2a3f2a605b4876',
'reference' => '7e2603bcc598e14804c4d2359d8dc4ee3c40391b',
),
'symfony/translation-contracts' =>
array (
@ -249,12 +258,12 @@ private static $installed = array (
),
'symfony/var-dumper' =>
array (
'pretty_version' => 'v5.2.8',
'version' => '5.2.8.0',
'pretty_version' => 'v5.3.2',
'version' => '5.3.2.0',
'aliases' =>
array (
),
'reference' => 'd693200a73fae179d27f8f1b16b4faf3e8569eba',
'reference' => '905a22c68b292ffb6f20d7636c36b220d1fba5ae',
),
'tightenco/collect' =>
array (
@ -455,8 +464,11 @@ 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;
}
@ -466,6 +478,17 @@ return self::$installed;
public static function getAllRawData()
{
return self::getInstalled();
}

View File

@ -8,6 +8,7 @@ $baseDir = dirname($vendorDir);
return array(
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/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',
'fe62ba7e10580d903cc46d808b5961a4' => $vendorDir . '/tightenco/collect/src/Collect/Support/helpers.php',

View File

@ -9,6 +9,7 @@ class ComposerStaticInit873464e4bd965a3168f133248b1b218b
public static $files = array (
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/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',
'fe62ba7e10580d903cc46d808b5961a4' => __DIR__ . '/..' . '/tightenco/collect/src/Collect/Support/helpers.php',

View File

@ -140,17 +140,17 @@
},
{
"name": "directorytree/ldaprecord",
"version": "v2.4.6",
"version_normalized": "2.4.6.0",
"version": "v2.5.0",
"version_normalized": "2.5.0.0",
"source": {
"type": "git",
"url": "https://github.com/DirectoryTree/LdapRecord.git",
"reference": "824a49feae4da52a522b3ec60ecad508b8f4ed23"
"reference": "ff7a92615fdc3f8b7f3d347c2847ce7ce06db287"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/824a49feae4da52a522b3ec60ecad508b8f4ed23",
"reference": "824a49feae4da52a522b3ec60ecad508b8f4ed23",
"url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/ff7a92615fdc3f8b7f3d347c2847ce7ce06db287",
"reference": "ff7a92615fdc3f8b7f3d347c2847ce7ce06db287",
"shasum": ""
},
"require": {
@ -158,17 +158,17 @@
"ext-ldap": "*",
"illuminate/contracts": "^5.0|^6.0|^7.0|^8.0",
"nesbot/carbon": "^1.0|^2.0",
"php": ">=7.2",
"php": ">=7.3",
"psr/log": "^1.0",
"psr/simple-cache": "^1.0",
"tightenco/collect": "^5.6|^6.0|^7.0|^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0",
"mockery/mockery": "^1.0",
"phpunit/phpunit": "^8.0"
"phpunit/phpunit": "^8.0",
"spatie/ray": "^1.24"
},
"time": "2021-05-11T13:29:46+00:00",
"time": "2021-06-06T18:51:41+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -216,17 +216,17 @@
},
{
"name": "illuminate/contracts",
"version": "v8.42.1",
"version_normalized": "8.42.1.0",
"version": "v8.48.0",
"version_normalized": "8.48.0.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/contracts.git",
"reference": "68036b4fb17ad40a599323bda3f2c0845c8100d8"
"reference": "199fcedc161ba4a0b83feaddc4629f395dbf1641"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/68036b4fb17ad40a599323bda3f2c0845c8100d8",
"reference": "68036b4fb17ad40a599323bda3f2c0845c8100d8",
"url": "https://api.github.com/repos/illuminate/contracts/zipball/199fcedc161ba4a0b83feaddc4629f395dbf1641",
"reference": "199fcedc161ba4a0b83feaddc4629f395dbf1641",
"shasum": ""
},
"require": {
@ -234,7 +234,7 @@
"psr/container": "^1.0",
"psr/simple-cache": "^1.0"
},
"time": "2021-05-18T12:49:19+00:00",
"time": "2021-06-01T14:53:38+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -453,17 +453,17 @@
},
{
"name": "nesbot/carbon",
"version": "2.48.0",
"version_normalized": "2.48.0.0",
"version": "2.49.0",
"version_normalized": "2.49.0.0",
"source": {
"type": "git",
"url": "https://github.com/briannesbitt/Carbon.git",
"reference": "d3c447f21072766cddec3522f9468a5849a76147"
"reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/d3c447f21072766cddec3522f9468a5849a76147",
"reference": "d3c447f21072766cddec3522f9468a5849a76147",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/93d9db91c0235c486875d22f1e08b50bdf3e6eee",
"reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee",
"shasum": ""
},
"require": {
@ -482,7 +482,7 @@
"phpunit/phpunit": "^7.5.20 || ^8.5.14",
"squizlabs/php_codesniffer": "^3.4"
},
"time": "2021-05-07T10:08:30+00:00",
"time": "2021-06-02T07:31:40+00:00",
"bin": [
"bin/carbon"
],
@ -687,17 +687,17 @@
},
{
"name": "phpmailer/phpmailer",
"version": "v6.4.1",
"version_normalized": "6.4.1.0",
"version": "v6.5.0",
"version_normalized": "6.5.0.0",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "9256f12d8fb0cd0500f93b19e18c356906cbed3d"
"reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/9256f12d8fb0cd0500f93b19e18c356906cbed3d",
"reference": "9256f12d8fb0cd0500f93b19e18c356906cbed3d",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a5b5c43e50b7fba655f793ad27303cd74c57363c",
"reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c",
"shasum": ""
},
"require": {
@ -722,7 +722,7 @@
"stevenmaguire/oauth2-microsoft": "Needed for Microsoft XOAUTH2 authentication",
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)"
},
"time": "2021-04-29T12:25:04+00:00",
"time": "2021-06-16T14:33:43+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -754,7 +754,7 @@
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.4.1"
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.5.0"
},
"funding": [
{
@ -1049,18 +1049,88 @@
"install-path": "../soundasleep/html2text"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.22.1",
"version_normalized": "1.22.1.0",
"name": "symfony/deprecation-contracts",
"version": "v2.4.0",
"version_normalized": "2.4.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "5232de97ee3b75b0360528dae24e73db49566ab1"
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/5232de97ee3b75b0360528dae24e73db49566ab1",
"reference": "5232de97ee3b75b0360528dae24e73db49566ab1",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627",
"reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"time": "2021-03-23T23:28:01+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"install-path": "../symfony/deprecation-contracts"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.23.0",
"version_normalized": "1.23.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
"reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
"shasum": ""
},
"require": {
@ -1069,11 +1139,11 @@
"suggest": {
"ext-mbstring": "For best performance"
},
"time": "2021-01-22T09:19:47+00:00",
"time": "2021-05-27T09:27:20+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.22-dev"
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1113,7 +1183,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.1"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.0"
},
"funding": [
{
@ -1133,27 +1203,27 @@
},
{
"name": "symfony/polyfill-php80",
"version": "v1.22.1",
"version_normalized": "1.22.1.0",
"version": "v1.23.0",
"version_normalized": "1.23.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91"
"reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91",
"reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0",
"reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"time": "2021-01-07T16:49:33+00:00",
"time": "2021-02-19T12:13:01+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.22-dev"
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -1199,7 +1269,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0"
},
"funding": [
{
@ -1219,21 +1289,22 @@
},
{
"name": "symfony/translation",
"version": "v5.2.9",
"version_normalized": "5.2.9.0",
"version": "v5.3.2",
"version_normalized": "5.3.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "61af68dba333e2d376a325a29c2a3f2a605b4876"
"reference": "7e2603bcc598e14804c4d2359d8dc4ee3c40391b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/61af68dba333e2d376a325a29c2a3f2a605b4876",
"reference": "61af68dba333e2d376a325a29c2a3f2a605b4876",
"url": "https://api.github.com/repos/symfony/translation/zipball/7e2603bcc598e14804c4d2359d8dc4ee3c40391b",
"reference": "7e2603bcc598e14804c4d2359d8dc4ee3c40391b",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php80": "^1.15",
"symfony/translation-contracts": "^2.3"
@ -1256,6 +1327,7 @@
"symfony/finder": "^4.4|^5.0",
"symfony/http-kernel": "^5.0",
"symfony/intl": "^4.4|^5.0",
"symfony/polyfill-intl-icu": "^1.21",
"symfony/service-contracts": "^1.1.2|^2",
"symfony/yaml": "^4.4|^5.0"
},
@ -1264,7 +1336,7 @@
"symfony/config": "",
"symfony/yaml": ""
},
"time": "2021-05-16T13:07:46+00:00",
"time": "2021-06-06T09:51:56+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -1295,7 +1367,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/translation/tree/v5.2.9"
"source": "https://github.com/symfony/translation/tree/v5.3.2"
},
"funding": [
{
@ -1396,17 +1468,17 @@
},
{
"name": "symfony/var-dumper",
"version": "v5.2.8",
"version_normalized": "5.2.8.0",
"version": "v5.3.2",
"version_normalized": "5.3.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "d693200a73fae179d27f8f1b16b4faf3e8569eba"
"reference": "905a22c68b292ffb6f20d7636c36b220d1fba5ae"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/d693200a73fae179d27f8f1b16b4faf3e8569eba",
"reference": "d693200a73fae179d27f8f1b16b4faf3e8569eba",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/905a22c68b292ffb6f20d7636c36b220d1fba5ae",
"reference": "905a22c68b292ffb6f20d7636c36b220d1fba5ae",
"shasum": ""
},
"require": {
@ -1429,7 +1501,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-05-07T13:42:21+00:00",
"time": "2021-06-06T09:51:56+00:00",
"bin": [
"Resources/bin/var-dump-server"
],
@ -1467,7 +1539,7 @@
"dump"
],
"support": {
"source": "https://github.com/symfony/var-dumper/tree/v5.2.8"
"source": "https://github.com/symfony/var-dumper/tree/v5.3.2"
},
"funding": [
{

View File

@ -40,12 +40,12 @@
),
'directorytree/ldaprecord' =>
array (
'pretty_version' => 'v2.4.6',
'version' => '2.4.6.0',
'pretty_version' => 'v2.5.0',
'version' => '2.5.0.0',
'aliases' =>
array (
),
'reference' => '824a49feae4da52a522b3ec60ecad508b8f4ed23',
'reference' => 'ff7a92615fdc3f8b7f3d347c2847ce7ce06db287',
),
'exorus/php-mime-mail-parser' =>
array (
@ -56,12 +56,12 @@
),
'illuminate/contracts' =>
array (
'pretty_version' => 'v8.42.1',
'version' => '8.42.1.0',
'pretty_version' => 'v8.48.0',
'version' => '8.48.0.0',
'aliases' =>
array (
),
'reference' => '68036b4fb17ad40a599323bda3f2c0845c8100d8',
'reference' => '199fcedc161ba4a0b83feaddc4629f395dbf1641',
),
'matthiasmullie/minify' =>
array (
@ -99,12 +99,12 @@
),
'nesbot/carbon' =>
array (
'pretty_version' => '2.48.0',
'version' => '2.48.0.0',
'pretty_version' => '2.49.0',
'version' => '2.49.0.0',
'aliases' =>
array (
),
'reference' => 'd3c447f21072766cddec3522f9468a5849a76147',
'reference' => '93d9db91c0235c486875d22f1e08b50bdf3e6eee',
),
'paragonie/random_compat' =>
array (
@ -126,12 +126,12 @@
),
'phpmailer/phpmailer' =>
array (
'pretty_version' => 'v6.4.1',
'version' => '6.4.1.0',
'pretty_version' => 'v6.5.0',
'version' => '6.5.0.0',
'aliases' =>
array (
),
'reference' => '9256f12d8fb0cd0500f93b19e18c356906cbed3d',
'reference' => 'a5b5c43e50b7fba655f793ad27303cd74c57363c',
),
'psr/container' =>
array (
@ -178,32 +178,41 @@
),
'reference' => 'cdb89f6ffa2c4cc78f8ed9ea6ee0594a9133ccad',
),
'symfony/polyfill-mbstring' =>
'symfony/deprecation-contracts' =>
array (
'pretty_version' => 'v1.22.1',
'version' => '1.22.1.0',
'pretty_version' => 'v2.4.0',
'version' => '2.4.0.0',
'aliases' =>
array (
),
'reference' => '5232de97ee3b75b0360528dae24e73db49566ab1',
'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.22.1',
'version' => '1.22.1.0',
'pretty_version' => 'v1.23.0',
'version' => '1.23.0.0',
'aliases' =>
array (
),
'reference' => 'dc3063ba22c2a1fd2f45ed856374d79114998f91',
'reference' => 'eca0bf41ed421bed1b57c4958bab16aa86b757d0',
),
'symfony/translation' =>
array (
'pretty_version' => 'v5.2.9',
'version' => '5.2.9.0',
'pretty_version' => 'v5.3.2',
'version' => '5.3.2.0',
'aliases' =>
array (
),
'reference' => '61af68dba333e2d376a325a29c2a3f2a605b4876',
'reference' => '7e2603bcc598e14804c4d2359d8dc4ee3c40391b',
),
'symfony/translation-contracts' =>
array (
@ -223,12 +232,12 @@
),
'symfony/var-dumper' =>
array (
'pretty_version' => 'v5.2.8',
'version' => '5.2.8.0',
'pretty_version' => 'v5.3.2',
'version' => '5.3.2.0',
'aliases' =>
array (
),
'reference' => 'd693200a73fae179d27f8f1b16b4faf3e8569eba',
'reference' => '905a22c68b292ffb6f20d7636c36b220d1fba5ae',
),
'tightenco/collect' =>
array (

View File

@ -1,33 +0,0 @@
name: fix-style
on:
push:
pull_request:
paths:
- '**.php'
jobs:
php-cs-fixer:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
with:
ref: ${{ github.head_ref }}
- name: Setup PHP
uses: shivammathur/setup-php@v1
with:
php-version: '7.4'
extensions: mbstring, intl, gd, xml, dom, json, fileinfo, curl, zip, iconv
- name: Install Dependencies
run: composer install --prefer-dist
- name: Fix Style
run: ./vendor/bin/php-cs-fixer fix --diff --allow-risky=yes
- name: Commit Changes
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: Fix styling changes

View File

@ -1,40 +1,40 @@
name: run-tests
on:
push:
pull_request:
schedule:
- cron: '0 0 * * *'
push:
pull_request:
schedule:
- cron: "0 0 * * *"
jobs:
run-tests:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: [8.0, 7.4, 7.3, 7.2]
run-tests:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: [8.0, 7.4, 7.3]
name: P${{ matrix.php }}
name: P${{ matrix.php }}
steps:
- name: Checkout code
uses: actions/checkout@v2
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ~/.composer/cache/files
key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ~/.composer/cache/files
key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: ldap, json
coverage: none
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: ldap, json
coverage: none
- name: Install dependencies
run: composer update --prefer-dist --no-interaction --no-suggest
- name: Execute tests
run: vendor/bin/phpunit
- name: Install dependencies
run: composer update --prefer-dist --no-interaction --no-suggest
- name: Execute tests
run: vendor/bin/phpunit

View File

@ -1,141 +0,0 @@
<?php
$finder = (new Symfony\Component\Finder\Finder)
->in([
__DIR__.'/src',
__DIR__.'/tests',
])
->name('*.php')
->ignoreVCS(true)
->ignoreDotFiles(true);
return (new PhpCsFixer\Config)
->setRules([
'array_syntax' => ['syntax' => 'short'],
'binary_operator_spaces' => [
'default' => 'single_space',
'operators' => ['=>' => null],
],
'blank_line_after_namespace' => true,
'blank_line_after_opening_tag' => true,
'blank_line_before_statement' => [
'statements' => ['return'],
],
'braces' => true,
'cast_spaces' => true,
'class_attributes_separation' => [
'elements' => ['method' => 'one'],
],
'class_definition' => true,
'concat_space' => [
'spacing' => 'none',
],
'constant_case' => true,
'declare_equal_normalize' => true,
'elseif' => true,
'encoding' => true,
'full_opening_tag' => true,
'fully_qualified_strict_types' => true,
'function_declaration' => true,
'function_typehint_space' => true,
'general_phpdoc_tag_rename' => true,
'heredoc_to_nowdoc' => true,
'include' => true,
'increment_style' => ['style' => 'post'],
'indentation_type' => true,
'linebreak_after_opening_tag' => true,
'line_ending' => true,
'lowercase_cast' => true,
'lowercase_keywords' => true,
'lowercase_static_reference' => true,
'magic_method_casing' => true,
'magic_constant_casing' => true,
'method_argument_space' => true,
'native_function_casing' => true,
'no_alias_functions' => true,
'no_extra_blank_lines' => [
'tokens' => [
'extra',
'throw',
'use',
'use_trait',
],
],
'no_blank_lines_after_class_opening' => true,
'no_blank_lines_after_phpdoc' => true,
'no_closing_tag' => true,
'no_empty_phpdoc' => true,
'no_empty_statement' => true,
'no_leading_import_slash' => true,
'no_leading_namespace_whitespace' => true,
'no_mixed_echo_print' => [
'use' => 'echo',
],
'no_multiline_whitespace_around_double_arrow' => true,
'multiline_whitespace_before_semicolons' => [
'strategy' => 'no_multi_line',
],
'no_short_bool_cast' => true,
'no_singleline_whitespace_before_semicolons' => true,
'no_spaces_after_function_name' => true,
'no_spaces_around_offset' => true,
'no_spaces_inside_parenthesis' => true,
'no_trailing_comma_in_list_call' => true,
'no_trailing_comma_in_singleline_array' => true,
'no_trailing_whitespace' => true,
'no_trailing_whitespace_in_comment' => true,
'no_unneeded_control_parentheses' => true,
'no_unreachable_default_argument_value' => true,
'no_useless_return' => true,
'no_unused_imports' => true,
'no_whitespace_before_comma_in_array' => true,
'no_whitespace_in_blank_line' => true,
'normalize_index_brace' => true,
'not_operator_with_successor_space' => true,
'object_operator_without_whitespace' => true,
'ordered_imports' => ['sort_algorithm' => 'alpha'],
'phpdoc_align' => true,
'phpdoc_indent' => true,
'phpdoc_inline_tag_normalizer' => true,
'phpdoc_no_access' => true,
'phpdoc_no_package' => true,
'phpdoc_no_useless_inheritdoc' => true,
'phpdoc_scalar' => true,
'phpdoc_single_line_var_spacing' => true,
'phpdoc_summary' => true,
'phpdoc_to_comment' => true,
'phpdoc_tag_type' => true,
'phpdoc_trim' => true,
'phpdoc_types' => true,
'phpdoc_var_without_name' => true,
'php_unit_method_casing' => [
'case' => 'snake_case',
],
'psr_autoloading' => true,
'self_accessor' => true,
'short_scalar_cast' => true,
'simplified_null_return' => false,
'single_blank_line_at_eof' => true,
'single_blank_line_before_namespace' => true,
'single_class_element_per_statement' => true,
'single_import_per_statement' => true,
'single_line_after_imports' => true,
'single_line_comment_style' => [
'comment_types' => ['hash'],
],
'single_quote' => true,
'space_after_semicolon' => true,
'standardize_not_equals' => true,
'switch_case_semicolon_to_colon' => true,
'switch_case_space' => true,
'ternary_operator_spaces' => true,
'trailing_comma_in_multiline' => [
'elements' => ['arrays'],
],
'trim_array_spaces' => true,
'unary_operator_spaces' => true,
'visibility_required' => [
'elements' => ['method', 'property'],
],
'whitespace_after_comma_in_array' => true,
])->setFinder($finder);

View File

@ -0,0 +1,4 @@
preset: laravel
enabled:
- phpdoc_align
- unalign_double_arrow

View File

@ -1,4 +0,0 @@
{
"php-cs-fixer.onsave": true,
"php-cs-fixer.allowRisky": true,
}

View File

@ -29,7 +29,7 @@
}
],
"require": {
"php": ">=7.2",
"php": ">=7.3",
"ext-ldap": "*",
"ext-json": "*",
"psr/log": "^1.0",
@ -41,7 +41,7 @@
"require-dev": {
"phpunit/phpunit": "^8.0",
"mockery/mockery": "^1.0",
"friendsofphp/php-cs-fixer": "^3.0"
"spatie/ray": "^1.24"
},
"archive": {
"exclude": ["/tests"]

View File

@ -54,10 +54,10 @@ class Guard
* @param string $password
* @param bool $stayBound
*
* @return bool
*
* @throws UsernameRequiredException
* @throws PasswordRequiredException
*
* @return bool
*/
public function attempt($username, $password, $stayBound = false)
{

View File

@ -124,9 +124,9 @@ class DomainConfiguration
*
* @param string $key
*
* @return mixed
*
* @throws ConfigurationException When the option specified does not exist.
*
* @return mixed
*/
public function get($key)
{
@ -155,9 +155,9 @@ class DomainConfiguration
* @param string $key
* @param mixed $value
*
* @return bool
*
* @throws ConfigurationException When an option value given is an invalid type.
*
* @return bool
*/
protected function validate($key, $value)
{

View File

@ -33,9 +33,9 @@ abstract class Validator
/**
* Validates the configuration value.
*
* @return bool
*
* @throws \LdapRecord\Configuration\ConfigurationException When the value given fails validation.
*
* @return bool
*/
abstract public function validate();
}

View File

@ -111,9 +111,9 @@ class Connection
*
* @param array $config
*
* @return $this
*
* @throws Configuration\ConfigurationException
*
* @return $this
*/
public function setConfiguration($config = [])
{
@ -183,8 +183,8 @@ class Connection
$this->configuration->get('options'),
[
LDAP_OPT_PROTOCOL_VERSION => $this->configuration->get('version'),
LDAP_OPT_NETWORK_TIMEOUT => $this->configuration->get('timeout'),
LDAP_OPT_REFERRALS => $this->configuration->get('follow_referrals'),
LDAP_OPT_NETWORK_TIMEOUT => $this->configuration->get('timeout'),
LDAP_OPT_REFERRALS => $this->configuration->get('follow_referrals'),
]
));
}
@ -241,10 +241,10 @@ class Connection
* @param string|null $username
* @param string|null $password
*
* @return Connection
*
* @throws Auth\BindException
* @throws LdapRecordException
*
* @return Connection
*/
public function connect($username = null, $password = null)
{
@ -274,10 +274,10 @@ class Connection
/**
* Reconnect to the LDAP server.
*
* @return void
*
* @throws Auth\BindException
* @throws ConnectionException
*
* @return void
*/
public function reconnect()
{
@ -385,9 +385,9 @@ class Connection
*
* @param Closure $operation
*
* @return mixed
*
* @throws LdapRecordException
*
* @return mixed
*/
protected function runOperationCallback(Closure $operation)
{
@ -442,9 +442,9 @@ class Connection
* @param LdapRecordException $e
* @param Closure $operation
*
* @return mixed
*
* @throws LdapRecordException
*
* @return mixed
*/
protected function tryAgainIfCausedByLostConnection(LdapRecordException $e, Closure $operation)
{
@ -463,9 +463,9 @@ class Connection
*
* @param Closure $operation
*
* @return mixed
*
* @throws LdapRecordException
*
* @return mixed
*/
protected function retry(Closure $operation)
{
@ -486,9 +486,9 @@ class Connection
* @param LdapRecordException $e
* @param Closure $operation
*
* @return mixed
*
* @throws LdapRecordException
*
* @return mixed
*/
protected function retryOnNextHost(LdapRecordException $e, Closure $operation)
{

View File

@ -84,7 +84,7 @@ class Container
*/
public static function getNewInstance()
{
return static::setInstance(new static);
return static::setInstance(new static());
}
/**
@ -117,9 +117,9 @@ class Container
*
* @param string|null $name
*
* @return Connection
*
* @throws ContainerException If the given connection does not exist.
*
* @return Connection
*/
public static function getConnection($name = null)
{
@ -332,9 +332,9 @@ class Container
*
* @param string|null $name
*
* @return Connection
*
* @throws ContainerException If the given connection does not exist.
*
* @return Connection
*/
public function get($name = null)
{

View File

@ -2,7 +2,7 @@
namespace LdapRecord\Events;
use Tightenco\Collect\Support\Arr;
use LdapRecord\Support\Arr;
/**
* Class Dispatcher.
@ -101,7 +101,7 @@ class Dispatcher implements DispatcherInterface
// When the given "event" is actually an object we will assume it is an event
// object and use the class as the event name and this event itself as the
// payload to the handler, which makes object based events quite simple.
list($event, $payload) = $this->parseEventAndPayload(
[$event, $payload] = $this->parseEventAndPayload(
$event,
$payload
);
@ -142,7 +142,7 @@ class Dispatcher implements DispatcherInterface
protected function parseEventAndPayload($event, $payload)
{
if (is_object($event)) {
list($payload, $event) = [[$event], get_class($event)];
[$payload, $event] = [[$event], get_class($event)];
}
return [$event, Arr::wrap($payload)];

View File

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

View File

@ -188,7 +188,7 @@ class Ldap extends LdapBase
{
$this->bound = false;
$this->host = $this->getConnectionString($hosts, $port);
$this->host = $this->makeConnectionUris($hosts, $port);
return $this->connection = $this->executeFailableOperation(function () {
return ldap_connect($this->host);

View File

@ -152,12 +152,15 @@ abstract class LdapBase implements LdapInterface
*
* @param Closure $operation
*
* @return mixed
*
* @throws LdapRecordException
*
* @return mixed
*/
protected function executeFailableOperation(Closure $operation)
{
// If some older versions of PHP, errors are reported instead of throwing
// exceptions, which could be a signifcant detriment to our application.
// Here, we will enforce these operations to throw exceptions instead.
set_error_handler(function ($severity, $message, $file, $line) {
if (! $this->shouldBypassError($message)) {
throw new ErrorException($message, $severity, $severity, $file, $line);
@ -169,6 +172,9 @@ abstract class LdapBase implements LdapInterface
return $result;
}
// If the failed query operation was a based on a query being executed
// -- such as a search, read, or listing, then we can safely return
// the failed response here and prevent throwning an exception.
if ($this->shouldBypassFailure($method = debug_backtrace()[1]['function'])) {
return $result;
}
@ -208,6 +214,8 @@ abstract class LdapBase implements LdapInterface
/**
* Determine if the current PHP version supports server controls.
*
* @deprecated
*
* @return bool
*/
public function supportsServerControlsInMethods()
@ -223,18 +231,33 @@ abstract class LdapBase implements LdapInterface
*
* @return string
*/
protected function getConnectionString($hosts, $port)
protected function makeConnectionUris($hosts, $port)
{
// If we are using SSL and using the default port, we
// will override it to use the default SSL port.
// 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;
}
$hosts = array_map(function ($host) use ($port) {
// The blank space here is intentional. PHP's LDAP extension
// requires additional hosts to be seperated by a blank
// space, so that it can parse each individually.
return implode(' ', $this->assembleHostUris($hosts, $port));
}
/**
* Assemble the host URI strings.
*
* @param array|string $hosts
* @param string $port
*
* @return array
*/
protected function assembleHostUris($hosts, $port)
{
return array_map(function ($host) use ($port) {
return "{$this->getProtocol()}{$host}:{$port}";
}, (array) $hosts);
return implode(' ', $hosts);
}
}

View File

@ -202,9 +202,9 @@ interface LdapInterface
*
* @link http://php.net/manual/en/function.ldap-start-tls.php
*
* @return bool
*
* @throws LdapRecordException
*
* @return bool
*/
public function startTLS();
@ -310,9 +310,9 @@ interface LdapInterface
* @param string $username
* @param string $password
*
* @return bool
*
* @throws LdapRecordException
*
* @return bool
*/
public function bind($username, $password);
@ -324,9 +324,9 @@ interface LdapInterface
* @param string $dn
* @param array $entry
*
* @return bool
*
* @throws LdapRecordException
*
* @return bool
*/
public function add($dn, array $entry);
@ -337,9 +337,9 @@ interface LdapInterface
*
* @param string $dn
*
* @return bool
*
* @throws LdapRecordException
*
* @return bool
*/
public function delete($dn);
@ -353,9 +353,9 @@ interface LdapInterface
* @param string $newParent
* @param bool $deleteOldRdn
*
* @return bool
*
* @throws LdapRecordException
*
* @return bool
*/
public function rename($dn, $newRdn, $newParent, $deleteOldRdn = false);
@ -367,9 +367,9 @@ interface LdapInterface
* @param string $dn
* @param array $entry
*
* @return bool
*
* @throws LdapRecordException
*
* @return bool
*/
public function modify($dn, array $entry);
@ -381,9 +381,9 @@ interface LdapInterface
* @param string $dn
* @param array $values
*
* @return bool
*
* @throws LdapRecordException
*
* @return bool
*/
public function modifyBatch($dn, array $values);
@ -395,9 +395,9 @@ interface LdapInterface
* @param string $dn
* @param array $entry
*
* @return bool
*
* @throws LdapRecordException
*
* @return bool
*/
public function modAdd($dn, array $entry);
@ -409,9 +409,9 @@ interface LdapInterface
* @param string $dn
* @param array $entry
*
* @return bool
*
* @throws LdapRecordException
*
* @return bool
*/
public function modReplace($dn, array $entry);
@ -423,9 +423,9 @@ interface LdapInterface
* @param string $dn
* @param array $entry
*
* @return bool
*
* @throws LdapRecordException
*
* @return bool
*/
public function modDelete($dn, array $entry);

View File

@ -19,8 +19,8 @@ class Entry extends BaseEntry implements ActiveDirectory
* @var array
*/
protected $defaultDates = [
'whenchanged' => 'windows',
'whencreated' => 'windows',
'whenchanged' => 'windows',
'whencreated' => 'windows',
'dscorepropagationdata' => 'windows',
];
@ -86,9 +86,9 @@ class Entry extends BaseEntry implements ActiveDirectory
*
* @param string|null $newParentDn
*
* @return bool
*
* @throws \LdapRecord\LdapRecordException
*
* @return bool
*/
public function restore($newParentDn = null)
{
@ -110,7 +110,7 @@ class Entry extends BaseEntry implements ActiveDirectory
});
$this->save([
'isDeleted' => null,
'isDeleted' => null,
'distinguishedName' => $newDn,
]);
}
@ -120,13 +120,13 @@ class Entry extends BaseEntry implements ActiveDirectory
*
* @param string|null $connection
*
* @return static
*
* @throws \LdapRecord\Models\ModelNotFoundException
*
* @return static
*/
public static function getRootDse($connection = null)
{
return static::on($connection ?? (new static)->getConnectionName())
return static::on($connection ?? (new static())->getConnectionName())
->in(null)
->read()
->whereHas('objectclass')

View File

@ -16,6 +16,6 @@ class ExchangeDatabase extends Entry
{
parent::boot();
static::addGlobalScope(new Scopes\InConfigurationContext);
static::addGlobalScope(new Scopes\InConfigurationContext());
}
}

View File

@ -16,7 +16,7 @@ class ExchangeServer extends Entry
{
parent::boot();
static::addGlobalScope(new Scopes\HasServerRoleAttribute);
static::addGlobalScope(new Scopes\InConfigurationContext);
static::addGlobalScope(new Scopes\HasServerRoleAttribute());
static::addGlobalScope(new Scopes\InConfigurationContext());
}
}

View File

@ -15,9 +15,9 @@ class InConfigurationContext implements Scope
* @param Builder $query
* @param Model $model
*
* @return void
*
* @throws \LdapRecord\Models\ModelNotFoundException
*
* @return void
*/
public function apply(Builder $query, Model $model)
{
@ -29,9 +29,9 @@ class InConfigurationContext implements Scope
*
* @param Model $model
*
* @return mixed
*
* @throws \LdapRecord\Models\ModelNotFoundException
*
* @return mixed
*/
protected function getConfigurationNamingContext(Model $model)
{

View File

@ -47,12 +47,12 @@ class User extends Entry implements Authenticatable
* @var array
*/
protected $dates = [
'lastlogon' => 'windows-int',
'lastlogoff' => 'windows-int',
'pwdlastset' => 'windows-int',
'lockouttime' => 'windows-int',
'accountexpires' => 'windows-int',
'badpasswordtime' => 'windows-int',
'lastlogon' => 'windows-int',
'lastlogoff' => 'windows-int',
'pwdlastset' => 'windows-int',
'lockouttime' => 'windows-int',
'accountexpires' => 'windows-int',
'badpasswordtime' => 'windows-int',
'lastlogontimestamp' => 'windows-int',
];

View File

@ -3,6 +3,7 @@
namespace LdapRecord\Models\Attributes;
use LdapRecord\EscapesValues;
use LdapRecord\Support\Arr;
class DistinguishedNameBuilder
{
@ -107,7 +108,7 @@ class DistinguishedNameBuilder
// RDN's have been given if the value is null, and
// attempt to break them into their components.
if (is_null($value)) {
$attributes = is_array($attribute) ? $attribute : [$attribute];
$attributes = Arr::wrap($attribute);
$components = array_map([$this, 'makeComponentizedArray'], $attributes);
} else {

View File

@ -244,9 +244,9 @@ class Password
*
* @param int $type
*
* @return array
*
* @throws InvalidArgumentException
*
* @return array
*/
protected static function makeCryptPrefixAndLength($type)
{
@ -297,9 +297,9 @@ class Password
/**
* Attempt to retrieve a salt from the encrypted password.
*
* @return string
*
* @throws LdapRecordException
*
* @return string
*/
public static function getSalt($encryptedPassword)
{
@ -321,11 +321,11 @@ class Password
*
* @param string $method
*
* @return bool
*
* @throws \ReflectionException
*
* @return bool
*/
public static function hashMethodRequiresSalt($method) : bool
public static function hashMethodRequiresSalt($method): bool
{
$parameters = (new ReflectionMethod(static::class, $method))->getParameters();

View File

@ -17,22 +17,22 @@ class TSPropertyArray
* @var array
*/
const DEFAULTS = [
'CtxCfgPresent' => 2953518677,
'CtxWFProfilePath' => '',
'CtxWFProfilePathW' => '',
'CtxWFHomeDir' => '',
'CtxWFHomeDirW' => '',
'CtxWFHomeDirDrive' => '',
'CtxWFHomeDirDriveW' => '',
'CtxShadow' => 1,
'CtxCfgPresent' => 2953518677,
'CtxWFProfilePath' => '',
'CtxWFProfilePathW' => '',
'CtxWFHomeDir' => '',
'CtxWFHomeDirW' => '',
'CtxWFHomeDirDrive' => '',
'CtxWFHomeDirDriveW' => '',
'CtxShadow' => 1,
'CtxMaxDisconnectionTime' => 0,
'CtxMaxConnectionTime' => 0,
'CtxMaxIdleTime' => 0,
'CtxWorkDirectory' => '',
'CtxWorkDirectoryW' => '',
'CtxCfgFlags1' => 2418077696,
'CtxInitialProgram' => '',
'CtxInitialProgramW' => '',
'CtxMaxConnectionTime' => 0,
'CtxMaxIdleTime' => 0,
'CtxWorkDirectory' => '',
'CtxWorkDirectoryW' => '',
'CtxCfgFlags1' => 2418077696,
'CtxInitialProgram' => '',
'CtxInitialProgramW' => '',
];
/**

View File

@ -61,9 +61,9 @@ class Timestamp
*
* @param mixed $value
*
* @return float|string
*
* @throws LdapRecordException
*
* @return float|string
*/
public function fromDateTime($value)
{
@ -121,9 +121,9 @@ class Timestamp
*
* @param mixed $value
*
* @return Carbon|false
*
* @throws LdapRecordException
*
* @return Carbon|false
*/
public function toDateTime($value)
{
@ -213,9 +213,9 @@ class Timestamp
*
* @param int $value
*
* @return DateTime|bool
*
* @throws \Exception
*
* @return DateTime|bool
*/
protected function convertWindowsIntegerTimeToDateTime($value)
{

View File

@ -269,7 +269,7 @@ class BatchModification
// A values key cannot be provided when
// a remove all type is selected.
return [
static::KEY_ATTRIB => $this->attribute,
static::KEY_ATTRIB => $this->attribute,
static::KEY_MODTYPE => $this->type,
];
case LDAP_MODIFY_BATCH_REMOVE:
@ -278,9 +278,9 @@ class BatchModification
// Fallthrough.
case LDAP_MODIFY_BATCH_REPLACE:
return [
static::KEY_ATTRIB => $this->attribute,
static::KEY_ATTRIB => $this->attribute,
static::KEY_MODTYPE => $this->type,
static::KEY_VALUES => $this->values,
static::KEY_VALUES => $this->values,
];
default:
// If the modtype isn't recognized, we'll return null.

View File

@ -5,7 +5,7 @@ namespace LdapRecord\Models;
use Closure;
use LdapRecord\Models\Attributes\DistinguishedName;
use LdapRecord\Query\Collection as QueryCollection;
use Tightenco\Collect\Support\Arr;
use LdapRecord\Support\Arr;
class Collection extends QueryCollection
{

View File

@ -9,7 +9,7 @@ use LdapRecord\LdapRecordException;
use LdapRecord\Models\Attributes\MbString;
use LdapRecord\Models\Attributes\Timestamp;
use LdapRecord\Models\DetectsResetIntegers;
use Tightenco\Collect\Support\Arr;
use LdapRecord\Support\Arr;
trait HasAttributes
{
@ -190,7 +190,7 @@ trait HasAttributes
// We want to spin through all the mutated attributes for this model and call
// the mutator for the attribute. We cache off every mutated attributes so
// we don't have to constantly check on attributes that actually change.
if (! array_key_exists($key, $attributes)) {
if (! Arr::exists($attributes, $key)) {
continue;
}
@ -311,9 +311,9 @@ trait HasAttributes
* @param string $type
* @param mixed $value
*
* @return float|string
*
* @throws LdapRecordException
*
* @return float|string
*/
public function fromDateTime($type, $value)
{
@ -326,9 +326,9 @@ trait HasAttributes
* @param mixed $value
* @param string $type
*
* @return Carbon|false
*
* @throws LdapRecordException
*
* @return Carbon|false
*/
public function asDateTime($value, $type)
{
@ -876,9 +876,9 @@ trait HasAttributes
// LDAP search results will contain the distinguished
// name inside of the `dn` key. We will retrieve this,
// and then set it on the model for accessibility.
if (array_key_exists('dn', $attributes)) {
$this->dn = is_array($attributes['dn'])
? reset($attributes['dn'])
if (Arr::exists($attributes, 'dn')) {
$this->dn = Arr::accessible($attributes['dn'])
? Arr::first($attributes['dn'])
: $attributes['dn'];
}

View File

@ -14,9 +14,9 @@ trait HasGlobalScopes
* @param Scope|Closure|string $scope
* @param Closure|null $implementation
*
* @return mixed
*
* @throws InvalidArgumentException
*
* @return mixed
*/
public static function addGlobalScope($scope, Closure $implementation = null)
{

View File

@ -159,9 +159,9 @@ trait HasPassword
* @param string $password
* @param string $salt
*
* @return string
*
* @throws LdapRecordException
*
* @return string
*/
protected function getHashedPassword($method, $password, $salt = null)
{
@ -179,9 +179,9 @@ trait HasPassword
/**
* Validates that the current LDAP connection is secure.
*
* @return void
*
* @throws ConnectionException
*
* @return void
*/
protected function validateSecureConnection()
{

View File

@ -5,7 +5,7 @@ namespace LdapRecord\Models\Concerns;
use LdapRecord\Models\Relations\HasMany;
use LdapRecord\Models\Relations\HasManyIn;
use LdapRecord\Models\Relations\HasOne;
use Tightenco\Collect\Support\Arr;
use LdapRecord\Support\Arr;
trait HasRelationships
{

View File

@ -24,7 +24,7 @@ class Entry extends BaseEntry implements FreeIPA
* @var array
*/
protected $defaultDates = [
'krblastpwdchange' => 'ldap',
'krblastpwdchange' => 'ldap',
'krbpasswordexpiration' => 'ldap',
];

View File

@ -13,6 +13,7 @@ use LdapRecord\Models\Attributes\Guid;
use LdapRecord\Models\Events\Renamed;
use LdapRecord\Models\Events\Renaming;
use LdapRecord\Query\Model\Builder;
use LdapRecord\Support\Arr;
use UnexpectedValueException;
/** @mixin Builder */
@ -675,7 +676,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
}
/**
* Get the models batch modifications to be processed.
* Get the model's batch modifications to be processed.
*
* @return array
*/
@ -713,9 +714,9 @@ abstract class Model implements ArrayAccess, JsonSerializable
*
* @param array|BatchModification $mod
*
* @return $this
*
* @throws InvalidArgumentException
*
* @return $this
*/
public function addModification($mod = [])
{
@ -735,7 +736,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
}
/**
* Get the models guid attribute key name.
* Get the model's guid attribute key name.
*
* @return string
*/
@ -745,7 +746,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
}
/**
* Get the models ANR attributes for querying when incompatible with ANR.
* Get the model's ANR attributes for querying when incompatible with ANR.
*
* @return array
*/
@ -803,7 +804,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
}
/**
* Get the models binary object GUID.
* Get the model's binary object GUID.
*
* @link https://msdn.microsoft.com/en-us/library/ms679021(v=vs.85).aspx
*
@ -815,7 +816,17 @@ abstract class Model implements ArrayAccess, JsonSerializable
}
/**
* Get the models string GUID.
* Get the model's object classes.
*
* @return array
*/
public function getObjectClasses()
{
return $this->getAttribute('objectclass') ?: [];
}
/**
* Get the model's string GUID.
*
* @return string|null
*/
@ -914,9 +925,9 @@ abstract class Model implements ArrayAccess, JsonSerializable
*
* @param array $attributes The attributes to update or create for the current entry.
*
* @return void
*
* @throws \LdapRecord\LdapRecordException
*
* @return void
*/
public function save(array $attributes = [])
{
@ -934,9 +945,9 @@ abstract class Model implements ArrayAccess, JsonSerializable
/**
* Inserts the model into the directory.
*
* @return void
*
* @throws \LdapRecord\LdapRecordException
*
* @return void
*/
protected function performInsert()
{
@ -975,9 +986,9 @@ abstract class Model implements ArrayAccess, JsonSerializable
/**
* Updates the model in the directory.
*
* @return void
*
* @throws \LdapRecord\LdapRecordException
*
* @return void
*/
protected function performUpdate()
{
@ -1020,10 +1031,10 @@ abstract class Model implements ArrayAccess, JsonSerializable
* @param string $attribute The attribute to create
* @param mixed $value The value of the new attribute
*
* @return void
*
* @throws ModelDoesNotExistException
* @throws \LdapRecord\LdapRecordException
*
* @return void
*/
public function createAttribute($attribute, $value)
{
@ -1039,10 +1050,10 @@ abstract class Model implements ArrayAccess, JsonSerializable
*
* @param array $attributes The attributes to update for the current entry.
*
* @return void
*
* @throws ModelDoesNotExistException
* @throws \LdapRecord\LdapRecordException
*
* @return void
*/
public function update(array $attributes = [])
{
@ -1057,10 +1068,10 @@ abstract class Model implements ArrayAccess, JsonSerializable
* @param string $attribute The attribute to modify
* @param mixed $value The new value for the attribute
*
* @return void
*
* @throws ModelDoesNotExistException
* @throws \LdapRecord\LdapRecordException
*
* @return void
*/
public function updateAttribute($attribute, $value)
{
@ -1077,9 +1088,9 @@ abstract class Model implements ArrayAccess, JsonSerializable
* @param Collection|array|string $dns
* @param bool $recursive
*
* @return int
*
* @throws \LdapRecord\LdapRecordException
*
* @return int
*/
public static function destroy($dns, $recursive = false)
{
@ -1110,10 +1121,10 @@ abstract class Model implements ArrayAccess, JsonSerializable
*
* @param bool $recursive Whether to recursively delete leaf nodes (models that are children).
*
* @return void
*
* @throws ModelDoesNotExistException
* @throws \LdapRecord\LdapRecordException
*
* @return void
*/
public function delete($recursive = false)
{
@ -1138,9 +1149,9 @@ abstract class Model implements ArrayAccess, JsonSerializable
/**
* Deletes leaf nodes that are attached to the model.
*
* @return Collection
*
* @throws \LdapRecord\LdapRecordException
*
* @return Collection
*/
protected function deleteLeafNodes()
{
@ -1160,38 +1171,36 @@ abstract class Model implements ArrayAccess, JsonSerializable
*
* Delete specific values in attributes:
*
* ["memberuid" => "username"]
* ["memberuid" => "jdoe"]
*
* Delete an entire attribute:
*
* ["memberuid" => []]
*
* @return void
*
* @throws ModelDoesNotExistException
* @throws \LdapRecord\LdapRecordException
*
* @return void
*/
public function deleteAttribute($attributes)
{
$this->validateExistence();
// If we have been given a string, we will assume we're
// removing a single attribute. Otherwise, we will
// assume it's an array of attributes to remove.
$attributes = is_string($attributes) ? [$attributes => []] : $attributes;
$attributes = $this->makeDeletableAttributes($attributes);
$this->newQuery()->deleteAttributes($this->dn, $attributes);
foreach ($attributes as $attribute => $value) {
// If the attribute value is empty, we will remove
// the attribute from the model and continue on.
// If the attribute value is empty, we can assume the
// attribute was completely deleted from the model.
// We will pull the attribute out and continue on.
if (empty($value)) {
unset($this->attributes[$attribute]);
}
// Otherwise, only specific attribute values have been
// removed. We will determine which ones have been
// removed and update the attributes value.
else {
elseif (Arr::exists($this->attributes, $attribute)) {
$this->attributes[$attribute] = array_values(
array_diff($this->attributes[$attribute], (array) $value)
);
@ -1201,6 +1210,26 @@ abstract class Model implements ArrayAccess, JsonSerializable
$this->syncOriginal();
}
/**
* Make a deletable attribute array.
*
* @param string|array $attributes
*
* @return array
*/
protected function makeDeletableAttributes($attributes)
{
$delete = [];
foreach (Arr::wrap($attributes) as $key => $value) {
is_int($key)
? $delete[$value] = []
: $delete[$key] = Arr::wrap($value);
}
return $delete;
}
/**
* Move the model into the given new parent.
*
@ -1209,11 +1238,11 @@ abstract class Model implements ArrayAccess, JsonSerializable
* @param static|string $newParentDn The new parent of the current model.
* @param bool $deleteOldRdn Whether to delete the old models relative distinguished name once renamed / moved.
*
* @return void
*
* @throws UnexpectedValueException
* @throws ModelDoesNotExistException
* @throws \LdapRecord\LdapRecordException
*
* @return void
*/
public function move($newParentDn, $deleteOldRdn = true)
{
@ -1233,10 +1262,10 @@ abstract class Model implements ArrayAccess, JsonSerializable
* @param static|string|null $newParentDn The models new parent distinguished name (if moving). Leave this null if you are only renaming. Example: "ou=MovedUsers,dc=acme,dc=org"
* @param bool|true $deleteOldRdn Whether to delete the old models relative distinguished name once renamed / moved.
*
* @return void
*
* @throws ModelDoesNotExistException
* @throws \LdapRecord\LdapRecordException
*
* @return void
*/
public function rename($rdn, $newParentDn = null, $deleteOldRdn = true)
{
@ -1339,9 +1368,9 @@ abstract class Model implements ArrayAccess, JsonSerializable
*/
protected function isValidModification($mod)
{
return is_array($mod) &&
array_key_exists(BatchModification::KEY_MODTYPE, $mod) &&
array_key_exists(BatchModification::KEY_ATTRIB, $mod);
return Arr::accessible($mod)
&& Arr::exists($mod, BatchModification::KEY_MODTYPE)
&& Arr::exists($mod, BatchModification::KEY_ATTRIB);
}
/**
@ -1356,7 +1385,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
foreach ($this->getDirty() as $attribute => $values) {
$modification = $this->newBatchModification($attribute, null, (array) $values);
if (array_key_exists($attribute, $this->original)) {
if (Arr::exists($this->original, $attribute)) {
// If the attribute we're modifying has an original value, we will
// give the BatchModification object its values to automatically
// determine which type of LDAP operation we need to perform.
@ -1376,9 +1405,9 @@ abstract class Model implements ArrayAccess, JsonSerializable
/**
* Validates that the current model exists.
*
* @return void
*
* @throws ModelDoesNotExistException
*
* @return void
*/
protected function validateExistence()
{

View File

@ -268,9 +268,9 @@ class HasMany extends OneToMany
*
* @param string $model
*
* @return Model
*
* @throws ModelNotFoundException
*
* @return Model
*/
protected function getForeignModelByValueOrFail($model)
{
@ -293,9 +293,9 @@ class HasMany extends OneToMany
* @param string|array $bypass
* @param mixed $value
*
* @return mixed
*
* @throws LdapRecordException
*
* @return mixed
*/
protected function attemptFailableOperation($operation, $bypass, $value)
{

View File

@ -27,9 +27,9 @@ class HasOne extends Relation
*
* @param Model|string $model
*
* @return Model|string
*
* @throws \LdapRecord\LdapRecordException
*
* @return Model|string
*/
public function attach($model)
{
@ -45,9 +45,9 @@ class HasOne extends Relation
/**
* Detach the related model from the parent.
*
* @return void
*
* @throws \LdapRecord\LdapRecordException
*
* @return void
*/
public function detach()
{

View File

@ -343,13 +343,11 @@ abstract class Relation
*/
protected function determineModelFromRelated(Model $model, array $related)
{
$objectClasses = $model->getAttribute('objectclass') ?? [];
// We must normalize all the related models object class
// names to the same case so we are able to properly
// determine the owning model from search results.
return array_search(
$this->normalizeObjectClasses($objectClasses),
$this->normalizeObjectClasses($model->getObjectClasses()),
array_map([$this, 'normalizeObjectClasses'], $related)
);
}

View File

@ -43,7 +43,7 @@ class ArrayCacheStore implements CacheInterface
public function set($key, $value, $ttl = null)
{
$this->storage[$key] = [
'value' => $value,
'value' => $value,
'expiresAt' => $this->parseDateInterval($ttl),
];

View File

@ -14,10 +14,10 @@ use LdapRecord\LdapRecordException;
use LdapRecord\Models\Model;
use LdapRecord\Query\Events\QueryExecuted;
use LdapRecord\Query\Model\Builder as ModelBuilder;
use LdapRecord\Query\Pagination\DeprecatedPaginator;
use LdapRecord\Query\Pagination\LazyPaginator;
use LdapRecord\Query\Pagination\Paginator;
use LdapRecord\Support\Arr;
use LdapRecord\Utilities;
use Tightenco\Collect\Support\Arr;
class Builder
{
@ -37,7 +37,7 @@ class Builder
*/
public $filters = [
'and' => [],
'or' => [],
'or' => [],
'raw' => [],
];
@ -484,6 +484,60 @@ class Builder
return $this->process($pages);
}
/**
* Runs the paginate operation with the given filter.
*
* @param string $filter
* @param int $perPage
* @param bool $isCritical
*
* @return array
*/
protected function runPaginate($filter, $perPage, $isCritical)
{
return $this->connection->run(function (LdapInterface $ldap) use ($filter, $perPage, $isCritical) {
return (new Paginator($this, $filter, $perPage, $isCritical))->execute($ldap);
});
}
/**
* Chunk the results of a paginated LDAP query.
*
* @param int $pageSize
* @param Closure $callback
* @param bool $isCritical
*
* @return void
*/
public function chunk($pageSize, Closure $callback, $isCritical = false)
{
$start = microtime(true);
$query = $this->getQuery();
foreach ($this->runChunk($query, $pageSize, $isCritical) as $chunk) {
$callback($this->process($chunk));
}
$this->logQuery($this, 'chunk', $this->getElapsedTime($start));
}
/**
* Runs the chunk operation with the given filter.
*
* @param string $filter
* @param int $perPage
* @param bool $isCritical
*
* @return array
*/
protected function runChunk($filter, $perPage, $isCritical)
{
return $this->connection->run(function (LdapInterface $ldap) use ($filter, $perPage, $isCritical) {
return (new LazyPaginator($this, $filter, $perPage, $isCritical))->execute($ldap);
});
}
/**
* Processes and converts the given LDAP results into models.
*
@ -574,26 +628,6 @@ class Builder
});
}
/**
* Runs the paginate operation with the given filter.
*
* @param string $filter
* @param int $perPage
* @param bool $isCritical
*
* @return array
*/
protected function runPaginate($filter, $perPage, $isCritical)
{
return $this->connection->run(function (LdapInterface $ldap) use ($filter, $perPage, $isCritical) {
$paginator = $ldap->supportsServerControlsInMethods()
? new Paginator($this, $filter, $perPage, $isCritical)
: new DeprecatedPaginator($this, $filter, $perPage, $isCritical);
return $paginator->execute($ldap);
});
}
/**
* Parses the given LDAP resource by retrieving its entries.
*
@ -660,9 +694,9 @@ class Builder
*
* @param array|string $columns
*
* @return Model|static
*
* @throws ObjectNotFoundException
*
* @return Model|static
*/
public function firstOrFail($columns = ['*'])
{
@ -713,9 +747,9 @@ class Builder
* @param string $value
* @param array|string $columns
*
* @return Model
*
* @throws ObjectNotFoundException
*
* @return Model
*/
public function findByOrFail($attribute, $value, $columns = ['*'])
{
@ -796,9 +830,9 @@ class Builder
* @param string $dn
* @param array|string $columns
*
* @return Model|static
*
* @throws ObjectNotFoundException
*
* @return Model|static
*/
public function findOrFail($dn, $columns = ['*'])
{
@ -917,27 +951,24 @@ class Builder
* @param string $boolean
* @param bool $raw
*
* @return $this
*
* @throws InvalidArgumentException
*
* @return $this
*/
public function where($field, $operator = null, $value = null, $boolean = 'and', $raw = false)
{
if (is_array($field)) {
// If the field is an array, we will assume it is an array of
// key-value pairs and can add them each as a where clause.
// If the field is an array, we will assume we have been
// provided with an array of key-value pairs and can
// add them each as their own seperate where clause.
return $this->addArrayOfWheres($field, $boolean, $raw);
}
// We'll bypass the 'has' and 'notHas' operator since they
// only require two arguments inside the where method.
$bypass = ['*', '!*'];
// Here we will make some assumptions about the operator. If only
// 2 values are passed to the method, we will assume that
// the operator is 'equals' and keep going.
if (func_num_args() === 2 && in_array($operator, $bypass) === false) {
list($value, $operator) = [$operator, '='];
// If we have been provided with two arguments not a "has" or
// "not has" operator, we'll assume the developer is creating
// an "equals" clause and set the proper operator in place.
if (func_num_args() === 2 && ! in_array($operator, ['*', '!*'])) {
[$value, $operator] = [$operator, '='];
}
if (! in_array($operator, $this->grammar->getOperators())) {
@ -1378,30 +1409,28 @@ class Builder
}
/**
* Adds a filter onto the current query.
* Adds a filter binding onto the current query.
*
* @param string $type The type of filter to add.
* @param array $bindings The bindings of the filter.
*
* @return $this
*
* @throws InvalidArgumentException
*
* @return $this
*/
public function addFilter($type, array $bindings)
{
if (! array_key_exists($type, $this->filters)) {
throw new InvalidArgumentException("Filter type [$type] is invalid.");
throw new InvalidArgumentException("Filter type: [$type] is invalid.");
}
// The required filter key bindings.
$required = ['field', 'operator', 'value'];
// Each filter clause require key bindings to be set. We
// will validate this here to ensure all of them have
// been provided, or throw an exception otherwise.
if ($missing = $this->missingBindingKeys($bindings)) {
$keys = implode(', ', $missing);
// Here we will ensure the proper key bindings are given.
if (count(array_intersect_key(array_flip($required), $bindings)) !== count($required)) {
// Retrieve the keys that are missing in the bindings array.
$missing = implode(', ', array_diff($required, array_flip($bindings)));
throw new InvalidArgumentException("Invalid filter bindings. Missing: [$missing] keys.");
throw new InvalidArgumentException("Invalid filter bindings. Missing: [$keys] keys.");
}
$this->filters[$type][] = $bindings;
@ -1409,6 +1438,22 @@ class Builder
return $this;
}
/**
* Extract any missing required binding keys.
*
* @param array $bindings
*
* @return array
*/
protected function missingBindingKeys($bindings)
{
$required = array_flip(['field', 'operator', 'value']);
$existing = array_intersect_key($required, $bindings);
return array_keys(array_diff_key($required, $existing));
}
/**
* Get all the filters on the query.
*
@ -1426,7 +1471,7 @@ class Builder
*/
public function clearFilters()
{
foreach ($this->filters as $type => $filters) {
foreach (array_keys($this->filters) as $type) {
$this->filters[$type] = [];
}
@ -1565,9 +1610,9 @@ class Builder
* @param string $dn
* @param array $attributes
*
* @return bool
*
* @throws LdapRecordException
*
* @return bool
*/
public function insert($dn, array $attributes)
{
@ -1683,9 +1728,9 @@ class Builder
* @param string $method
* @param array $parameters
*
* @return mixed
*
* @throws BadMethodCallException
*
* @return mixed
*/
public function __call($method, $parameters)
{
@ -1760,7 +1805,7 @@ class Builder
if (is_numeric($key) && is_array($value)) {
// If the key is numeric and the value is an array, we'll
// assume we've been given an array with conditionals.
list($field, $condition) = $value;
[$field, $condition] = $value;
// Since a value is optional for some conditionals, we will
// try and retrieve the third parameter from the array,
@ -1818,6 +1863,9 @@ class Builder
case 'read':
$event = new Events\Read(...$args);
break;
case 'chunk':
$event = new Events\Chunk(...$args);
break;
case 'paginate':
$event = new Events\Paginate(...$args);
break;

View File

@ -0,0 +1,8 @@
<?php
namespace LdapRecord\Query\Events;
class Chunk extends QueryExecuted
{
//
}

View File

@ -12,20 +12,20 @@ class Grammar
* @var array
*/
public $operators = [
'*' => 'has',
'!*' => 'notHas',
'=' => 'equals',
'!' => 'doesNotEqual',
'!=' => 'doesNotEqual',
'>=' => 'greaterThanOrEquals',
'<=' => 'lessThanOrEquals',
'~=' => 'approximatelyEquals',
'starts_with' => 'startsWith',
'*' => 'has',
'!*' => 'notHas',
'=' => 'equals',
'!' => 'doesNotEqual',
'!=' => 'doesNotEqual',
'>=' => 'greaterThanOrEquals',
'<=' => 'lessThanOrEquals',
'~=' => 'approximatelyEquals',
'starts_with' => 'startsWith',
'not_starts_with' => 'notStartsWith',
'ends_with' => 'endsWith',
'not_ends_with' => 'notEndsWith',
'contains' => 'contains',
'not_contains' => 'notContains',
'ends_with' => 'endsWith',
'not_ends_with' => 'notEndsWith',
'contains' => 'contains',
'not_contains' => 'notContains',
];
/**
@ -142,15 +142,17 @@ class Grammar
{
$filter = $this->compileWheres($query, 'or');
if ($this->hasMultipleFilters($query)) {
// Here we will detect whether the entire query can be
// wrapped inside of an "or" statement by checking
// how many filter statements exist for each type.
if ($this->queryCanBeWrappedInSingleOrStatement($query)) {
$this->wrapper = 'or';
} else {
$filter = $this->compileOr($filter);
}
if (! $this->hasMultipleFilters($query)) {
return $filter;
}
// Here we will detect whether the entire query can be
// wrapped inside of an "or" statement by checking
// how many filter statements exist for each type.
if ($this->queryCanBeWrappedInSingleOrStatement($query)) {
$this->wrapper = 'or';
} else {
$filter = $this->compileOr($filter);
}
return $filter;
@ -270,7 +272,9 @@ class Grammar
*/
public function compileDoesNotEqual($field, $value)
{
return $this->compileNot($this->compileEquals($field, $value));
return $this->compileNot(
$this->compileEquals($field, $value)
);
}
/**
@ -360,7 +364,9 @@ class Grammar
*/
public function compileNotStartsWith($field, $value)
{
return $this->compileNot($this->compileStartsWith($field, $value));
return $this->compileNot(
$this->compileStartsWith($field, $value)
);
}
/**
@ -420,7 +426,9 @@ class Grammar
*/
public function compileNotContains($field, $value)
{
return $this->compileNot($this->compileContains($field, $value));
return $this->compileNot(
$this->compileContains($field, $value)
);
}
/**
@ -448,7 +456,9 @@ class Grammar
*/
public function compileNotHas($field)
{
return $this->compileNot($this->compileHas($field));
return $this->compileNot(
$this->compileHas($field)
);
}
/**
@ -496,18 +506,44 @@ class Grammar
*
* @param array $where
*
* @return string
*
* @throws UnexpectedValueException
*
* @return string
*/
protected function compileWhere(array $where)
{
if (! array_key_exists($where['operator'], $this->operators)) {
throw new UnexpectedValueException('Invalid LDAP filter operator ['.$where['operator'].']');
}
$method = 'compile'.ucfirst($this->operators[$where['operator']]);
$method = $this->makeCompileMethod($where['operator']);
return $this->{$method}($where['field'], $where['value']);
}
/**
* Make the compile method name for the operator.
*
* @param string $operator
*
* @throws UnexpectedValueException
*
* @return string
*/
protected function makeCompileMethod($operator)
{
if (! $this->operatorExists($operator)) {
throw new UnexpectedValueException("Invalid LDAP filter operator ['$operator']");
}
return 'compile'.ucfirst($this->operators[$operator]);
}
/**
* Determine if the operator exists.
*
* @param string $operator
*
* @return bool
*/
protected function operatorExists($operator)
{
return array_key_exists($operator, $this->operators);
}
}

View File

@ -34,9 +34,9 @@ class ActiveDirectoryBuilder extends Builder
* @param string $sid
* @param array|string $columns
*
* @return \LdapRecord\Models\ActiveDirectory\Entry|static
*
* @throws ModelNotFoundException
*
* @return \LdapRecord\Models\ActiveDirectory\Entry|static
*/
public function findBySidOrFail($sid, $columns = [])
{

View File

@ -181,9 +181,9 @@ class Builder extends BaseBuilder
* @param string $value
* @param array|string $columns
*
* @return Model
*
* @throws ModelNotFoundException
*
* @return Model
*/
public function findByAnrOrFail($value, $columns = ['*'])
{
@ -271,9 +271,9 @@ class Builder extends BaseBuilder
* @param string $guid
* @param array|string $columns
*
* @return Model|static
*
* @throws ModelNotFoundException
*
* @return Model|static
*/
public function findByGuidOrFail($guid, $columns = ['*'])
{

View File

@ -4,6 +4,9 @@ namespace LdapRecord\Query\Pagination;
use LdapRecord\LdapInterface;
/**
* @deprecated
*/
class DeprecatedPaginator extends AbstractPaginator
{
/**

View File

@ -0,0 +1,34 @@
<?php
namespace LdapRecord\Query\Pagination;
use LdapRecord\LdapInterface;
class LazyPaginator extends Paginator
{
/**
* Execute the pagination request.
*
* @param LdapInterface $ldap
*
* @return Generator
*/
public function execute(LdapInterface $ldap)
{
$this->prepareServerControls();
do {
$this->applyServerControls($ldap);
if (! $resource = $this->query->run($this->filter)) {
break;
}
$this->updateServerControls($ldap, $resource);
yield $this->query->parse($resource);
} while (! empty($this->fetchCookie()));
$this->resetServerControls($ldap);
}
}

View File

@ -0,0 +1,139 @@
<?php
namespace LdapRecord\Support;
use ArrayAccess;
class Arr
{
/**
* Determine whether the given value is array accessible.
*
* @param mixed $value
*
* @return bool
*/
public static function accessible($value)
{
return is_array($value) || $value instanceof ArrayAccess;
}
/**
* Determine if the given key exists in the provided array.
*
* @param \ArrayAccess|array $array
* @param string|int $key
*
* @return bool
*/
public static function exists($array, $key)
{
if ($array instanceof ArrayAccess) {
return $array->offsetExists($key);
}
return array_key_exists($key, $array);
}
/**
* If the given value is not an array and not null, wrap it in one.
*
* @param mixed $value
*
* @return array
*/
public static function wrap($value)
{
if (is_null($value)) {
return [];
}
return is_array($value) ? $value : [$value];
}
/**
* Return the first element in an array passing a given truth test.
*
* @param iterable $array
* @param callable|null $callback
* @param mixed $default
*
* @return mixed
*/
public static function first($array, callable $callback = null, $default = null)
{
if (is_null($callback)) {
if (empty($array)) {
return Helpers::value($default);
}
foreach ($array as $item) {
return $item;
}
}
foreach ($array as $key => $value) {
if ($callback($value, $key)) {
return $value;
}
}
return Helpers::value($default);
}
/**
* Return the last element in an array passing a given truth test.
*
* @param array $array
* @param callable|null $callback
* @param mixed $default
*
* @return mixed
*/
public static function last($array, callable $callback = null, $default = null)
{
if (is_null($callback)) {
return empty($array) ? Helpers::value($default) : end($array);
}
return static::first(array_reverse($array, true), $callback, $default);
}
/**
* Get an item from an array using "dot" notation.
*
* @param ArrayAccess|array $array
* @param string|int|null $key
* @param mixed $default
*
* @return mixed
*/
public static function get($array, $key, $default = null)
{
if (! static::accessible($array)) {
return Helpers::value($default);
}
if (is_null($key)) {
return $array;
}
if (static::exists($array, $key)) {
return $array[$key];
}
if (strpos($key, '.') === false) {
return $array[$key] ?? Helpers::value($default);
}
foreach (explode('.', $key) as $segment) {
if (static::accessible($array) && static::exists($array, $segment)) {
$array = $array[$segment];
} else {
return Helpers::value($default);
}
}
return $array;
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace LdapRecord\Support;
use Closure;
class Helpers
{
/**
* Return the default value of the given value.
*
* @param mixed $value
*
* @return mixed
*/
public static function value($value)
{
return $value instanceof Closure ? $value() : $value;
}
}

View File

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

View File

@ -11,9 +11,9 @@ class DirectoryFake
*
* @param string|null $name
*
* @return ConnectionFake
*
* @throws \LdapRecord\ContainerException
*
* @return ConnectionFake
*/
public static function setup($name = null)
{

View File

@ -5,6 +5,7 @@ namespace LdapRecord\Testing;
use Exception;
use LdapRecord\DetailedError;
use LdapRecord\LdapBase;
use LdapRecord\Support\Arr;
use PHPUnit\Framework\Assert as PHPUnit;
use PHPUnit\Framework\Constraint\Constraint;
@ -73,7 +74,7 @@ class LdapFake extends LdapBase
*/
public function expect($expectations = [])
{
$expectations = is_array($expectations) ? $expectations : [$expectations];
$expectations = Arr::wrap($expectations);
foreach ($expectations as $key => $expectation) {
// If the key is non-numeric, we will assume
@ -285,7 +286,7 @@ class LdapFake extends LdapBase
{
$this->bound = false;
$this->host = $this->getConnectionString($hosts, $port);
$this->host = $this->makeConnectionUris($hosts, $port);
return $this->connection = $this->hasExpectations('connect')
? $this->resolveExpectation('connect', func_get_args())
@ -448,9 +449,9 @@ class LdapFake extends LdapBase
* @param string $method
* @param array $args
*
* @return mixed
*
* @throws Exception
*
* @return mixed
*/
protected function resolveExpectation($method, $args = [])
{

View File

@ -0,0 +1,20 @@
<?php
namespace Illuminate\Contracts\Broadcasting;
interface HasBroadcastChannel
{
/**
* Get the broadcast channel route definition that is associated with the given entity.
*
* @return string
*/
public function broadcastChannelRoute();
/**
* Get the broadcast channel name that is associated with the given entity.
*
* @return string
*/
public function broadcastChannel();
}

View File

@ -7,8 +7,8 @@ interface SupportsPartialRelations
/**
* Indicate that the relation is a single result of a larger one-to-many relationship.
*
* @param \Closure|string|null $column
* @param string|null $relation
* @param string|null $column
* @param string|\Closure|null $aggregate
* @param string $relation
* @return $this
*/
@ -20,4 +20,11 @@ interface SupportsPartialRelations
* @return bool
*/
public function isOneOfMany();
/**
* Get the one of many inner join subselect query builder instance.
*
* @return \Illuminate\Database\Eloquent\Builder|void
*/
public function getOneOfManySubQuery();
}

View File

@ -0,0 +1,14 @@
<?php
namespace Illuminate\Contracts\Validation;
interface ValidatorAwareRule
{
/**
* Set the current validator.
*
* @param \Illuminate\Validation\Validator $validator
* @return $this
*/
public function setValidator($validator);
}

View File

@ -117,21 +117,28 @@ This project exists thanks to all the people who contribute.
[Thanks to people helping us to translate Carbon in so many languages](https://carbon.nesbot.com/contribute/translators/)
### Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/Carbon#backer)]
<a href="https://opencollective.com/Carbon#backers" target="_blank"><img src="https://opencollective.com/Carbon/backers.svg?width=890"></a>
### Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/Carbon#sponsor)]
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://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>
<a href="https://opencollective.com/Carbon/sponsor/3/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/Carbon/sponsor/4/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/4/avatar.svg"></a>
[[Become a sponsor](https://opencollective.com/Carbon#sponsor)]
### Backers
Thank you to all our backers! 🙏
<a href="https://opencollective.com/Carbon#backers" target="_blank"><img src="https://opencollective.com/Carbon/backers.svg?width=890"></a>
[[Become a backer](https://opencollective.com/Carbon#backer)]
## Carbon for enterprise
Available as part of the Tidelift Subscription.

View File

@ -1226,6 +1226,25 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*/
public static function createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null);
/**
* Create a new Carbon instance from a specific date and time using strict validation.
*
* @see create()
*
* @param int|null $year
* @param int|null $month
* @param int|null $day
* @param int|null $hour
* @param int|null $minute
* @param int|null $second
* @param DateTimeZone|string|null $tz
*
* @throws InvalidFormatException
*
* @return static
*/
public static function createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $tz = null);
/**
* Get/set the day of year.
*
@ -2284,7 +2303,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @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);
/**
* Returns raw translation message for a given key.
@ -2296,7 +2315,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @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);
/**
* Get the default translator instance in use.
@ -2934,7 +2953,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @return string
*/
public function isoFormat(string $format, string $originalFormat = null): string;
public function isoFormat(string $format, ?string $originalFormat = null): string;
/**
* Get/set the week number using given first day of week and first
@ -3066,7 +3085,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @return $this|string
*/
public function locale(string $locale = null, ...$fallbackLocales);
public function locale(?string $locale = null, ...$fallbackLocales);
/**
* Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow).
@ -3423,7 +3442,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @return string
*/
public function ordinal(string $key, string $period = null): string;
public function ordinal(string $key, ?string $period = null): string;
/**
* Create a carbon instance from a string.
@ -4737,7 +4756,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @return string
*/
public function translate(string $key, array $parameters = [], $number = null, \Symfony\Component\Translation\TranslatorInterface $translator = null, bool $altNumbers = false): string;
public function translate(string $key, array $parameters = [], $number = null, ?\Symfony\Component\Translation\TranslatorInterface $translator = null, bool $altNumbers = false): string;
/**
* Returns the alternative number for a given integer if available in the current locale.
@ -4907,7 +4926,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
*
* @return int|static
*/
public function utcOffset(int $minuteOffset = null);
public function utcOffset(?int $minuteOffset = null);
/**
* Returns the milliseconds timestamps used amongst other by Date javascript objects.

View File

@ -27,6 +27,7 @@ use Closure;
use DateInterval;
use Exception;
use ReflectionException;
use ReturnTypeWillChange;
use Throwable;
/**
@ -522,6 +523,8 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
$interval = implode($match[1], $interval);
}
$interval = $interval ?? '';
for ($index = 0; $index < $length; $index++) {
$expected = mb_substr($format, $index, 1);
$nextCharacter = mb_substr($interval, 0, 1);
@ -963,6 +966,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
*
* @link http://php.net/manual/en/dateinterval.createfromdatestring.php
*/
#[ReturnTypeWillChange]
public static function createFromDateString($time)
{
$interval = @parent::createFromDateString(strtr($time, [

View File

@ -479,7 +479,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
$interval = $part;
} elseif ($start === null && $parsed = Carbon::make($part)) {
$start = $part;
} elseif ($end === null && $parsed = Carbon::make(static::addMissingParts($start, $part))) {
} elseif ($end === null && $parsed = Carbon::make(static::addMissingParts($start ?? '', $part))) {
$end = $part;
} else {
throw new InvalidPeriodParameterException("Invalid ISO 8601 specification: $iso.");
@ -641,7 +641,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
if ($this->dateInterval === null &&
(
\is_string($argument) && preg_match(
'/^(\d(\d(?![\/-])|[^\d\/-]([\/-])?)*|P[T0-9].*|(?:\h*\d+(?:\.\d+)?\h*[a-z]+)+)$/i',
'/^(-?\d(\d(?![\/-])|[^\d\/-]([\/-])?)*|P[T0-9].*|(?:\h*\d+(?:\.\d+)?\h*[a-z]+)+)$/i',
$argument
) ||
$argument instanceof DateInterval ||

View File

@ -13,8 +13,14 @@ use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\ConversionException;
use Exception;
/**
* @template T of CarbonInterface
*/
trait CarbonTypeConverter
{
/**
* @return class-string<T>
*/
protected function getCarbonClassName(): string
{
return Carbon::class;
@ -42,6 +48,8 @@ trait CarbonTypeConverter
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @return T|null
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
@ -78,6 +86,8 @@ trait CarbonTypeConverter
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @return string|null
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{

View File

@ -11,8 +11,12 @@ use Doctrine\DBAL\Types\VarDateTimeImmutableType;
class DateTimeImmutableType extends VarDateTimeImmutableType implements CarbonDoctrineType
{
/** @use CarbonTypeConverter<CarbonImmutable> */
use CarbonTypeConverter;
/**
* @return class-string<CarbonImmutable>
*/
protected function getCarbonClassName(): string
{
return CarbonImmutable::class;

View File

@ -6,9 +6,11 @@
*/
namespace Carbon\Doctrine;
use Carbon\Carbon;
use Doctrine\DBAL\Types\VarDateTimeType;
class DateTimeType extends VarDateTimeType implements CarbonDoctrineType
{
/** @use CarbonTypeConverter<Carbon> */
use CarbonTypeConverter;
}

View File

@ -52,6 +52,7 @@ use ReflectionMethod;
* will be 0.
* If one of the set values is not valid, an InvalidDateException
* will be thrown.
* @method CarbonInterface createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $tz = null) Create a new Carbon instance from a specific date and time using strict validation.
* @method Carbon disableHumanDiffOption($humanDiffOption) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
* You should rather use the ->settings() method.
* @method Carbon enableHumanDiffOption($humanDiffOption) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
@ -76,7 +77,7 @@ use ReflectionMethod;
* @method Closure|Carbon getTestNow() Get the Carbon instance (real or mock) to be returned when a "now"
* instance is created.
* @method string getTimeFormatByPrecision($unitPrecision) Return a format from H:i to H:i:s.u according to given unit precision.
* @method string getTranslationMessageWith($translator, string $key, string $locale = null, string $default = null) Returns raw translation message for a given key.
* @method string getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null) Returns raw translation message for a given key.
* @method \Symfony\Component\Translation\TranslatorInterface getTranslator() Get the default translator instance in use.
* @method int getWeekEndsAt() Get the last day of week
* @method int getWeekStartsAt() Get the first day of week

View File

@ -51,6 +51,7 @@ use Closure;
* will be 0.
* If one of the set values is not valid, an InvalidDateException
* will be thrown.
* @method CarbonInterface createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $tz = null) Create a new Carbon instance from a specific date and time using strict validation.
* @method CarbonImmutable disableHumanDiffOption($humanDiffOption) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
* You should rather use the ->settings() method.
* @method CarbonImmutable enableHumanDiffOption($humanDiffOption) @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
@ -75,7 +76,7 @@ use Closure;
* @method Closure|CarbonImmutable getTestNow() Get the Carbon instance (real or mock) to be returned when a "now"
* instance is created.
* @method string getTimeFormatByPrecision($unitPrecision) Return a format from H:i to H:i:s.u according to given unit precision.
* @method string getTranslationMessageWith($translator, string $key, string $locale = null, string $default = null) Returns raw translation message for a given key.
* @method string getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null) Returns raw translation message for a given key.
* @method \Symfony\Component\Translation\TranslatorInterface getTranslator() Get the default translator instance in use.
* @method int getWeekEndsAt() Get the last day of week
* @method int getWeekStartsAt() Get the first day of week

View File

@ -24,6 +24,7 @@ if (class_exists('Symfony\\Component\\Translation\\PluralizationRules')) {
* - Serhan Apaydın
* - JD Isaacks
* - AbadonnaAbbys
* - Siomkin Alexander
*/
return [
'year' => ':count год|:count гады|:count гадоў',
@ -35,18 +36,18 @@ return [
'week' => ':count тыдзень|:count тыдні|:count тыдняў',
'a_week' => '{1}тыдзень|:count тыдзень|:count тыдні|:count тыдняў',
'w' => ':count тыдзень|:count тыдні|:count тыдняў',
'day' => ':count дзень|:count ні|:count дзён',
'a_day' => '{1}дзень|:count дзень|:count ні|:count дзён',
'd' => ':count дзень|:count ні|:count дзён',
'day' => ':count дзень|:count дні|:count дзён',
'a_day' => '{1}дзень|:count дзень|:count дні|:count дзён',
'd' => ':count дн',
'hour' => ':count гадзіну|:count гадзіны|:count гадзін',
'a_hour' => '{1}гадзіна|:count гадзіна|:count гадзіны|:count гадзін',
'h' => ':count гадзіна|:count гадзіны|:count гадзін',
'minute' => ':count хвіліна|:count хвіліны|:count хвілін',
'a_minute' => '{1}хвіліна|:count хвіліна|:count хвіліны|:count хвілін',
'min' => ':count хвіліна|:count хвіліны|:count хвілін',
'min' => ':count хв',
'second' => ':count секунда|:count секунды|:count секунд',
'a_second' => '{1}некалькі секунд|:count секунда|:count секунды|:count секунд',
's' => ':count секунда|:count секунды|:count секунд',
's' => ':count сек',
'hour_ago' => ':count гадзіну|:count гадзіны|:count гадзін',
'a_hour_ago' => '{1}гадзіну|:count гадзіну|:count гадзіны|:count гадзін',

View File

@ -19,6 +19,7 @@ use Carbon\Exceptions\UnitException;
use Closure;
use DateTime;
use DateTimeImmutable;
use ReturnTypeWillChange;
/**
* Trait Converter.
@ -75,6 +76,7 @@ trait Converter
*
* @return string
*/
#[ReturnTypeWillChange]
public function format($format)
{
$function = $this->localFormatFunction ?: static::$formatFunction;

View File

@ -21,6 +21,7 @@ use Closure;
use DateTimeInterface;
use DateTimeZone;
use Exception;
use ReturnTypeWillChange;
/**
* Trait Creator.
@ -477,6 +478,37 @@ trait Creator
return $instance;
}
/**
* Create a new Carbon instance from a specific date and time using strict validation.
*
* @see create()
*
* @param int|null $year
* @param int|null $month
* @param int|null $day
* @param int|null $hour
* @param int|null $minute
* @param int|null $second
* @param DateTimeZone|string|null $tz
*
* @throws InvalidFormatException
*
* @return static
*/
public static function createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $tz = null): self
{
$initialStrictMode = static::isStrictModeEnabled();
static::useStrictMode(true);
try {
$date = static::create($year, $month, $day, $hour, $minute, $second, $tz);
} finally {
static::useStrictMode($initialStrictMode);
}
return $date;
}
/**
* Create a Carbon instance from just a date. The time portion is set to now.
*
@ -657,6 +689,7 @@ trait Creator
*
* @return static|false
*/
#[ReturnTypeWillChange]
public static function createFromFormat($format, $time, $tz = null)
{
$function = static::$createFromFormatFunction;
@ -899,6 +932,7 @@ trait Creator
/**
* {@inheritdoc}
*/
#[ReturnTypeWillChange]
public static function getLastErrors()
{
return static::$lastErrors;

View File

@ -31,6 +31,7 @@ use DateTimeInterface;
use DateTimeZone;
use InvalidArgumentException;
use ReflectionException;
use ReturnTypeWillChange;
use Throwable;
/**
@ -631,6 +632,7 @@ trait Date
*
* @link http://php.net/manual/en/datetime.gettimezone.php
*/
#[ReturnTypeWillChange]
public function getTimezone()
{
return CarbonTimeZone::instance(parent::getTimezone());
@ -737,6 +739,30 @@ trait Date
return $date instanceof self ? $date : static::instance($date);
}
/**
* Return the Carbon instance passed through, a now instance in UTC
* if null given or parse the input if string given (using current timezone
* then switching to UTC).
*
* @param Carbon|DateTimeInterface|string|null $date
*
* @return static
*/
protected function resolveUTC($date = null): self
{
if (!$date) {
return static::now('UTC');
}
if (\is_string($date)) {
return static::parse($date, $this->getTimezone())->utc();
}
static::expectDateTime($date, ['null', 'string']);
return $date instanceof self ? $date : static::instance($date)->utc();
}
/**
* Return the Carbon instance passed through, a now instance in the same timezone
* if null given or parse the input if string given.
@ -1398,6 +1424,7 @@ trait Date
*
* @return static
*/
#[ReturnTypeWillChange]
public function setDate($year, $month, $day)
{
return parent::setDate((int) $year, (int) $month, (int) $day);
@ -1414,6 +1441,7 @@ trait Date
*
* @return static
*/
#[ReturnTypeWillChange]
public function setISODate($year, $week, $day = 1)
{
return parent::setISODate((int) $year, (int) $week, (int) $day);
@ -1449,6 +1477,7 @@ trait Date
*
* @return static
*/
#[ReturnTypeWillChange]
public function setTime($hour, $minute, $second = 0, $microseconds = 0)
{
return parent::setTime((int) $hour, (int) $minute, (int) $second, (int) $microseconds);
@ -1463,6 +1492,7 @@ trait Date
*
* @return static
*/
#[ReturnTypeWillChange]
public function setTimestamp($unixTimestamp)
{
[$timestamp, $microseconds] = self::getIntegerAndDecimalParts($unixTimestamp);
@ -1521,6 +1551,7 @@ trait Date
*
* @return static
*/
#[ReturnTypeWillChange]
public function setTimezone($value)
{
return parent::setTimezone(static::safeCreateDateTimeZone($value));

View File

@ -19,6 +19,7 @@ use Carbon\Translator;
use Closure;
use DateInterval;
use DateTimeInterface;
use ReturnTypeWillChange;
/**
* Trait Difference.
@ -117,6 +118,7 @@ trait Difference
*
* @return DateInterval
*/
#[ReturnTypeWillChange]
public function diff($date = null, $absolute = false)
{
return parent::diff($this->resolveCarbon($date), (bool) $absolute);
@ -638,7 +640,7 @@ trait Difference
*/
public function floatDiffInRealDays($date = null, $absolute = true)
{
$date = $this->resolveCarbon($date)->utc();
$date = $this->resolveUTC($date);
$utc = $this->copy()->utc();
$hoursDiff = $utc->floatDiffInRealHours($date, $absolute);

View File

@ -11,6 +11,7 @@
namespace Carbon\Traits;
use Carbon\CarbonInterface;
use ReturnTypeWillChange;
/**
* Trait Modifiers.
@ -429,6 +430,7 @@ trait Modifiers
*
* @see https://php.net/manual/en/datetime.modify.php
*/
#[ReturnTypeWillChange]
public function modify($modify)
{
return parent::modify((string) $modify);

View File

@ -11,6 +11,7 @@
namespace Carbon\Traits;
use Carbon\Exceptions\InvalidFormatException;
use ReturnTypeWillChange;
/**
* Trait Serialization.
@ -91,6 +92,7 @@ trait Serialization
*
* @return static
*/
#[ReturnTypeWillChange]
public static function __set_state($dump)
{
if (\is_string($dump)) {
@ -125,6 +127,7 @@ trait Serialization
/**
* Set locale if specified on unserialize() called.
*/
#[ReturnTypeWillChange]
public function __wakeup()
{
if (get_parent_class() && method_exists(parent::class, '__wakeup')) {

View File

@ -16,6 +16,7 @@ use Carbon\CarbonInterval;
use Carbon\Exceptions\UnitException;
use Closure;
use DateInterval;
use ReturnTypeWillChange;
/**
* Trait Units.
@ -193,6 +194,7 @@ trait Units
*
* @return static
*/
#[ReturnTypeWillChange]
public function add($unit, $value = 1, $overflow = null)
{
if (\is_string($unit) && \func_num_args() === 1) {
@ -352,6 +354,7 @@ trait Units
*
* @return static
*/
#[ReturnTypeWillChange]
public function sub($unit, $value = 1, $overflow = null)
{
if (\is_string($unit) && \func_num_args() === 1) {

View File

@ -2,6 +2,11 @@
Please disclose any security issues or vulnerabilities found through [Tidelift's coordinated disclosure system](https://tidelift.com/security) or to the maintainers privately.
PHPMailer 6.4.1 and earlier contain a vulnerability that can result in untrusted code being called (if such code is injected into the host project's scope by other means). If the `$patternselect` parameter to `validateAddress()` is set to `'php'` (the default, defined by `PHPMailer::$validator`), and the global namespace contains a function called `php`, it will be called in preference to the built-in validator of the same name. Mitigated in PHPMailer 6.5.0 by denying the use of simple strings as validator function names. Recorded as [CVE-2021-3603](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2021-3603). Reported by [Vikrant Singh Chauhan](mailto:vi@hackberry.xyz) via [huntr.dev](https://www.huntr.dev/).
PHPMailer versions 6.4.1 and earlier contain a possible remote code execution vulnerability through the `$lang_path` parameter of the `setLanguage()` method. If the `$lang_path` parameter is passed unfiltered from user input, it can be set to [a UNC path](https://docs.microsoft.com/en-us/dotnet/standard/io/file-path-formats#unc-paths), and if an attacker is also able to persuade the server to load a file from that UNC path, a script file under their control may be executed. This vulnerability only applies to systems that resolve UNC paths, typically only Microsoft Windows.
PHPMailer 6.5.0 mitigates this by no longer treating translation files as PHP code, but by parsing their text content directly. This approach avoids the possibility of executing unknown code while retaining backward compatibility. This isn't ideal, so the current translation format is deprecated and will be replaced in the next major release. Recorded as [CVE-2021-34551](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2021-34551). Reported by [Jilin Diting Information Technology Co., Ltd](https://listensec.com) via Tidelift.
PHPMailer versions between 6.1.8 and 6.4.0 contain a regression of the earlier CVE-2018-19296 object injection vulnerability as a result of [a fix for Windows UNC paths in 6.1.8](https://github.com/PHPMailer/PHPMailer/commit/e2e07a355ee8ff36aba21d0242c5950c56e4c6f9). Recorded as [CVE-2020-36326](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2020-36326). Reported by Fariskhi Vidyan via Tidelift. 6.4.1 fixes this issue, and also enforces stricter checks for URL schemes in local path contexts.
PHPMailer versions 6.1.5 and earlier contain an output escaping bug that occurs in `Content-Type` and `Content-Disposition` when filenames passed into `addAttachment` and other methods that accept attachment names contain double quote characters, in contravention of RFC822 3.4.1. No specific vulnerability has been found relating to this, but it could allow file attachments to bypass attachment filters that are based on matching filename extensions. Recorded as [CVE-2020-13625](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2020-13625). Reported by Elar Lang of Clarified Security.

View File

@ -1 +1 @@
6.4.1
6.5.0

View File

@ -19,8 +19,7 @@ $PHPMAILER_LANG['instantiate'] = 'لا يمكن توفير خدمة ا
$PHPMAILER_LANG['invalid_address'] = 'الإرسال غير ممكن لأن عنوان البريد الإلكتروني غير صالح: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' برنامج الإرسال غير مدعوم.';
$PHPMAILER_LANG['provide_address'] = 'يجب توفير عنوان البريد الإلكتروني لمستلم واحد على الأقل.';
$PHPMAILER_LANG['recipients_failed'] = 'خطأ SMTP: الأخطاء التالية ' .
'فشل في الارسال لكل من : ';
$PHPMAILER_LANG['recipients_failed'] = 'خطأ SMTP: الأخطاء التالية فشل في الارسال لكل من : ';
$PHPMAILER_LANG['signing'] = 'خطأ في التوقيع: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() غير ممكن.';
$PHPMAILER_LANG['smtp_error'] = 'خطأ على مستوى الخادم SMTP: ';

View File

@ -428,9 +428,11 @@ class PHPMailer
public $Debugoutput = 'echo';
/**
* Whether to keep SMTP connection open after each message.
* If this is set to true then to close the connection
* requires an explicit call to smtpClose().
* Whether to keep the SMTP connection open after each message.
* If this is set to true then the connection will remain open after a send,
* and closing the connection will require an explicit call to smtpClose().
* It's a good idea to use this if you are sending multiple messages as it reduces overhead.
* See the mailing list example for how to use it.
*
* @var bool
*/
@ -748,7 +750,7 @@ class PHPMailer
*
* @var string
*/
const VERSION = '6.4.1';
const VERSION = '6.5.0';
/**
* Error severity: message only, continue processing.
@ -1335,7 +1337,8 @@ class PHPMailer
if (null === $patternselect) {
$patternselect = static::$validator;
}
if (is_callable($patternselect)) {
//Don't allow strings as callables, see SECURITY.md and CVE-2021-3603
if (is_callable($patternselect) && !is_string($patternselect)) {
return call_user_func($patternselect, $address);
}
//Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
@ -2182,7 +2185,8 @@ class PHPMailer
* The default language is English.
*
* @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr")
* @param string $lang_path Path to the language file directory, with trailing separator (slash)
* @param string $lang_path Path to the language file directory, with trailing separator (slash).D
* Do not set this from user input!
*
* @return bool
*/
@ -2244,14 +2248,32 @@ class PHPMailer
if (!static::fileIsAccessible($lang_file)) {
$foundlang = false;
} else {
//Overwrite language-specific strings.
//This way we'll never have missing translation keys.
$foundlang = include $lang_file;
//$foundlang = include $lang_file;
$lines = file($lang_file);
foreach ($lines as $line) {
//Translation file lines look like this:
//$PHPMAILER_LANG['authenticate'] = 'SMTP-Fehler: Authentifizierung fehlgeschlagen.';
//These files are parsed as text and not PHP so as to avoid the possibility of code injection
//See https://blog.stevenlevithan.com/archives/match-quoted-string
$matches = [];
if (
preg_match(
'/^\$PHPMAILER_LANG\[\'([a-z\d_]+)\'\]\s*=\s*(["\'])(.+)*?\2;/',
$line,
$matches
) &&
//Ignore unknown translation keys
array_key_exists($matches[1], $PHPMAILER_LANG)
) {
//Overwrite language-specific strings so we'll never have missing translation keys.
$PHPMAILER_LANG[$matches[1]] = (string)$matches[3];
}
}
}
}
$this->language = $PHPMAILER_LANG;
return (bool) $foundlang; //Returns false if language not found
return $foundlang; //Returns false if language not found
}
/**

View File

@ -46,7 +46,7 @@ class POP3
*
* @var string
*/
const VERSION = '6.4.1';
const VERSION = '6.5.0';
/**
* Default POP3 port number.

View File

@ -35,7 +35,7 @@ class SMTP
*
* @var string
*/
const VERSION = '6.4.1';
const VERSION = '6.5.0';
/**
* SMTP line break constant.
@ -186,6 +186,7 @@ class SMTP
'Amazon_SES' => '/[\d]{3} Ok (.*)/',
'SendGrid' => '/[\d]{3} Ok: queued as (.*)/',
'CampaignMonitor' => '/[\d]{3} 2.0.0 OK:([a-zA-Z\d]{48})/',
'Haraka' => '/[\d]{3} Message Queued \((.*)\)/',
];
/**

View File

@ -0,0 +1,3 @@
vendor/
composer.lock
phpunit.xml

View File

@ -0,0 +1,5 @@
CHANGELOG
=========
The changelog is maintained for all Symfony contracts at the following URL:
https://github.com/symfony/contracts/blob/main/CHANGELOG.md

View File

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

View File

@ -0,0 +1,26 @@
Symfony Deprecation Contracts
=============================
A generic function and convention to trigger deprecation notices.
This package provides a single global function named `trigger_deprecation()` that triggers silenced deprecation notices.
By using a custom PHP error handler such as the one provided by the Symfony ErrorHandler component,
the triggered deprecations can be caught and logged for later discovery, both on dev and prod environments.
The function requires at least 3 arguments:
- the name of the Composer package that is triggering the deprecation
- the version of the package that introduced the deprecation
- the message of the deprecation
- more arguments can be provided: they will be inserted in the message using `printf()` formatting
Example:
```php
trigger_deprecation('symfony/blockchain', '8.9', 'Using "%s" is deprecated, use "%s" instead.', 'bitcoin', 'fabcoin');
```
This will generate the following message:
`Since symfony/blockchain 8.9: Using "bitcoin" is deprecated, use "fabcoin" instead.`
While not necessarily recommended, the deprecation notices can be completely ignored by declaring an empty
`function trigger_deprecation() {}` in your application.

View File

@ -0,0 +1,35 @@
{
"name": "symfony/deprecation-contracts",
"type": "library",
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": ">=7.1"
},
"autoload": {
"files": [
"function.php"
]
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
}
}

View File

@ -0,0 +1,27 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
if (!function_exists('trigger_deprecation')) {
/**
* Triggers a silenced deprecation notice.
*
* @param string $package The name of the Composer package that is triggering the deprecation
* @param string $version The version of the package that introduced the deprecation
* @param string $message The message of the deprecation
* @param mixed ...$args Values to insert in the message using printf() formatting
*
* @author Nicolas Grekas <p@tchwork.com>
*/
function trigger_deprecation(string $package, string $version, string $message, ...$args): void
{
@trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED);
}
}

View File

@ -101,7 +101,7 @@ final class Mbstring
$fromEncoding = 'Windows-1252';
}
if ('UTF-8' !== $fromEncoding) {
$s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
$s = \iconv($fromEncoding, 'UTF-8//IGNORE', $s);
}
return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s);
@ -112,7 +112,7 @@ final class Mbstring
$fromEncoding = 'UTF-8';
}
return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
return \iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
}
public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars)
@ -129,7 +129,7 @@ final class Mbstring
public static function mb_decode_mimeheader($s)
{
return iconv_mime_decode($s, 2, self::$internalEncoding);
return \iconv_mime_decode($s, 2, self::$internalEncoding);
}
public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
@ -165,10 +165,10 @@ final class Mbstring
if ('UTF-8' === $encoding) {
$encoding = null;
if (!preg_match('//u', $s)) {
$s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
$s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
}
} else {
$s = iconv($encoding, 'UTF-8//IGNORE', $s);
$s = \iconv($encoding, 'UTF-8//IGNORE', $s);
}
$cnt = floor(\count($convmap) / 4) * 4;
@ -194,7 +194,7 @@ final class Mbstring
return $s;
}
return iconv('UTF-8', $encoding.'//IGNORE', $s);
return \iconv('UTF-8', $encoding.'//IGNORE', $s);
}
public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
@ -231,10 +231,10 @@ final class Mbstring
if ('UTF-8' === $encoding) {
$encoding = null;
if (!preg_match('//u', $s)) {
$s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
$s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
}
} else {
$s = iconv($encoding, 'UTF-8//IGNORE', $s);
$s = \iconv($encoding, 'UTF-8//IGNORE', $s);
}
static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];
@ -264,7 +264,7 @@ final class Mbstring
return $result;
}
return iconv('UTF-8', $encoding.'//IGNORE', $result);
return \iconv('UTF-8', $encoding.'//IGNORE', $result);
}
public static function mb_convert_case($s, $mode, $encoding = null)
@ -279,10 +279,10 @@ final class Mbstring
if ('UTF-8' === $encoding) {
$encoding = null;
if (!preg_match('//u', $s)) {
$s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
$s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
}
} else {
$s = iconv($encoding, 'UTF-8//IGNORE', $s);
$s = \iconv($encoding, 'UTF-8//IGNORE', $s);
}
if (\MB_CASE_TITLE == $mode) {
@ -342,7 +342,7 @@ final class Mbstring
return $s;
}
return iconv('UTF-8', $encoding.'//IGNORE', $s);
return \iconv('UTF-8', $encoding.'//IGNORE', $s);
}
public static function mb_internal_encoding($encoding = null)
@ -353,7 +353,7 @@ final class Mbstring
$normalizedEncoding = self::getEncoding($encoding);
if ('UTF-8' === $normalizedEncoding || false !== @iconv($normalizedEncoding, $normalizedEncoding, ' ')) {
if ('UTF-8' === $normalizedEncoding || false !== @\iconv($normalizedEncoding, $normalizedEncoding, ' ')) {
self::$internalEncoding = $normalizedEncoding;
return true;
@ -412,7 +412,7 @@ final class Mbstring
$encoding = self::$internalEncoding;
}
return self::mb_detect_encoding($var, [$encoding]) || false !== @iconv($encoding, $encoding, $var);
return self::mb_detect_encoding($var, [$encoding]) || false !== @\iconv($encoding, $encoding, $var);
}
public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
@ -487,7 +487,7 @@ final class Mbstring
return \strlen($s);
}
return @iconv_strlen($s, $encoding);
return @\iconv_strlen($s, $encoding);
}
public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
@ -508,7 +508,7 @@ final class Mbstring
return 0;
}
return iconv_strpos($haystack, $needle, $offset, $encoding);
return \iconv_strpos($haystack, $needle, $offset, $encoding);
}
public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
@ -532,7 +532,7 @@ final class Mbstring
}
$pos = '' !== $needle || 80000 > \PHP_VERSION_ID
? iconv_strrpos($haystack, $needle, $encoding)
? \iconv_strrpos($haystack, $needle, $encoding)
: self::mb_strlen($haystack, $encoding);
return false !== $pos ? $offset + $pos : false;
@ -613,7 +613,7 @@ final class Mbstring
}
if ($start < 0) {
$start = iconv_strlen($s, $encoding) + $start;
$start = \iconv_strlen($s, $encoding) + $start;
if ($start < 0) {
$start = 0;
}
@ -622,13 +622,13 @@ final class Mbstring
if (null === $length) {
$length = 2147483647;
} elseif ($length < 0) {
$length = iconv_strlen($s, $encoding) + $length - $start;
$length = \iconv_strlen($s, $encoding) + $length - $start;
if ($length < 0) {
return '';
}
}
return (string) iconv_substr($s, $start, $length, $encoding);
return (string) \iconv_substr($s, $start, $length, $encoding);
}
public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
@ -653,7 +653,7 @@ final class Mbstring
$pos = strrpos($haystack, $needle);
} else {
$needle = self::mb_substr($needle, 0, 1, $encoding);
$pos = iconv_strrpos($haystack, $needle, $encoding);
$pos = \iconv_strrpos($haystack, $needle, $encoding);
}
return self::getSubpart($pos, $part, $haystack, $encoding);
@ -732,12 +732,12 @@ final class Mbstring
$encoding = self::getEncoding($encoding);
if ('UTF-8' !== $encoding) {
$s = iconv($encoding, 'UTF-8//IGNORE', $s);
$s = \iconv($encoding, 'UTF-8//IGNORE', $s);
}
$s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide);
return ($wide << 1) + iconv_strlen($s, 'UTF-8');
return ($wide << 1) + \iconv_strlen($s, 'UTF-8');
}
public static function mb_substr_count($haystack, $needle, $encoding = null)

View File

@ -81,7 +81,7 @@ return array (
'Ī' => 'ī',
'Ĭ' => 'ĭ',
'Į' => 'į',
'İ' => 'i',
'İ' => 'i̇',
'IJ' => 'ij',
'Ĵ' => 'ĵ',
'Ķ' => 'ķ',

View File

@ -746,41 +746,41 @@ return array (
'ύ' => 'Ύ',
'ὼ' => 'Ὼ',
'ώ' => 'Ώ',
'ᾀ' => '',
'ᾁ' => '',
'ᾂ' => '',
'ᾃ' => '',
'ᾄ' => '',
'ᾅ' => '',
'ᾆ' => '',
'ᾇ' => '',
'ᾐ' => '',
'ᾑ' => '',
'ᾒ' => '',
'ᾓ' => '',
'ᾔ' => '',
'ᾕ' => '',
'ᾖ' => '',
'ᾗ' => '',
'ᾠ' => '',
'ᾡ' => '',
'ᾢ' => '',
'ᾣ' => '',
'ᾤ' => '',
'ᾥ' => '',
'ᾦ' => '',
'ᾧ' => '',
'ᾀ' => 'ἈΙ',
'ᾁ' => 'ἉΙ',
'ᾂ' => 'ἊΙ',
'ᾃ' => 'ἋΙ',
'ᾄ' => 'ἌΙ',
'ᾅ' => 'ἍΙ',
'ᾆ' => 'ἎΙ',
'ᾇ' => 'ἏΙ',
'ᾐ' => 'ἨΙ',
'ᾑ' => 'ἩΙ',
'ᾒ' => 'ἪΙ',
'ᾓ' => 'ἫΙ',
'ᾔ' => 'ἬΙ',
'ᾕ' => 'ἭΙ',
'ᾖ' => 'ἮΙ',
'ᾗ' => 'ἯΙ',
'ᾠ' => 'ὨΙ',
'ᾡ' => 'ὩΙ',
'ᾢ' => 'ὪΙ',
'ᾣ' => 'ὫΙ',
'ᾤ' => 'ὬΙ',
'ᾥ' => 'ὭΙ',
'ᾦ' => 'ὮΙ',
'ᾧ' => 'ὯΙ',
'ᾰ' => 'Ᾰ',
'ᾱ' => 'Ᾱ',
'ᾳ' => '',
'ᾳ' => 'ΑΙ',
'' => 'Ι',
'ῃ' => '',
'ῃ' => 'ΗΙ',
'ῐ' => 'Ῐ',
'ῑ' => 'Ῑ',
'ῠ' => 'Ῠ',
'ῡ' => 'Ῡ',
'ῥ' => 'Ῥ',
'ῳ' => '',
'ῳ' => 'ΩΙ',
'ⅎ' => 'Ⅎ',
'' => '',
'ⅱ' => 'Ⅱ',
@ -1411,4 +1411,79 @@ return array (
'𞥁' => '𞤟',
'𞥂' => '𞤠',
'𞥃' => '𞤡',
'ß' => 'SS',
'ff' => 'FF',
'fi' => 'FI',
'fl' => 'FL',
'ffi' => 'FFI',
'ffl' => 'FFL',
'ſt' => 'ST',
'st' => 'ST',
'և' => 'ԵՒ',
'ﬓ' => 'ՄՆ',
'ﬔ' => 'ՄԵ',
'ﬕ' => 'ՄԻ',
'ﬖ' => 'ՎՆ',
'ﬗ' => 'ՄԽ',
'ʼn' => 'ʼN',
'ΐ' => 'Ϊ́',
'ΰ' => 'Ϋ́',
'ǰ' => 'J̌',
'ẖ' => 'H̱',
'ẗ' => 'T̈',
'ẘ' => 'W̊',
'ẙ' => 'Y̊',
'ẚ' => 'Aʾ',
'ὐ' => 'Υ̓',
'ὒ' => 'Υ̓̀',
'ὔ' => 'Υ̓́',
'ὖ' => 'Υ̓͂',
'ᾶ' => 'Α͂',
'ῆ' => 'Η͂',
'ῒ' => 'Ϊ̀',
'ΐ' => 'Ϊ́',
'ῖ' => 'Ι͂',
'ῗ' => 'Ϊ͂',
'ῢ' => 'Ϋ̀',
'ΰ' => 'Ϋ́',
'ῤ' => 'Ρ̓',
'ῦ' => 'Υ͂',
'ῧ' => 'Ϋ͂',
'ῶ' => 'Ω͂',
'ᾈ' => 'ἈΙ',
'ᾉ' => 'ἉΙ',
'ᾊ' => 'ἊΙ',
'ᾋ' => 'ἋΙ',
'ᾌ' => 'ἌΙ',
'ᾍ' => 'ἍΙ',
'ᾎ' => 'ἎΙ',
'ᾏ' => 'ἏΙ',
'ᾘ' => 'ἨΙ',
'ᾙ' => 'ἩΙ',
'ᾚ' => 'ἪΙ',
'ᾛ' => 'ἫΙ',
'ᾜ' => 'ἬΙ',
'ᾝ' => 'ἭΙ',
'ᾞ' => 'ἮΙ',
'ᾟ' => 'ἯΙ',
'ᾨ' => 'ὨΙ',
'ᾩ' => 'ὩΙ',
'ᾪ' => 'ὪΙ',
'ᾫ' => 'ὫΙ',
'ᾬ' => 'ὬΙ',
'ᾭ' => 'ὭΙ',
'ᾮ' => 'ὮΙ',
'ᾯ' => 'ὯΙ',
'ᾼ' => 'ΑΙ',
'ῌ' => 'ΗΙ',
'ῼ' => 'ΩΙ',
'ᾲ' => 'ᾺΙ',
'ᾴ' => 'ΆΙ',
'ῂ' => 'ῊΙ',
'ῄ' => 'ΉΙ',
'ῲ' => 'ῺΙ',
'ῴ' => 'ΏΙ',
'ᾷ' => 'Α͂Ι',
'ῇ' => 'Η͂Ι',
'ῷ' => 'Ω͂Ι',
);

View File

@ -55,7 +55,7 @@ if (!function_exists('mb_detect_order')) {
function mb_detect_order($encoding = null) { return p\Mbstring::mb_detect_order($encoding); }
}
if (!function_exists('mb_parse_str')) {
function mb_parse_str($string, &$result = []) { parse_str($string, $result); }
function mb_parse_str($string, &$result = []) { parse_str($string, $result); return (bool) $result; }
}
if (!function_exists('mb_strlen')) {
function mb_strlen($string, $encoding = null) { return p\Mbstring::mb_strlen($string, $encoding); }

View File

@ -48,10 +48,10 @@ if (!function_exists('mb_detect_encoding')) {
function mb_detect_encoding(?string $string, array|string|null $encodings = null, ?bool $strict = false): string|false { return p\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict); }
}
if (!function_exists('mb_detect_order')) {
function mb_detect_order(array|string|null $encoding = null): array|bool { return p\Mbstring::mb_detect_order((string) $encoding); }
function mb_detect_order(array|string|null $encoding = null): array|bool { return p\Mbstring::mb_detect_order($encoding); }
}
if (!function_exists('mb_parse_str')) {
function mb_parse_str(?string $string, &$result = []): bool { parse_str((string) $string, $result); }
function mb_parse_str(?string $string, &$result = []): bool { parse_str((string) $string, $result); return (bool) $result; }
}
if (!function_exists('mb_strlen')) {
function mb_strlen(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strlen((string) $string, $encoding); }
@ -78,7 +78,7 @@ if (!function_exists('mb_stristr')) {
function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
}
if (!function_exists('mb_strrchr')) {
function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, $before_needle, (bool) $encoding); }
function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
}
if (!function_exists('mb_strrichr')) {
function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }

View File

@ -28,7 +28,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-main": "1.22-dev"
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",

View File

@ -30,7 +30,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-main": "1.22-dev"
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",

View File

@ -1,6 +1,13 @@
CHANGELOG
=========
5.3
---
* Add `translation:pull` and `translation:push` commands to manage translations with third-party providers
* Add `TranslatorBagInterface::getCatalogues` method
* Add support to load XLIFF string in `XliffFileLoader`
5.2.0
-----

View File

@ -26,6 +26,10 @@ use Symfony\Component\Translation\MessageCatalogueInterface;
*/
abstract class AbstractOperation implements OperationInterface
{
public const OBSOLETE_BATCH = 'obsolete';
public const NEW_BATCH = 'new';
public const ALL_BATCH = 'all';
protected $source;
protected $target;
protected $result;
@ -94,11 +98,11 @@ abstract class AbstractOperation implements OperationInterface
throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain));
}
if (!isset($this->messages[$domain]['all'])) {
if (!isset($this->messages[$domain][self::ALL_BATCH])) {
$this->processDomain($domain);
}
return $this->messages[$domain]['all'];
return $this->messages[$domain][self::ALL_BATCH];
}
/**
@ -110,11 +114,11 @@ abstract class AbstractOperation implements OperationInterface
throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain));
}
if (!isset($this->messages[$domain]['new'])) {
if (!isset($this->messages[$domain][self::NEW_BATCH])) {
$this->processDomain($domain);
}
return $this->messages[$domain]['new'];
return $this->messages[$domain][self::NEW_BATCH];
}
/**
@ -126,11 +130,11 @@ abstract class AbstractOperation implements OperationInterface
throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain));
}
if (!isset($this->messages[$domain]['obsolete'])) {
if (!isset($this->messages[$domain][self::OBSOLETE_BATCH])) {
$this->processDomain($domain);
}
return $this->messages[$domain]['obsolete'];
return $this->messages[$domain][self::OBSOLETE_BATCH];
}
/**
@ -147,6 +151,37 @@ abstract class AbstractOperation implements OperationInterface
return $this->result;
}
/**
* @param self::*_BATCH $batch
*/
public function moveMessagesToIntlDomainsIfPossible(string $batch = self::ALL_BATCH): void
{
// If MessageFormatter class does not exists, intl domains are not supported.
if (!class_exists(\MessageFormatter::class)) {
return;
}
foreach ($this->getDomains() as $domain) {
$intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
switch ($batch) {
case self::OBSOLETE_BATCH: $messages = $this->getObsoleteMessages($domain); break;
case self::NEW_BATCH: $messages = $this->getNewMessages($domain); break;
case self::ALL_BATCH: $messages = $this->getMessages($domain); break;
default: throw new \InvalidArgumentException(sprintf('$batch argument must be one of ["%s", "%s", "%s"].', self::ALL_BATCH, self::NEW_BATCH, self::OBSOLETE_BATCH));
}
if (!$messages || (!$this->source->all($intlDomain) && $this->source->all($domain))) {
continue;
}
$result = $this->getResult();
$allIntlMessages = $result->all($intlDomain);
$currentMessages = array_diff_key($messages, $result->all($domain));
$result->replace($currentMessages, $domain);
$result->replace($allIntlMessages + $messages, $intlDomain);
}
}
/**
* Performs operation on source and target catalogues for the given domain and
* stores the results.

View File

@ -0,0 +1,157 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Translation\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Translation\Catalogue\TargetOperation;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Provider\TranslationProviderCollection;
use Symfony\Component\Translation\Reader\TranslationReaderInterface;
use Symfony\Component\Translation\Writer\TranslationWriterInterface;
/**
* @author Mathieu Santostefano <msantostefano@protonmail.com>
*
* @experimental in 5.3
*/
final class TranslationPullCommand extends Command
{
use TranslationTrait;
protected static $defaultName = 'translation:pull';
protected static $defaultDescription = 'Pull translations from a given provider.';
private $providerCollection;
private $writer;
private $reader;
private $defaultLocale;
private $transPaths;
private $enabledLocales;
public function __construct(TranslationProviderCollection $providerCollection, TranslationWriterInterface $writer, TranslationReaderInterface $reader, string $defaultLocale, array $transPaths = [], array $enabledLocales = [])
{
$this->providerCollection = $providerCollection;
$this->writer = $writer;
$this->reader = $reader;
$this->defaultLocale = $defaultLocale;
$this->transPaths = $transPaths;
$this->enabledLocales = $enabledLocales;
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$keys = $this->providerCollection->keys();
$defaultProvider = 1 === \count($keys) ? $keys[0] : null;
$this
->setDefinition([
new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to pull translations from.', $defaultProvider),
new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with provider ones (it will delete not synchronized messages).'),
new InputOption('intl-icu', null, InputOption::VALUE_NONE, 'Associated to --force option, it will write messages in "%domain%+intl-icu.%locale%.xlf" files.'),
new InputOption('domains', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the domains to pull.'),
new InputOption('locales', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the locales to pull.'),
new InputOption('format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format.', 'xlf12'),
])
->setHelp(<<<'EOF'
The <info>%command.name%</> command pulls translations from the given provider. Only
new translations are pulled, existing ones are not overwritten.
You can overwrite existing translations (and remove the missing ones on local side) by using the <comment>--force</> flag:
<info>php %command.full_name% --force provider</>
Full example:
<info>php %command.full_name% provider --force --domains=messages,validators --locales=en</>
This command pulls all translations associated with the <comment>messages</> and <comment>validators</> domains for the <comment>en</> locale.
Local translations for the specified domains and locale are deleted if they're not present on the provider and overwritten if it's the case.
Local translations for others domains and locales are ignored.
EOF
)
;
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$provider = $this->providerCollection->get($input->getArgument('provider'));
$force = $input->getOption('force');
$intlIcu = $input->getOption('intl-icu');
$locales = $input->getOption('locales') ?: $this->enabledLocales;
$domains = $input->getOption('domains');
$format = $input->getOption('format');
$xliffVersion = '1.2';
if ($intlIcu && !$force) {
$io->note('--intl-icu option only has an effect when used with --force. Here, it will be ignored.');
}
switch ($format) {
case 'xlf20': $xliffVersion = '2.0';
// no break
case 'xlf12': $format = 'xlf';
}
$writeOptions = [
'path' => end($this->transPaths),
'xliff_version' => $xliffVersion,
];
if (!$domains) {
$domains = $provider->getDomains();
}
$providerTranslations = $provider->read($domains, $locales);
if ($force) {
foreach ($providerTranslations->getCatalogues() as $catalogue) {
$operation = new TargetOperation((new MessageCatalogue($catalogue->getLocale())), $catalogue);
if ($intlIcu) {
$operation->moveMessagesToIntlDomainsIfPossible();
}
$this->writer->write($operation->getResult(), $format, $writeOptions);
}
$io->success(sprintf('Local translations has been updated from "%s" (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
return 0;
}
$localTranslations = $this->readLocalTranslations($locales, $domains, $this->transPaths);
// Append pulled translations to local ones.
$localTranslations->addBag($providerTranslations->diff($localTranslations));
foreach ($localTranslations->getCatalogues() as $catalogue) {
$this->writer->write($catalogue, $format, $writeOptions);
}
$io->success(sprintf('New translations from "%s" has been written locally (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
return 0;
}
}

View File

@ -0,0 +1,158 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Translation\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Translation\Provider\TranslationProviderCollection;
use Symfony\Component\Translation\Reader\TranslationReaderInterface;
use Symfony\Component\Translation\TranslatorBag;
/**
* @author Mathieu Santostefano <msantostefano@protonmail.com>
*
* @experimental in 5.3
*/
final class TranslationPushCommand extends Command
{
use TranslationTrait;
protected static $defaultName = 'translation:push';
protected static $defaultDescription = 'Push translations to a given provider.';
private $providers;
private $reader;
private $transPaths;
private $enabledLocales;
public function __construct(TranslationProviderCollection $providers, TranslationReaderInterface $reader, array $transPaths = [], array $enabledLocales = [])
{
$this->providers = $providers;
$this->reader = $reader;
$this->transPaths = $transPaths;
$this->enabledLocales = $enabledLocales;
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$keys = $this->providers->keys();
$defaultProvider = 1 === \count($keys) ? $keys[0] : null;
$this
->setDefinition([
new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to push translations to.', $defaultProvider),
new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with local ones (it will delete not synchronized messages).'),
new InputOption('delete-missing', null, InputOption::VALUE_NONE, 'Delete translations available on provider but not locally.'),
new InputOption('domains', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the domains to push.'),
new InputOption('locales', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the locales to push.', $this->enabledLocales),
])
->setHelp(<<<'EOF'
The <info>%command.name%</> command pushes translations to the given provider. Only new
translations are pushed, existing ones are not overwritten.
You can overwrite existing translations by using the <comment>--force</> flag:
<info>php %command.full_name% --force provider</>
You can delete provider translations which are not present locally by using the <comment>--delete-missing</> flag:
<info>php %command.full_name% --delete-missing provider</>
Full example:
<info>php %command.full_name% provider --force --delete-missing --domains=messages,validators --locales=en</>
This command pushes all translations associated with the <comment>messages</> and <comment>validators</> domains for the <comment>en</> locale.
Provider translations for the specified domains and locale are deleted if they're not present locally and overwritten if it's the case.
Provider translations for others domains and locales are ignored.
EOF
)
;
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
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.');
}
$io = new SymfonyStyle($input, $output);
$provider = $this->providers->get($input->getArgument('provider'));
$domains = $input->getOption('domains');
$locales = $input->getOption('locales');
$force = $input->getOption('force');
$deleteMissing = $input->getOption('delete-missing');
$localTranslations = $this->readLocalTranslations($locales, $domains, $this->transPaths);
if (!$domains) {
$domains = $this->getDomainsFromTranslatorBag($localTranslations);
}
if (!$deleteMissing && $force) {
$provider->write($localTranslations);
$io->success(sprintf('All local translations has been sent to "%s" (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
return 0;
}
$providerTranslations = $provider->read($domains, $locales);
if ($deleteMissing) {
$provider->delete($providerTranslations->diff($localTranslations));
$io->success(sprintf('Missing translations on "%s" has been deleted (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
// Read provider translations again, after missing translations deletion,
// to avoid push freshly deleted translations.
$providerTranslations = $provider->read($domains, $locales);
}
$translationsToWrite = $localTranslations->diff($providerTranslations);
if ($force) {
$translationsToWrite->addBag($localTranslations->intersect($providerTranslations));
}
$provider->write($translationsToWrite);
$io->success(sprintf('%s local translations has been sent to "%s" (for "%s" locale(s), and "%s" domain(s)).', $force ? 'All' : 'New', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
return 0;
}
private function getDomainsFromTranslatorBag(TranslatorBag $translatorBag): array
{
$domains = [];
foreach ($translatorBag->getCatalogues() as $catalogue) {
$domains += $catalogue->getDomains();
}
return array_unique($domains);
}
}

View File

@ -0,0 +1,78 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Translation\Command;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\MessageCatalogueInterface;
use Symfony\Component\Translation\TranslatorBag;
/**
* @internal
*/
trait TranslationTrait
{
private function readLocalTranslations(array $locales, array $domains, array $transPaths): TranslatorBag
{
$bag = new TranslatorBag();
foreach ($locales as $locale) {
$catalogue = new MessageCatalogue($locale);
foreach ($transPaths as $path) {
$this->reader->read($path, $catalogue);
}
if ($domains) {
foreach ($domains as $domain) {
$catalogue = $this->filterCatalogue($catalogue, $domain);
$bag->addCatalogue($catalogue);
}
} else {
$bag->addCatalogue($catalogue);
}
}
return $bag;
}
private function filterCatalogue(MessageCatalogue $catalogue, string $domain): MessageCatalogue
{
$filteredCatalogue = new MessageCatalogue($catalogue->getLocale());
// extract intl-icu messages only
$intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
if ($intlMessages = $catalogue->all($intlDomain)) {
$filteredCatalogue->add($intlMessages, $intlDomain);
}
// extract all messages and subtract intl-icu messages
if ($messages = array_diff($catalogue->all($domain), $intlMessages)) {
$filteredCatalogue->add($messages, $domain);
}
foreach ($catalogue->getResources() as $resource) {
$filteredCatalogue->addResource($resource);
}
if ($metadata = $catalogue->getMetadata('', $intlDomain)) {
foreach ($metadata as $k => $v) {
$filteredCatalogue->setMetadata($k, $v, $intlDomain);
}
}
if ($metadata = $catalogue->getMetadata('', $domain)) {
foreach ($metadata as $k => $v) {
$filteredCatalogue->setMetadata($k, $v, $domain);
}
}
return $filteredCatalogue;
}
}

View File

@ -31,6 +31,7 @@ use Symfony\Component\Translation\Util\XliffUtils;
class XliffLintCommand extends Command
{
protected static $defaultName = 'lint:xliff';
protected static $defaultDescription = 'Lint an XLIFF file and outputs encountered errors';
private $format;
private $displayCorrectFiles;
@ -53,7 +54,7 @@ class XliffLintCommand extends Command
protected function configure()
{
$this
->setDescription('Lint an XLIFF file and outputs encountered errors')
->setDescription(self::$defaultDescription)
->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN')
->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt')
->setHelp(<<<EOF

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