From 64281064f764b77d545f8f15983ddd344e9c872e Mon Sep 17 00:00:00 2001 From: Antonio Carlos Ribeiro Date: Thu, 21 Dec 2017 01:42:27 -0200 Subject: [PATCH] Add upgrader script and rename namespace to Tightenco --- composer.json | 17 +- composer.lock | 446 +++++++++--- .../Contracts/Support/Arrayable.php | 2 +- .../Contracts/Support/Htmlable.php | 2 +- .../Contracts/Support/Jsonable.php | 2 +- src/{Illuminate => Tightenco}/Support/Arr.php | 4 +- src/Tightenco/Support/Carbon.php | 48 ++ .../Support/Collection.php | 14 +- .../Support/Debug/Dumper.php | 2 +- .../Support/Debug/HtmlDumper.php | 2 +- .../Support/HigherOrderCollectionProxy.php | 8 +- src/Tightenco/Support/HigherOrderTapProxy.php | 38 + .../Support/HtmlString.php | 4 +- src/Tightenco/Support/Optional.php | 110 +++ src/Tightenco/Support/Str.php | 683 ++++++++++++++++++ .../Support/Traits/Macroable.php | 2 +- src/Tightenco/Support/alias.php | 20 + src/Tightenco/Support/helpers.php | 116 +++ stubs/src/Tightenco/Support/alias.php | 9 + .../src/Tightenco}/Support/helpers.php | 0 stubs/tests/bootstrap.php | 5 + tests/Support/SupportArrTest.php | 666 +++++++++++++++++ tests/Support/SupportCarbonTest.php | 96 +++ tests/Support/SupportCollectionTest.php | 20 +- tests/Support/SupportMacroableTest.php | 92 +++ tests/Support/SupportStrTest.php | 303 ++++++++ upgrade.sh | 344 +++++++++ 27 files changed, 2926 insertions(+), 129 deletions(-) rename src/{Illuminate => Tightenco}/Contracts/Support/Arrayable.php (78%) mode change 100644 => 100755 rename src/{Illuminate => Tightenco}/Contracts/Support/Htmlable.php (78%) rename src/{Illuminate => Tightenco}/Contracts/Support/Jsonable.php (83%) mode change 100644 => 100755 rename src/{Illuminate => Tightenco}/Support/Arr.php (99%) mode change 100644 => 100755 create mode 100644 src/Tightenco/Support/Carbon.php rename src/{Illuminate => Tightenco}/Support/Collection.php (99%) rename src/{Illuminate => Tightenco}/Support/Debug/Dumper.php (93%) rename src/{Illuminate => Tightenco}/Support/Debug/HtmlDumper.php (96%) rename src/{Illuminate => Tightenco}/Support/HigherOrderCollectionProxy.php (87%) create mode 100644 src/Tightenco/Support/HigherOrderTapProxy.php rename src/{Illuminate => Tightenco}/Support/HtmlString.php (89%) create mode 100644 src/Tightenco/Support/Optional.php create mode 100644 src/Tightenco/Support/Str.php rename src/{Illuminate => Tightenco}/Support/Traits/Macroable.php (98%) create mode 100644 src/Tightenco/Support/alias.php create mode 100755 src/Tightenco/Support/helpers.php create mode 100644 stubs/src/Tightenco/Support/alias.php rename {src/Illuminate => stubs/src/Tightenco}/Support/helpers.php (100%) mode change 100644 => 100755 create mode 100644 stubs/tests/bootstrap.php create mode 100644 tests/Support/SupportArrTest.php create mode 100644 tests/Support/SupportCarbonTest.php create mode 100644 tests/Support/SupportMacroableTest.php create mode 100644 tests/Support/SupportStrTest.php create mode 100755 upgrade.sh diff --git a/composer.json b/composer.json index 5f3169e..63ae8cb 100644 --- a/composer.json +++ b/composer.json @@ -10,23 +10,32 @@ } ], "require": { - "php": ">=7.0" + "php": ">=7.0", + "nesbot/carbon": "~1.20" }, "require-dev": { "mockery/mockery": "~1.0", - "phpunit/phpunit": "~6.0" + "phpunit/phpunit": "~6.0", + "symfony/var-dumper": "~3.3" }, "autoload": { "files": [ - "src/Illuminate/Support/helpers.php" + "src/Tightenco/Support/helpers.php", + "src/Tightenco/Support/alias.php" ], "psr-4": { - "Illuminate\\": "src/Illuminate" + "Tightenco\\": "src/Tightenco" } }, "suggest": { "symfony/var-dumper": "Required to prettify dd() and dump() (~3.3)." }, + "scripts": { + "test": [ + "@composer install", + "vendor/bin/phpunit" + ] + }, "minimum-stability": "dev", "prefer-stable": true } diff --git a/composer.lock b/composer.lock index f125fb3..bfd25ac 100644 --- a/composer.lock +++ b/composer.lock @@ -4,37 +4,218 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "93255db3a480848e29f88498fd5d562a", - "packages": [], + "content-hash": "679e3042bfdf42a1f874e734d08033b1", + "packages": [ + { + "name": "nesbot/carbon", + "version": "1.22.1", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc", + "reference": "7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "symfony/translation": "~2.6 || ~3.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2", + "phpunit/phpunit": "~4.0 || ~5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.23-dev" + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "http://nesbot.com" + } + ], + "description": "A simple API extension for DateTime.", + "homepage": "http://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "time": "2017-01-16T07:55:07+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", + "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.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": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2017-10-11T12:05:26+00:00" + }, + { + "name": "symfony/translation", + "version": "v3.4.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "4c5d5582baf2829751a5207659329c1f52eedeb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/4c5d5582baf2829751a5207659329c1f52eedeb6", + "reference": "4c5d5582baf2829751a5207659329c1f52eedeb6", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/config": "<2.8", + "symfony/dependency-injection": "<3.4", + "symfony/yaml": "<3.4" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/intl": "^2.8.18|^3.2.5|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "psr/log": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Translation Component", + "homepage": "https://symfony.com", + "time": "2017-12-12T08:27:14+00:00" + } + ], "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.0.5", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "php": "^7.1" }, "require-dev": { "athletic/athletic": "~0.1.8", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "phpunit/phpunit": "^6.2.3", + "squizlabs/php_codesniffer": "^3.0.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -59,7 +240,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14T21:17:01+00:00" + "time": "2017-07-22T11:58:36+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -111,16 +292,16 @@ }, { "name": "mockery/mockery", - "version": "1.0.0-alpha1", + "version": "1.0", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "0b23f71799b3e43406f4ce7fef112ac3f0b7a385" + "reference": "1bac8c362b12f522fdd1f1fa3556284c91affa38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/0b23f71799b3e43406f4ce7fef112ac3f0b7a385", - "reference": "0b23f71799b3e43406f4ce7fef112ac3f0b7a385", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1bac8c362b12f522fdd1f1fa3556284c91affa38", + "reference": "1bac8c362b12f522fdd1f1fa3556284c91affa38", "shasum": "" }, "require": { @@ -129,7 +310,7 @@ "php": ">=5.6.0" }, "require-dev": { - "phpunit/phpunit": "~5.7" + "phpunit/phpunit": "~5.7|~6.1" }, "type": "library", "extra": { @@ -159,7 +340,7 @@ } ], "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.", - "homepage": "http://github.com/padraic/mockery", + "homepage": "http://github.com/mockery/mockery", "keywords": [ "BDD", "TDD", @@ -172,41 +353,44 @@ "test double", "testing" ], - "time": "2017-02-02T08:52:46+00:00" + "time": "2017-10-06T16:20:43+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.6.1", + "version": "1.7.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102" + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8e6e04167378abf1ddb4d3522d8755c5fd90d102", - "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", "shasum": "" }, "require": { - "php": ">=5.4.0" + "php": "^5.6 || ^7.0" }, "require-dev": { - "doctrine/collections": "1.*", - "phpunit/phpunit": "~4.1" + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^4.1" }, "type": "library", "autoload": { "psr-4": { "DeepCopy\\": "src/DeepCopy/" - } + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Create deep copies (clones) of your objects", - "homepage": "https://github.com/myclabs/DeepCopy", "keywords": [ "clone", "copy", @@ -214,7 +398,7 @@ "object", "object graph" ], - "time": "2017-04-12T18:52:22+00:00" + "time": "2017-10-19T19:58:43+00:00" }, { "name": "phar-io/manifest", @@ -320,16 +504,16 @@ }, { "name": "phpdocumentor/reflection-common", - "version": "1.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", "shasum": "" }, "require": { @@ -370,33 +554,39 @@ "reflection", "static analysis" ], - "time": "2015-12-27T11:43:31+00:00" + "time": "2017-09-11T18:02:19+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.1.1", + "version": "4.2.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "2d3d238c433cf69caeb4842e97a3223a116f94b2" + "reference": "66465776cfc249844bde6d117abff1d22e06c2da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/2d3d238c433cf69caeb4842e97a3223a116f94b2", - "reference": "2d3d238c433cf69caeb4842e97a3223a116f94b2", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/66465776cfc249844bde6d117abff1d22e06c2da", + "reference": "66465776cfc249844bde6d117abff1d22e06c2da", "shasum": "" }, "require": { "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0@dev", + "phpdocumentor/reflection-common": "^1.0.0", "phpdocumentor/type-resolver": "^0.4.0", "webmozart/assert": "^1.0" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^4.4" + "doctrine/instantiator": "~1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, "autoload": { "psr-4": { "phpDocumentor\\Reflection\\": [ @@ -415,7 +605,7 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-08-30T18:51:59+00:00" + "time": "2017-11-27T17:38:31+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -466,16 +656,16 @@ }, { "name": "phpspec/prophecy", - "version": "v1.7.2", + "version": "1.7.3", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6" + "reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6", - "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf", + "reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf", "shasum": "" }, "require": { @@ -487,7 +677,7 @@ }, "require-dev": { "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8 || ^5.6.5" + "phpunit/phpunit": "^4.8.35 || ^5.7" }, "type": "library", "extra": { @@ -525,20 +715,20 @@ "spy", "stub" ], - "time": "2017-09-04T11:05:03+00:00" + "time": "2017-11-24T13:59:53+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "5.2.2", + "version": "5.3.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "8ed1902a57849e117b5651fc1a5c48110946c06b" + "reference": "661f34d0bd3f1a7225ef491a70a020ad23a057a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/8ed1902a57849e117b5651fc1a5c48110946c06b", - "reference": "8ed1902a57849e117b5651fc1a5c48110946c06b", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/661f34d0bd3f1a7225ef491a70a020ad23a057a1", + "reference": "661f34d0bd3f1a7225ef491a70a020ad23a057a1", "shasum": "" }, "require": { @@ -547,14 +737,13 @@ "php": "^7.0", "phpunit/php-file-iterator": "^1.4.2", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^1.4.11 || ^2.0", + "phpunit/php-token-stream": "^2.0.1", "sebastian/code-unit-reverse-lookup": "^1.0.1", "sebastian/environment": "^3.0", "sebastian/version": "^2.0.1", "theseer/tokenizer": "^1.1" }, "require-dev": { - "ext-xdebug": "^2.5", "phpunit/phpunit": "^6.0" }, "suggest": { @@ -563,7 +752,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.2.x-dev" + "dev-master": "5.3.x-dev" } }, "autoload": { @@ -578,7 +767,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -589,20 +778,20 @@ "testing", "xunit" ], - "time": "2017-08-03T12:40:43+00:00" + "time": "2017-12-06T09:29:45+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.2", + "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", "shasum": "" }, "require": { @@ -636,7 +825,7 @@ "filesystem", "iterator" ], - "time": "2016-10-03T07:40:28+00:00" + "time": "2017-11-27T13:52:08+00:00" }, { "name": "phpunit/php-text-template", @@ -730,16 +919,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "2.0.1", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "9a02332089ac48e704c70f6cefed30c224e3c0b0" + "reference": "791198a2c6254db10131eecfe8c06670700904db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/9a02332089ac48e704c70f6cefed30c224e3c0b0", - "reference": "9a02332089ac48e704c70f6cefed30c224e3c0b0", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", + "reference": "791198a2c6254db10131eecfe8c06670700904db", "shasum": "" }, "require": { @@ -775,20 +964,20 @@ "keywords": [ "tokenizer" ], - "time": "2017-08-20T05:47:52+00:00" + "time": "2017-11-27T05:48:46+00:00" }, { "name": "phpunit/phpunit", - "version": "6.3.0", + "version": "6.5.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "9501bab711403a1ab5b8378a8adb4ec3db3debdb" + "reference": "83d27937a310f2984fd575686138597147bdc7df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9501bab711403a1ab5b8378a8adb4ec3db3debdb", - "reference": "9501bab711403a1ab5b8378a8adb4ec3db3debdb", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/83d27937a310f2984fd575686138597147bdc7df", + "reference": "83d27937a310f2984fd575686138597147bdc7df", "shasum": "" }, "require": { @@ -802,12 +991,12 @@ "phar-io/version": "^1.0", "php": "^7.0", "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^5.2.2", - "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-code-coverage": "^5.3", + "phpunit/php-file-iterator": "^1.4.3", "phpunit/php-text-template": "^1.2.1", "phpunit/php-timer": "^1.0.9", - "phpunit/phpunit-mock-objects": "^4.0.3", - "sebastian/comparator": "^2.0.2", + "phpunit/phpunit-mock-objects": "^5.0.5", + "sebastian/comparator": "^2.1", "sebastian/diff": "^2.0", "sebastian/environment": "^3.1", "sebastian/exporter": "^3.1", @@ -833,7 +1022,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.3.x-dev" + "dev-master": "6.5.x-dev" } }, "autoload": { @@ -859,33 +1048,33 @@ "testing", "xunit" ], - "time": "2017-08-04T05:20:39+00:00" + "time": "2017-12-17T06:31:19+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "4.0.4", + "version": "5.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "2f789b59ab89669015ad984afa350c4ec577ade0" + "reference": "283b9f4f670e3a6fd6c4ff95c51a952eb5c75933" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/2f789b59ab89669015ad984afa350c4ec577ade0", - "reference": "2f789b59ab89669015ad984afa350c4ec577ade0", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/283b9f4f670e3a6fd6c4ff95c51a952eb5c75933", + "reference": "283b9f4f670e3a6fd6c4ff95c51a952eb5c75933", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.5", "php": "^7.0", "phpunit/php-text-template": "^1.2.1", - "sebastian/exporter": "^3.0" + "sebastian/exporter": "^3.1" }, "conflict": { "phpunit/phpunit": "<6.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^6.5" }, "suggest": { "ext-soap": "*" @@ -893,7 +1082,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0.x-dev" + "dev-master": "5.0.x-dev" } }, "autoload": { @@ -908,7 +1097,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -918,7 +1107,7 @@ "mock", "xunit" ], - "time": "2017-08-03T14:08:16+00:00" + "time": "2017-12-10T08:01:53+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -967,30 +1156,30 @@ }, { "name": "sebastian/comparator", - "version": "2.0.2", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "ae068fede81d06e7bb9bb46a367210a3d3e1fe6a" + "reference": "1174d9018191e93cb9d719edec01257fc05f8158" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/ae068fede81d06e7bb9bb46a367210a3d3e1fe6a", - "reference": "ae068fede81d06e7bb9bb46a367210a3d3e1fe6a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1174d9018191e93cb9d719edec01257fc05f8158", + "reference": "1174d9018191e93cb9d719edec01257fc05f8158", "shasum": "" }, "require": { "php": "^7.0", "sebastian/diff": "^2.0", - "sebastian/exporter": "^3.0" + "sebastian/exporter": "^3.1" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "2.1.x-dev" } }, "autoload": { @@ -1021,13 +1210,13 @@ } ], "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", + "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ "comparator", "compare", "equality" ], - "time": "2017-08-03T07:14:59+00:00" + "time": "2017-11-03T07:16:52+00:00" }, { "name": "sebastian/diff", @@ -1479,6 +1668,75 @@ "homepage": "https://github.com/sebastianbergmann/version", "time": "2016-10-03T07:35:21+00:00" }, + { + "name": "symfony/var-dumper", + "version": "v3.4.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "757074cf71b952ce9e75b557538948811c2bf006" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/757074cf71b952ce9e75b557538948811c2bf006", + "reference": "757074cf71b952ce9e75b557538948811c2bf006", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" + }, + "require-dev": { + "ext-iconv": "*", + "twig/twig": "~1.34|~2.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "ext-symfony_debug": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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": "Symfony mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "time": "2017-12-11T22:06:16+00:00" + }, { "name": "theseer/tokenizer", "version": "1.1.0", diff --git a/src/Illuminate/Contracts/Support/Arrayable.php b/src/Tightenco/Contracts/Support/Arrayable.php old mode 100644 new mode 100755 similarity index 78% rename from src/Illuminate/Contracts/Support/Arrayable.php rename to src/Tightenco/Contracts/Support/Arrayable.php index 5ad93b7..fd0ca6d --- a/src/Illuminate/Contracts/Support/Arrayable.php +++ b/src/Tightenco/Contracts/Support/Arrayable.php @@ -1,6 +1,6 @@ target = $target; + } + + /** + * Dynamically pass method calls to the target. + * + * @param string $method + * @param array $parameters + * @return mixed + */ + public function __call($method, $parameters) + { + $this->target->{$method}(...$parameters); + + return $this->target; + } +} diff --git a/src/Illuminate/Support/HtmlString.php b/src/Tightenco/Support/HtmlString.php similarity index 89% rename from src/Illuminate/Support/HtmlString.php rename to src/Tightenco/Support/HtmlString.php index c13adfd..b9d9c27 100644 --- a/src/Illuminate/Support/HtmlString.php +++ b/src/Tightenco/Support/HtmlString.php @@ -1,8 +1,8 @@ value = $value; + } + + /** + * Dynamically access a property on the underlying object. + * + * @param string $key + * @return mixed + */ + public function __get($key) + { + if (is_object($this->value)) { + return $this->value->{$key}; + } + } + + /** + * Dynamically pass a method to the underlying object. + * + * @param string $method + * @param array $parameters + * @return mixed + */ + public function __call($method, $parameters) + { + if (static::hasMacro($method)) { + return $this->macroCall($method, $parameters); + } + + if (is_object($this->value)) { + return $this->value->{$method}(...$parameters); + } + } + + /** + * Determine if an item exists at an offset. + * + * @param mixed $key + * @return bool + */ + public function offsetExists($key) + { + return Arr::accessible($this->value) && Arr::exists($this->value, $key); + } + + /** + * Get an item at a given offset. + * + * @param mixed $key + * @return mixed + */ + public function offsetGet($key) + { + return Arr::get($this->value, $key); + } + + /** + * Set the item at a given offset. + * + * @param mixed $key + * @param mixed $value + * @return void + */ + public function offsetSet($key, $value) + { + if (Arr::accessible($this->value)) { + $this->value[$key] = $value; + } + } + + /** + * Unset the item at a given offset. + * + * @param string $key + * @return void + */ + public function offsetUnset($key) + { + if (Arr::accessible($this->value)) { + unset($this->value[$key]); + } + } +} diff --git a/src/Tightenco/Support/Str.php b/src/Tightenco/Support/Str.php new file mode 100644 index 0000000..0271e45 --- /dev/null +++ b/src/Tightenco/Support/Str.php @@ -0,0 +1,683 @@ + $val) { + $value = str_replace($val, $key, $value); + } + + return preg_replace('/[^\x20-\x7E]/u', '', $value); + } + + /** + * Get the portion of a string before a given value. + * + * @param string $subject + * @param string $search + * @return string + */ + public static function before($subject, $search) + { + return $search === '' ? $subject : explode($search, $subject)[0]; + } + + /** + * Convert a value to camel case. + * + * @param string $value + * @return string + */ + public static function camel($value) + { + if (isset(static::$camelCache[$value])) { + return static::$camelCache[$value]; + } + + return static::$camelCache[$value] = lcfirst(static::studly($value)); + } + + /** + * Determine if a given string contains a given substring. + * + * @param string $haystack + * @param string|array $needles + * @return bool + */ + public static function contains($haystack, $needles) + { + foreach ((array) $needles as $needle) { + if ($needle !== '' && mb_strpos($haystack, $needle) !== false) { + return true; + } + } + + return false; + } + + /** + * Determine if a given string ends with a given substring. + * + * @param string $haystack + * @param string|array $needles + * @return bool + */ + public static function endsWith($haystack, $needles) + { + foreach ((array) $needles as $needle) { + if (substr($haystack, -strlen($needle)) === (string) $needle) { + return true; + } + } + + return false; + } + + /** + * Cap a string with a single instance of a given value. + * + * @param string $value + * @param string $cap + * @return string + */ + public static function finish($value, $cap) + { + $quoted = preg_quote($cap, '/'); + + return preg_replace('/(?:'.$quoted.')+$/u', '', $value).$cap; + } + + /** + * Determine if a given string matches a given pattern. + * + * @param string|array $pattern + * @param string $value + * @return bool + */ + public static function is($pattern, $value) + { + $patterns = is_array($pattern) ? $pattern : (array) $pattern; + + if (empty($patterns)) { + return false; + } + + foreach ($patterns as $pattern) { + // If the given value is an exact match we can of course return true right + // from the beginning. Otherwise, we will translate asterisks and do an + // actual pattern match against the two strings to see if they match. + if ($pattern == $value) { + return true; + } + + $pattern = preg_quote($pattern, '#'); + + // Asterisks are translated into zero-or-more regular expression wildcards + // to make it convenient to check if the strings starts with the given + // pattern such as "library/*", making any string check convenient. + $pattern = str_replace('\*', '.*', $pattern); + + if (preg_match('#^'.$pattern.'\z#u', $value) === 1) { + return true; + } + } + + return false; + } + + /** + * Convert a string to kebab case. + * + * @param string $value + * @return string + */ + public static function kebab($value) + { + return static::snake($value, '-'); + } + + /** + * Return the length of the given string. + * + * @param string $value + * @param string $encoding + * @return int + */ + public static function length($value, $encoding = null) + { + if ($encoding) { + return mb_strlen($value, $encoding); + } + + return mb_strlen($value); + } + + /** + * Limit the number of characters in a string. + * + * @param string $value + * @param int $limit + * @param string $end + * @return string + */ + public static function limit($value, $limit = 100, $end = '...') + { + if (mb_strwidth($value, 'UTF-8') <= $limit) { + return $value; + } + + return rtrim(mb_strimwidth($value, 0, $limit, '', 'UTF-8')).$end; + } + + /** + * Convert the given string to lower-case. + * + * @param string $value + * @return string + */ + public static function lower($value) + { + return mb_strtolower($value, 'UTF-8'); + } + + /** + * Limit the number of words in a string. + * + * @param string $value + * @param int $words + * @param string $end + * @return string + */ + public static function words($value, $words = 100, $end = '...') + { + preg_match('/^\s*+(?:\S++\s*+){1,'.$words.'}/u', $value, $matches); + + if (! isset($matches[0]) || static::length($value) === static::length($matches[0])) { + return $value; + } + + return rtrim($matches[0]).$end; + } + + /** + * Parse a Class@method style callback into class and method. + * + * @param string $callback + * @param string|null $default + * @return array + */ + public static function parseCallback($callback, $default = null) + { + return static::contains($callback, '@') ? explode('@', $callback, 2) : [$callback, $default]; + } + + /** + * Get the plural form of an English word. + * + * @param string $value + * @param int $count + * @return string + */ + public static function plural($value, $count = 2) + { + return Pluralizer::plural($value, $count); + } + + /** + * Generate a more truly "random" alpha-numeric string. + * + * @param int $length + * @return string + */ + public static function random($length = 16) + { + $string = ''; + + while (($len = strlen($string)) < $length) { + $size = $length - $len; + + $bytes = random_bytes($size); + + $string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size); + } + + return $string; + } + + /** + * Replace a given value in the string sequentially with an array. + * + * @param string $search + * @param array $replace + * @param string $subject + * @return string + */ + public static function replaceArray($search, array $replace, $subject) + { + foreach ($replace as $value) { + $subject = static::replaceFirst($search, $value, $subject); + } + + return $subject; + } + + /** + * Replace the first occurrence of a given value in the string. + * + * @param string $search + * @param string $replace + * @param string $subject + * @return string + */ + public static function replaceFirst($search, $replace, $subject) + { + if ($search == '') { + return $subject; + } + + $position = strpos($subject, $search); + + if ($position !== false) { + return substr_replace($subject, $replace, $position, strlen($search)); + } + + return $subject; + } + + /** + * Replace the last occurrence of a given value in the string. + * + * @param string $search + * @param string $replace + * @param string $subject + * @return string + */ + public static function replaceLast($search, $replace, $subject) + { + $position = strrpos($subject, $search); + + if ($position !== false) { + return substr_replace($subject, $replace, $position, strlen($search)); + } + + return $subject; + } + + /** + * Begin a string with a single instance of a given value. + * + * @param string $value + * @param string $prefix + * @return string + */ + public static function start($value, $prefix) + { + $quoted = preg_quote($prefix, '/'); + + return $prefix.preg_replace('/^(?:'.$quoted.')+/u', '', $value); + } + + /** + * Convert the given string to upper-case. + * + * @param string $value + * @return string + */ + public static function upper($value) + { + return mb_strtoupper($value, 'UTF-8'); + } + + /** + * Convert the given string to title case. + * + * @param string $value + * @return string + */ + public static function title($value) + { + return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8'); + } + + /** + * Get the singular form of an English word. + * + * @param string $value + * @return string + */ + public static function singular($value) + { + return Pluralizer::singular($value); + } + + /** + * Generate a URL friendly "slug" from a given string. + * + * @param string $title + * @param string $separator + * @param string $language + * @return string + */ + public static function slug($title, $separator = '-', $language = 'en') + { + $title = static::ascii($title, $language); + + // Convert all dashes/underscores into separator + $flip = $separator == '-' ? '_' : '-'; + + $title = preg_replace('!['.preg_quote($flip).']+!u', $separator, $title); + + // Replace @ with the word 'at' + $title = str_replace('@', $separator.'at'.$separator, $title); + + // Remove all characters that are not the separator, letters, numbers, or whitespace. + $title = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', mb_strtolower($title)); + + // Replace all separator characters and whitespace by a single separator + $title = preg_replace('!['.preg_quote($separator).'\s]+!u', $separator, $title); + + return trim($title, $separator); + } + + /** + * Convert a string to snake case. + * + * @param string $value + * @param string $delimiter + * @return string + */ + public static function snake($value, $delimiter = '_') + { + $key = $value; + + if (isset(static::$snakeCache[$key][$delimiter])) { + return static::$snakeCache[$key][$delimiter]; + } + + if (! ctype_lower($value)) { + $value = preg_replace('/\s+/u', '', ucwords($value)); + + $value = static::lower(preg_replace('/(.)(?=[A-Z])/u', '$1'.$delimiter, $value)); + } + + return static::$snakeCache[$key][$delimiter] = $value; + } + + /** + * Determine if a given string starts with a given substring. + * + * @param string $haystack + * @param string|array $needles + * @return bool + */ + public static function startsWith($haystack, $needles) + { + foreach ((array) $needles as $needle) { + if ($needle !== '' && substr($haystack, 0, strlen($needle)) === (string) $needle) { + return true; + } + } + + return false; + } + + /** + * Convert a value to studly caps case. + * + * @param string $value + * @return string + */ + public static function studly($value) + { + $key = $value; + + if (isset(static::$studlyCache[$key])) { + return static::$studlyCache[$key]; + } + + $value = ucwords(str_replace(['-', '_'], ' ', $value)); + + return static::$studlyCache[$key] = str_replace(' ', '', $value); + } + + /** + * Returns the portion of string specified by the start and length parameters. + * + * @param string $string + * @param int $start + * @param int|null $length + * @return string + */ + public static function substr($string, $start, $length = null) + { + return mb_substr($string, $start, $length, 'UTF-8'); + } + + /** + * Make a string's first character uppercase. + * + * @param string $string + * @return string + */ + public static function ucfirst($string) + { + return static::upper(static::substr($string, 0, 1)).static::substr($string, 1); + } + + /** + * Returns the replacements for the ascii method. + * + * Note: Adapted from Stringy\Stringy. + * + * @see https://github.com/danielstjules/Stringy/blob/3.1.0/LICENSE.txt + * + * @return array + */ + protected static function charsArray() + { + static $charsArray; + + if (isset($charsArray)) { + return $charsArray; + } + + return $charsArray = [ + '0' => ['°', '₀', '۰', '0'], + '1' => ['¹', '₁', '۱', '1'], + '2' => ['²', '₂', '۲', '2'], + '3' => ['³', '₃', '۳', '3'], + '4' => ['⁴', '₄', '۴', '٤', '4'], + '5' => ['⁵', '₅', '۵', '٥', '5'], + '6' => ['⁶', '₆', '۶', '٦', '6'], + '7' => ['⁷', '₇', '۷', '7'], + '8' => ['⁸', '₈', '۸', '8'], + '9' => ['⁹', '₉', '۹', '9'], + 'a' => ['à', 'á', 'ả', 'ã', 'ạ', 'ă', 'ắ', 'ằ', 'ẳ', 'ẵ', 'ặ', 'â', 'ấ', 'ầ', 'ẩ', 'ẫ', 'ậ', 'ā', 'ą', 'å', 'α', 'ά', 'ἀ', 'ἁ', 'ἂ', 'ἃ', 'ἄ', 'ἅ', 'ἆ', 'ἇ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ὰ', 'ά', 'ᾰ', 'ᾱ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'а', 'أ', 'အ', 'ာ', 'ါ', 'ǻ', 'ǎ', 'ª', 'ა', 'अ', 'ا', 'a', 'ä'], + 'b' => ['б', 'β', 'ب', 'ဗ', 'ბ', 'b'], + 'c' => ['ç', 'ć', 'č', 'ĉ', 'ċ', 'c'], + 'd' => ['ď', 'ð', 'đ', 'ƌ', 'ȡ', 'ɖ', 'ɗ', 'ᵭ', 'ᶁ', 'ᶑ', 'д', 'δ', 'د', 'ض', 'ဍ', 'ဒ', 'დ', 'd'], + 'e' => ['é', 'è', 'ẻ', 'ẽ', 'ẹ', 'ê', 'ế', 'ề', 'ể', 'ễ', 'ệ', 'ë', 'ē', 'ę', 'ě', 'ĕ', 'ė', 'ε', 'έ', 'ἐ', 'ἑ', 'ἒ', 'ἓ', 'ἔ', 'ἕ', 'ὲ', 'έ', 'е', 'ё', 'э', 'є', 'ə', 'ဧ', 'ေ', 'ဲ', 'ე', 'ए', 'إ', 'ئ', 'e'], + 'f' => ['ф', 'φ', 'ف', 'ƒ', 'ფ', 'f'], + 'g' => ['ĝ', 'ğ', 'ġ', 'ģ', 'г', 'ґ', 'γ', 'ဂ', 'გ', 'گ', 'g'], + 'h' => ['ĥ', 'ħ', 'η', 'ή', 'ح', 'ه', 'ဟ', 'ှ', 'ჰ', 'h'], + 'i' => ['í', 'ì', 'ỉ', 'ĩ', 'ị', 'î', 'ï', 'ī', 'ĭ', 'į', 'ı', 'ι', 'ί', 'ϊ', 'ΐ', 'ἰ', 'ἱ', 'ἲ', 'ἳ', 'ἴ', 'ἵ', 'ἶ', 'ἷ', 'ὶ', 'ί', 'ῐ', 'ῑ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'і', 'ї', 'и', 'ဣ', 'ိ', 'ီ', 'ည်', 'ǐ', 'ი', 'इ', 'ی', 'i'], + 'j' => ['ĵ', 'ј', 'Ј', 'ჯ', 'ج', 'j'], + 'k' => ['ķ', 'ĸ', 'к', 'κ', 'Ķ', 'ق', 'ك', 'က', 'კ', 'ქ', 'ک', 'k'], + 'l' => ['ł', 'ľ', 'ĺ', 'ļ', 'ŀ', 'л', 'λ', 'ل', 'လ', 'ლ', 'l'], + 'm' => ['м', 'μ', 'م', 'မ', 'მ', 'm'], + 'n' => ['ñ', 'ń', 'ň', 'ņ', 'ʼn', 'ŋ', 'ν', 'н', 'ن', 'န', 'ნ', 'n'], + 'o' => ['ó', 'ò', 'ỏ', 'õ', 'ọ', 'ô', 'ố', 'ồ', 'ổ', 'ỗ', 'ộ', 'ơ', 'ớ', 'ờ', 'ở', 'ỡ', 'ợ', 'ø', 'ō', 'ő', 'ŏ', 'ο', 'ὀ', 'ὁ', 'ὂ', 'ὃ', 'ὄ', 'ὅ', 'ὸ', 'ό', 'о', 'و', 'θ', 'ို', 'ǒ', 'ǿ', 'º', 'ო', 'ओ', 'o', 'ö'], + 'p' => ['п', 'π', 'ပ', 'პ', 'پ', 'p'], + 'q' => ['ყ', 'q'], + 'r' => ['ŕ', 'ř', 'ŗ', 'р', 'ρ', 'ر', 'რ', 'r'], + 's' => ['ś', 'š', 'ş', 'с', 'σ', 'ș', 'ς', 'س', 'ص', 'စ', 'ſ', 'ს', 's'], + 't' => ['ť', 'ţ', 'т', 'τ', 'ț', 'ت', 'ط', 'ဋ', 'တ', 'ŧ', 'თ', 'ტ', 't'], + 'u' => ['ú', 'ù', 'ủ', 'ũ', 'ụ', 'ư', 'ứ', 'ừ', 'ử', 'ữ', 'ự', 'û', 'ū', 'ů', 'ű', 'ŭ', 'ų', 'µ', 'у', 'ဉ', 'ု', 'ူ', 'ǔ', 'ǖ', 'ǘ', 'ǚ', 'ǜ', 'უ', 'उ', 'u', 'ў', 'ü'], + 'v' => ['в', 'ვ', 'ϐ', 'v'], + 'w' => ['ŵ', 'ω', 'ώ', 'ဝ', 'ွ', 'w'], + 'x' => ['χ', 'ξ', 'x'], + 'y' => ['ý', 'ỳ', 'ỷ', 'ỹ', 'ỵ', 'ÿ', 'ŷ', 'й', 'ы', 'υ', 'ϋ', 'ύ', 'ΰ', 'ي', 'ယ', 'y'], + 'z' => ['ź', 'ž', 'ż', 'з', 'ζ', 'ز', 'ဇ', 'ზ', 'z'], + 'aa' => ['ع', 'आ', 'آ'], + 'ae' => ['æ', 'ǽ'], + 'ai' => ['ऐ'], + 'ch' => ['ч', 'ჩ', 'ჭ', 'چ'], + 'dj' => ['ђ', 'đ'], + 'dz' => ['џ', 'ძ'], + 'ei' => ['ऍ'], + 'gh' => ['غ', 'ღ'], + 'ii' => ['ई'], + 'ij' => ['ij'], + 'kh' => ['х', 'خ', 'ხ'], + 'lj' => ['љ'], + 'nj' => ['њ'], + 'oe' => ['ö', 'œ', 'ؤ'], + 'oi' => ['ऑ'], + 'oii' => ['ऒ'], + 'ps' => ['ψ'], + 'sh' => ['ш', 'შ', 'ش'], + 'shch' => ['щ'], + 'ss' => ['ß'], + 'sx' => ['ŝ'], + 'th' => ['þ', 'ϑ', 'ث', 'ذ', 'ظ'], + 'ts' => ['ц', 'ც', 'წ'], + 'ue' => ['ü'], + 'uu' => ['ऊ'], + 'ya' => ['я'], + 'yu' => ['ю'], + 'zh' => ['ж', 'ჟ', 'ژ'], + '(c)' => ['©'], + 'A' => ['Á', 'À', 'Ả', 'Ã', 'Ạ', 'Ă', 'Ắ', 'Ằ', 'Ẳ', 'Ẵ', 'Ặ', 'Â', 'Ấ', 'Ầ', 'Ẩ', 'Ẫ', 'Ậ', 'Å', 'Ā', 'Ą', 'Α', 'Ά', 'Ἀ', 'Ἁ', 'Ἂ', 'Ἃ', 'Ἄ', 'Ἅ', 'Ἆ', 'Ἇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'Ᾰ', 'Ᾱ', 'Ὰ', 'Ά', 'ᾼ', 'А', 'Ǻ', 'Ǎ', 'A', 'Ä'], + 'B' => ['Б', 'Β', 'ब', 'B'], + 'C' => ['Ç', 'Ć', 'Č', 'Ĉ', 'Ċ', 'C'], + 'D' => ['Ď', 'Ð', 'Đ', 'Ɖ', 'Ɗ', 'Ƌ', 'ᴅ', 'ᴆ', 'Д', 'Δ', 'D'], + 'E' => ['É', 'È', 'Ẻ', 'Ẽ', 'Ẹ', 'Ê', 'Ế', 'Ề', 'Ể', 'Ễ', 'Ệ', 'Ë', 'Ē', 'Ę', 'Ě', 'Ĕ', 'Ė', 'Ε', 'Έ', 'Ἐ', 'Ἑ', 'Ἒ', 'Ἓ', 'Ἔ', 'Ἕ', 'Έ', 'Ὲ', 'Е', 'Ё', 'Э', 'Є', 'Ə', 'E'], + 'F' => ['Ф', 'Φ', 'F'], + 'G' => ['Ğ', 'Ġ', 'Ģ', 'Г', 'Ґ', 'Γ', 'G'], + 'H' => ['Η', 'Ή', 'Ħ', 'H'], + 'I' => ['Í', 'Ì', 'Ỉ', 'Ĩ', 'Ị', 'Î', 'Ï', 'Ī', 'Ĭ', 'Į', 'İ', 'Ι', 'Ί', 'Ϊ', 'Ἰ', 'Ἱ', 'Ἳ', 'Ἴ', 'Ἵ', 'Ἶ', 'Ἷ', 'Ῐ', 'Ῑ', 'Ὶ', 'Ί', 'И', 'І', 'Ї', 'Ǐ', 'ϒ', 'I'], + 'J' => ['J'], + 'K' => ['К', 'Κ', 'K'], + 'L' => ['Ĺ', 'Ł', 'Л', 'Λ', 'Ļ', 'Ľ', 'Ŀ', 'ल', 'L'], + 'M' => ['М', 'Μ', 'M'], + 'N' => ['Ń', 'Ñ', 'Ň', 'Ņ', 'Ŋ', 'Н', 'Ν', 'N'], + 'O' => ['Ó', 'Ò', 'Ỏ', 'Õ', 'Ọ', 'Ô', 'Ố', 'Ồ', 'Ổ', 'Ỗ', 'Ộ', 'Ơ', 'Ớ', 'Ờ', 'Ở', 'Ỡ', 'Ợ', 'Ø', 'Ō', 'Ő', 'Ŏ', 'Ο', 'Ό', 'Ὀ', 'Ὁ', 'Ὂ', 'Ὃ', 'Ὄ', 'Ὅ', 'Ὸ', 'Ό', 'О', 'Θ', 'Ө', 'Ǒ', 'Ǿ', 'O', 'Ö'], + 'P' => ['П', 'Π', 'P'], + 'Q' => ['Q'], + 'R' => ['Ř', 'Ŕ', 'Р', 'Ρ', 'Ŗ', 'R'], + 'S' => ['Ş', 'Ŝ', 'Ș', 'Š', 'Ś', 'С', 'Σ', 'S'], + 'T' => ['Ť', 'Ţ', 'Ŧ', 'Ț', 'Т', 'Τ', 'T'], + 'U' => ['Ú', 'Ù', 'Ủ', 'Ũ', 'Ụ', 'Ư', 'Ứ', 'Ừ', 'Ử', 'Ữ', 'Ự', 'Û', 'Ū', 'Ů', 'Ű', 'Ŭ', 'Ų', 'У', 'Ǔ', 'Ǖ', 'Ǘ', 'Ǚ', 'Ǜ', 'U', 'Ў', 'Ü'], + 'V' => ['В', 'V'], + 'W' => ['Ω', 'Ώ', 'Ŵ', 'W'], + 'X' => ['Χ', 'Ξ', 'X'], + 'Y' => ['Ý', 'Ỳ', 'Ỷ', 'Ỹ', 'Ỵ', 'Ÿ', 'Ῠ', 'Ῡ', 'Ὺ', 'Ύ', 'Ы', 'Й', 'Υ', 'Ϋ', 'Ŷ', 'Y'], + 'Z' => ['Ź', 'Ž', 'Ż', 'З', 'Ζ', 'Z'], + 'AE' => ['Æ', 'Ǽ'], + 'Ch' => ['Ч'], + 'Dj' => ['Ђ'], + 'Dz' => ['Џ'], + 'Gx' => ['Ĝ'], + 'Hx' => ['Ĥ'], + 'Ij' => ['IJ'], + 'Jx' => ['Ĵ'], + 'Kh' => ['Х'], + 'Lj' => ['Љ'], + 'Nj' => ['Њ'], + 'Oe' => ['Œ'], + 'Ps' => ['Ψ'], + 'Sh' => ['Ш'], + 'Shch' => ['Щ'], + 'Ss' => ['ẞ'], + 'Th' => ['Þ'], + 'Ts' => ['Ц'], + 'Ya' => ['Я'], + 'Yu' => ['Ю'], + 'Zh' => ['Ж'], + ' ' => ["\xC2\xA0", "\xE2\x80\x80", "\xE2\x80\x81", "\xE2\x80\x82", "\xE2\x80\x83", "\xE2\x80\x84", "\xE2\x80\x85", "\xE2\x80\x86", "\xE2\x80\x87", "\xE2\x80\x88", "\xE2\x80\x89", "\xE2\x80\x8A", "\xE2\x80\xAF", "\xE2\x81\x9F", "\xE3\x80\x80", "\xEF\xBE\xA0"], + ]; + } + + /** + * Returns the language specific replacements for the ascii method. + * + * Note: Adapted from Stringy\Stringy. + * + * @see https://github.com/danielstjules/Stringy/blob/3.1.0/LICENSE.txt + * + * @param string $language + * @return array|null + */ + protected static function languageSpecificCharsArray($language) + { + static $languageSpecific; + + if (! isset($languageSpecific)) { + $languageSpecific = [ + 'bg' => [ + ['х', 'Х', 'щ', 'Щ', 'ъ', 'Ъ', 'ь', 'Ь'], + ['h', 'H', 'sht', 'SHT', 'a', 'А', 'y', 'Y'], + ], + 'de' => [ + ['ä', 'ö', 'ü', 'Ä', 'Ö', 'Ü'], + ['ae', 'oe', 'ue', 'AE', 'OE', 'UE'], + ], + ]; + } + + return $languageSpecific[$language] ?? null; + } +} diff --git a/src/Illuminate/Support/Traits/Macroable.php b/src/Tightenco/Support/Traits/Macroable.php similarity index 98% rename from src/Illuminate/Support/Traits/Macroable.php rename to src/Tightenco/Support/Traits/Macroable.php index a7703b1..874ce7b 100644 --- a/src/Illuminate/Support/Traits/Macroable.php +++ b/src/Tightenco/Support/Traits/Macroable.php @@ -1,6 +1,6 @@ Tightenco\Support\Collection::class, + Illuminate\Support\Arr::class => Tightenco\Support\Arr::class, + Illuminate\Support\Carbon::class => Tightenco\Support\Carbon::class, + Illuminate\Support\HigherOrderCollectionProxy::class => Tightenco\Support\HigherOrderCollectionProxy::class, + Illuminate\Support\HigherOrderTapProxy::class => Tightenco\Support\HigherOrderTapProxy::class, + Illuminate\Support\HtmlString::class => Tightenco\Support\HtmlString::class, + Illuminate\Support\Optional::class => Tightenco\Support\Optional::class, + Illuminate\Support\Str::class => Tightenco\Support\Str::class, + Illuminate\Support\Debug\Dumper::class => Tightenco\Support\Debug\Dumper::class, + Illuminate\Support\Debug\HtmlDumper::class => Tightenco\Support\Debug\HtmlDumper::class, +]; + +foreach ($aliases as $illuminate => $tighten) { + if (class_exists($illuminate) && ! interface_exists($illuminate) && ! trait_exists($illuminate)) { + class_alias($illuminate, $tighten); + } +} diff --git a/src/Tightenco/Support/helpers.php b/src/Tightenco/Support/helpers.php new file mode 100755 index 0000000..edc4654 --- /dev/null +++ b/src/Tightenco/Support/helpers.php @@ -0,0 +1,116 @@ +all(); + } elseif (! is_array($target)) { + return value($default); + } + + $result = Arr::pluck($target, $key); + + return in_array('*', $key) ? Arr::collapse($result) : $result; + } + + if (Arr::accessible($target) && Arr::exists($target, $segment)) { + $target = $target[$segment]; + } elseif (is_object($target) && isset($target->{$segment})) { + $target = $target->{$segment}; + } else { + return value($default); + } + } + + return $target; + } +} + +if (! function_exists('with')) { + /** + * Return the given object. Useful for chaining. + * + * @param mixed $object + * @return mixed + */ + function with($object) + { + return $object; + } +} + +if (! function_exists('dd')) { + /** + * Dump the passed variables and end the script. + * + * @param mixed + * @return void + */ + function dd(...$args) + { + foreach ($args as $x) { + (new Dumper)->dump($x); + } + die(1); + } +} diff --git a/stubs/src/Tightenco/Support/alias.php b/stubs/src/Tightenco/Support/alias.php new file mode 100644 index 0000000..fb910e0 --- /dev/null +++ b/stubs/src/Tightenco/Support/alias.php @@ -0,0 +1,9 @@ + $tighten) { + if (class_exists($illuminate) && ! interface_exists($illuminate) && ! trait_exists($illuminate)) { + class_alias($illuminate, $tighten); + } +} diff --git a/src/Illuminate/Support/helpers.php b/stubs/src/Tightenco/Support/helpers.php old mode 100644 new mode 100755 similarity index 100% rename from src/Illuminate/Support/helpers.php rename to stubs/src/Tightenco/Support/helpers.php diff --git a/stubs/tests/bootstrap.php b/stubs/tests/bootstrap.php new file mode 100644 index 0000000..8b39c17 --- /dev/null +++ b/stubs/tests/bootstrap.php @@ -0,0 +1,5 @@ +assertTrue(Arr::accessible([])); + $this->assertTrue(Arr::accessible([1, 2])); + $this->assertTrue(Arr::accessible(['a' => 1, 'b' => 2])); + $this->assertTrue(Arr::accessible(new Collection)); + + $this->assertFalse(Arr::accessible(null)); + $this->assertFalse(Arr::accessible('abc')); + $this->assertFalse(Arr::accessible(new stdClass)); + $this->assertFalse(Arr::accessible((object) ['a' => 1, 'b' => 2])); + } + + public function testAdd() + { + $array = Arr::add(['name' => 'Desk'], 'price', 100); + $this->assertEquals(['name' => 'Desk', 'price' => 100], $array); + } + + public function testCollapse() + { + $data = [['foo', 'bar'], ['baz']]; + $this->assertEquals(['foo', 'bar', 'baz'], Arr::collapse($data)); + } + + public function testCrossJoin() + { + // Single dimension + $this->assertSame( + [[1, 'a'], [1, 'b'], [1, 'c']], + Arr::crossJoin([1], ['a', 'b', 'c']) + ); + + // Square matrix + $this->assertSame( + [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']], + Arr::crossJoin([1, 2], ['a', 'b']) + ); + + // Rectangular matrix + $this->assertSame( + [[1, 'a'], [1, 'b'], [1, 'c'], [2, 'a'], [2, 'b'], [2, 'c']], + Arr::crossJoin([1, 2], ['a', 'b', 'c']) + ); + + // 3D matrix + $this->assertSame( + [ + [1, 'a', 'I'], [1, 'a', 'II'], [1, 'a', 'III'], + [1, 'b', 'I'], [1, 'b', 'II'], [1, 'b', 'III'], + [2, 'a', 'I'], [2, 'a', 'II'], [2, 'a', 'III'], + [2, 'b', 'I'], [2, 'b', 'II'], [2, 'b', 'III'], + ], + Arr::crossJoin([1, 2], ['a', 'b'], ['I', 'II', 'III']) + ); + + // With 1 empty dimension + $this->assertEmpty(Arr::crossJoin([], ['a', 'b'], ['I', 'II', 'III'])); + $this->assertEmpty(Arr::crossJoin([1, 2], [], ['I', 'II', 'III'])); + $this->assertEmpty(Arr::crossJoin([1, 2], ['a', 'b'], [])); + + // With empty arrays + $this->assertEmpty(Arr::crossJoin([], [], [])); + $this->assertEmpty(Arr::crossJoin([], [])); + $this->assertEmpty(Arr::crossJoin([])); + + // Not really a proper usage, still, test for preserving BC + $this->assertSame([[]], Arr::crossJoin()); + } + + public function testDivide() + { + list($keys, $values) = Arr::divide(['name' => 'Desk']); + $this->assertEquals(['name'], $keys); + $this->assertEquals(['Desk'], $values); + } + + public function testDot() + { + $array = Arr::dot(['foo' => ['bar' => 'baz']]); + $this->assertEquals(['foo.bar' => 'baz'], $array); + + $array = Arr::dot([]); + $this->assertEquals([], $array); + + $array = Arr::dot(['foo' => []]); + $this->assertEquals(['foo' => []], $array); + + $array = Arr::dot(['foo' => ['bar' => []]]); + $this->assertEquals(['foo.bar' => []], $array); + } + + public function testExcept() + { + $array = ['name' => 'Desk', 'price' => 100]; + $array = Arr::except($array, ['price']); + $this->assertEquals(['name' => 'Desk'], $array); + } + + public function testExists() + { + $this->assertTrue(Arr::exists([1], 0)); + $this->assertTrue(Arr::exists([null], 0)); + $this->assertTrue(Arr::exists(['a' => 1], 'a')); + $this->assertTrue(Arr::exists(['a' => null], 'a')); + $this->assertTrue(Arr::exists(new Collection(['a' => null]), 'a')); + + $this->assertFalse(Arr::exists([1], 1)); + $this->assertFalse(Arr::exists([null], 1)); + $this->assertFalse(Arr::exists(['a' => 1], 0)); + $this->assertFalse(Arr::exists(new Collection(['a' => null]), 'b')); + } + + public function testFirst() + { + $array = [100, 200, 300]; + + $value = Arr::first($array, function ($value) { + return $value >= 150; + }); + + $this->assertEquals(200, $value); + $this->assertEquals(100, Arr::first($array)); + } + + public function testLast() + { + $array = [100, 200, 300]; + + $last = Arr::last($array, function ($value) { + return $value < 250; + }); + $this->assertEquals(200, $last); + + $last = Arr::last($array, function ($value, $key) { + return $key < 2; + }); + $this->assertEquals(200, $last); + + $this->assertEquals(300, Arr::last($array)); + } + + public function testFlatten() + { + // Flat arrays are unaffected + $array = ['#foo', '#bar', '#baz']; + $this->assertEquals(['#foo', '#bar', '#baz'], Arr::flatten(['#foo', '#bar', '#baz'])); + + // Nested arrays are flattened with existing flat items + $array = [['#foo', '#bar'], '#baz']; + $this->assertEquals(['#foo', '#bar', '#baz'], Arr::flatten($array)); + + // Flattened array includes "null" items + $array = [['#foo', null], '#baz', null]; + $this->assertEquals(['#foo', null, '#baz', null], Arr::flatten($array)); + + // Sets of nested arrays are flattened + $array = [['#foo', '#bar'], ['#baz']]; + $this->assertEquals(['#foo', '#bar', '#baz'], Arr::flatten($array)); + + // Deeply nested arrays are flattened + $array = [['#foo', ['#bar']], ['#baz']]; + $this->assertEquals(['#foo', '#bar', '#baz'], Arr::flatten($array)); + + // Nested arrays are flattened alongside arrays + $array = [new Collection(['#foo', '#bar']), ['#baz']]; + $this->assertEquals(['#foo', '#bar', '#baz'], Arr::flatten($array)); + + // Nested arrays containing plain arrays are flattened + $array = [new Collection(['#foo', ['#bar']]), ['#baz']]; + $this->assertEquals(['#foo', '#bar', '#baz'], Arr::flatten($array)); + + // Nested arrays containing arrays are flattened + $array = [['#foo', new Collection(['#bar'])], ['#baz']]; + $this->assertEquals(['#foo', '#bar', '#baz'], Arr::flatten($array)); + + // Nested arrays containing arrays containing arrays are flattened + $array = [['#foo', new Collection(['#bar', ['#zap']])], ['#baz']]; + $this->assertEquals(['#foo', '#bar', '#zap', '#baz'], Arr::flatten($array)); + } + + public function testFlattenWithDepth() + { + // No depth flattens recursively + $array = [['#foo', ['#bar', ['#baz']]], '#zap']; + $this->assertEquals(['#foo', '#bar', '#baz', '#zap'], Arr::flatten($array)); + + // Specifying a depth only flattens to that depth + $array = [['#foo', ['#bar', ['#baz']]], '#zap']; + $this->assertEquals(['#foo', ['#bar', ['#baz']], '#zap'], Arr::flatten($array, 1)); + + $array = [['#foo', ['#bar', ['#baz']]], '#zap']; + $this->assertEquals(['#foo', '#bar', ['#baz'], '#zap'], Arr::flatten($array, 2)); + } + + public function testGet() + { + $array = ['products.desk' => ['price' => 100]]; + $this->assertEquals(['price' => 100], Arr::get($array, 'products.desk')); + + $array = ['products' => ['desk' => ['price' => 100]]]; + $value = Arr::get($array, 'products.desk'); + $this->assertEquals(['price' => 100], $value); + + // Test null array values + $array = ['foo' => null, 'bar' => ['baz' => null]]; + $this->assertNull(Arr::get($array, 'foo', 'default')); + $this->assertNull(Arr::get($array, 'bar.baz', 'default')); + + // Test direct ArrayAccess object + $array = ['products' => ['desk' => ['price' => 100]]]; + $arrayAccessObject = new ArrayObject($array); + $value = Arr::get($arrayAccessObject, 'products.desk'); + $this->assertEquals(['price' => 100], $value); + + // Test array containing ArrayAccess object + $arrayAccessChild = new ArrayObject(['products' => ['desk' => ['price' => 100]]]); + $array = ['child' => $arrayAccessChild]; + $value = Arr::get($array, 'child.products.desk'); + $this->assertEquals(['price' => 100], $value); + + // Test array containing multiple nested ArrayAccess objects + $arrayAccessChild = new ArrayObject(['products' => ['desk' => ['price' => 100]]]); + $arrayAccessParent = new ArrayObject(['child' => $arrayAccessChild]); + $array = ['parent' => $arrayAccessParent]; + $value = Arr::get($array, 'parent.child.products.desk'); + $this->assertEquals(['price' => 100], $value); + + // Test missing ArrayAccess object field + $arrayAccessChild = new ArrayObject(['products' => ['desk' => ['price' => 100]]]); + $arrayAccessParent = new ArrayObject(['child' => $arrayAccessChild]); + $array = ['parent' => $arrayAccessParent]; + $value = Arr::get($array, 'parent.child.desk'); + $this->assertNull($value); + + // Test missing ArrayAccess object field + $arrayAccessObject = new ArrayObject(['products' => ['desk' => null]]); + $array = ['parent' => $arrayAccessObject]; + $value = Arr::get($array, 'parent.products.desk.price'); + $this->assertNull($value); + + // Test null ArrayAccess object fields + $array = new ArrayObject(['foo' => null, 'bar' => new ArrayObject(['baz' => null])]); + $this->assertNull(Arr::get($array, 'foo', 'default')); + $this->assertNull(Arr::get($array, 'bar.baz', 'default')); + + // Test null key returns the whole array + $array = ['foo', 'bar']; + $this->assertEquals($array, Arr::get($array, null)); + + // Test $array not an array + $this->assertSame('default', Arr::get(null, 'foo', 'default')); + $this->assertSame('default', Arr::get(false, 'foo', 'default')); + + // Test $array not an array and key is null + $this->assertSame('default', Arr::get(null, null, 'default')); + + // Test $array is empty and key is null + $this->assertEmpty(Arr::get([], null)); + $this->assertEmpty(Arr::get([], null, 'default')); + } + + public function testHas() + { + $array = ['products.desk' => ['price' => 100]]; + $this->assertTrue(Arr::has($array, 'products.desk')); + + $array = ['products' => ['desk' => ['price' => 100]]]; + $this->assertTrue(Arr::has($array, 'products.desk')); + $this->assertTrue(Arr::has($array, 'products.desk.price')); + $this->assertFalse(Arr::has($array, 'products.foo')); + $this->assertFalse(Arr::has($array, 'products.desk.foo')); + + $array = ['foo' => null, 'bar' => ['baz' => null]]; + $this->assertTrue(Arr::has($array, 'foo')); + $this->assertTrue(Arr::has($array, 'bar.baz')); + + $array = new ArrayObject(['foo' => 10, 'bar' => new ArrayObject(['baz' => 10])]); + $this->assertTrue(Arr::has($array, 'foo')); + $this->assertTrue(Arr::has($array, 'bar')); + $this->assertTrue(Arr::has($array, 'bar.baz')); + $this->assertFalse(Arr::has($array, 'xxx')); + $this->assertFalse(Arr::has($array, 'xxx.yyy')); + $this->assertFalse(Arr::has($array, 'foo.xxx')); + $this->assertFalse(Arr::has($array, 'bar.xxx')); + + $array = new ArrayObject(['foo' => null, 'bar' => new ArrayObject(['baz' => null])]); + $this->assertTrue(Arr::has($array, 'foo')); + $this->assertTrue(Arr::has($array, 'bar.baz')); + + $array = ['foo', 'bar']; + $this->assertFalse(Arr::has($array, null)); + + $this->assertFalse(Arr::has(null, 'foo')); + $this->assertFalse(Arr::has(false, 'foo')); + + $this->assertFalse(Arr::has(null, null)); + $this->assertFalse(Arr::has([], null)); + + $array = ['products' => ['desk' => ['price' => 100]]]; + $this->assertTrue(Arr::has($array, ['products.desk'])); + $this->assertTrue(Arr::has($array, ['products.desk', 'products.desk.price'])); + $this->assertTrue(Arr::has($array, ['products', 'products'])); + $this->assertFalse(Arr::has($array, ['foo'])); + $this->assertFalse(Arr::has($array, [])); + $this->assertFalse(Arr::has($array, ['products.desk', 'products.price'])); + + $this->assertFalse(Arr::has([], [null])); + $this->assertFalse(Arr::has(null, [null])); + } + + public function testIsAssoc() + { + $this->assertTrue(Arr::isAssoc(['a' => 'a', 0 => 'b'])); + $this->assertTrue(Arr::isAssoc([1 => 'a', 0 => 'b'])); + $this->assertTrue(Arr::isAssoc([1 => 'a', 2 => 'b'])); + $this->assertFalse(Arr::isAssoc([0 => 'a', 1 => 'b'])); + $this->assertFalse(Arr::isAssoc(['a', 'b'])); + } + + public function testOnly() + { + $array = ['name' => 'Desk', 'price' => 100, 'orders' => 10]; + $array = Arr::only($array, ['name', 'price']); + $this->assertEquals(['name' => 'Desk', 'price' => 100], $array); + } + + public function testPluck() + { + $array = [ + ['developer' => ['name' => 'Taylor']], + ['developer' => ['name' => 'Abigail']], + ]; + + $array = Arr::pluck($array, 'developer.name'); + + $this->assertEquals(['Taylor', 'Abigail'], $array); + } + + public function testPluckWithArrayValue() + { + $array = [ + ['developer' => ['name' => 'Taylor']], + ['developer' => ['name' => 'Abigail']], + ]; + $array = Arr::pluck($array, ['developer', 'name']); + $this->assertEquals(['Taylor', 'Abigail'], $array); + } + + public function testPluckWithKeys() + { + $array = [ + ['name' => 'Taylor', 'role' => 'developer'], + ['name' => 'Abigail', 'role' => 'developer'], + ]; + + $test1 = Arr::pluck($array, 'role', 'name'); + $test2 = Arr::pluck($array, null, 'name'); + + $this->assertEquals([ + 'Taylor' => 'developer', + 'Abigail' => 'developer', + ], $test1); + + $this->assertEquals([ + 'Taylor' => ['name' => 'Taylor', 'role' => 'developer'], + 'Abigail' => ['name' => 'Abigail', 'role' => 'developer'], + ], $test2); + } + + public function testPluckWithCarbonKeys() + { + $array = [ + ['start' => new Carbon('2017-07-25 00:00:00'), 'end' => new Carbon('2017-07-30 00:00:00')], + ]; + $array = Arr::pluck($array, 'end', 'start'); + $this->assertEquals(['2017-07-25 00:00:00' => '2017-07-30 00:00:00'], $array); + } + + public function testPrepend() + { + $array = Arr::prepend(['one', 'two', 'three', 'four'], 'zero'); + $this->assertEquals(['zero', 'one', 'two', 'three', 'four'], $array); + + $array = Arr::prepend(['one' => 1, 'two' => 2], 0, 'zero'); + $this->assertEquals(['zero' => 0, 'one' => 1, 'two' => 2], $array); + } + + public function testPull() + { + $array = ['name' => 'Desk', 'price' => 100]; + $name = Arr::pull($array, 'name'); + $this->assertEquals('Desk', $name); + $this->assertEquals(['price' => 100], $array); + + // Only works on first level keys + $array = ['joe@example.com' => 'Joe', 'jane@localhost' => 'Jane']; + $name = Arr::pull($array, 'joe@example.com'); + $this->assertEquals('Joe', $name); + $this->assertEquals(['jane@localhost' => 'Jane'], $array); + + // Does not work for nested keys + $array = ['emails' => ['joe@example.com' => 'Joe', 'jane@localhost' => 'Jane']]; + $name = Arr::pull($array, 'emails.joe@example.com'); + $this->assertNull($name); + $this->assertEquals(['emails' => ['joe@example.com' => 'Joe', 'jane@localhost' => 'Jane']], $array); + } + + public function testRandom() + { + $random = Arr::random(['foo', 'bar', 'baz']); + $this->assertContains($random, ['foo', 'bar', 'baz']); + + $random = Arr::random(['foo', 'bar', 'baz'], 0); + $this->assertInternalType('array', $random); + $this->assertCount(0, $random); + + $random = Arr::random(['foo', 'bar', 'baz'], 1); + $this->assertInternalType('array', $random); + $this->assertCount(1, $random); + $this->assertContains($random[0], ['foo', 'bar', 'baz']); + + $random = Arr::random(['foo', 'bar', 'baz'], 2); + $this->assertInternalType('array', $random); + $this->assertCount(2, $random); + $this->assertContains($random[0], ['foo', 'bar', 'baz']); + $this->assertContains($random[1], ['foo', 'bar', 'baz']); + + $random = Arr::random(['foo', 'bar', 'baz'], '0'); + $this->assertInternalType('array', $random); + $this->assertCount(0, $random); + + $random = Arr::random(['foo', 'bar', 'baz'], '1'); + $this->assertInternalType('array', $random); + $this->assertCount(1, $random); + $this->assertContains($random[0], ['foo', 'bar', 'baz']); + + $random = Arr::random(['foo', 'bar', 'baz'], '2'); + $this->assertInternalType('array', $random); + $this->assertCount(2, $random); + $this->assertContains($random[0], ['foo', 'bar', 'baz']); + $this->assertContains($random[1], ['foo', 'bar', 'baz']); + } + + public function testRandomOnEmptyArray() + { + $random = Arr::random([], 0); + $this->assertInternalType('array', $random); + $this->assertCount(0, $random); + + $random = Arr::random([], '0'); + $this->assertInternalType('array', $random); + $this->assertCount(0, $random); + } + + public function testRandomThrowsAnErrorWhenRequestingMoreItemsThanAreAvailable() + { + $exceptions = 0; + + try { + Arr::random([]); + } catch (\InvalidArgumentException $e) { + $exceptions++; + } + + try { + Arr::random([], 1); + } catch (\InvalidArgumentException $e) { + $exceptions++; + } + + try { + Arr::random([], 2); + } catch (\InvalidArgumentException $e) { + $exceptions++; + } + + $this->assertSame(3, $exceptions); + } + + public function testSet() + { + $array = ['products' => ['desk' => ['price' => 100]]]; + Arr::set($array, 'products.desk.price', 200); + $this->assertEquals(['products' => ['desk' => ['price' => 200]]], $array); + } + + public function testSort() + { + $unsorted = [ + ['name' => 'Desk'], + ['name' => 'Chair'], + ]; + + $expected = [ + ['name' => 'Chair'], + ['name' => 'Desk'], + ]; + + $sorted = array_values(Arr::sort($unsorted)); + $this->assertEquals($expected, $sorted); + + // sort with closure + $sortedWithClosure = array_values(Arr::sort($unsorted, function ($value) { + return $value['name']; + })); + $this->assertEquals($expected, $sortedWithClosure); + + // sort with dot notation + $sortedWithDotNotation = array_values(Arr::sort($unsorted, 'name')); + $this->assertEquals($expected, $sortedWithDotNotation); + } + + public function testSortRecursive() + { + $array = [ + 'users' => [ + [ + // should sort associative arrays by keys + 'name' => 'joe', + 'mail' => 'joe@example.com', + // should sort deeply nested arrays + 'numbers' => [2, 1, 0], + ], + [ + 'name' => 'jane', + 'age' => 25, + ], + ], + 'repositories' => [ + // should use weird `sort()` behavior on arrays of arrays + ['id' => 1], + ['id' => 0], + ], + // should sort non-associative arrays by value + 20 => [2, 1, 0], + 30 => [ + // should sort non-incrementing numerical keys by keys + 2 => 'a', + 1 => 'b', + 0 => 'c', + ], + ]; + + $expect = [ + 20 => [0, 1, 2], + 30 => [ + 0 => 'c', + 1 => 'b', + 2 => 'a', + ], + 'repositories' => [ + ['id' => 0], + ['id' => 1], + ], + 'users' => [ + [ + 'age' => 25, + 'name' => 'jane', + ], + [ + 'mail' => 'joe@example.com', + 'name' => 'joe', + 'numbers' => [0, 1, 2], + ], + ], + ]; + + $this->assertEquals($expect, Arr::sortRecursive($array)); + } + + public function testWhere() + { + $array = [100, '200', 300, '400', 500]; + + $array = Arr::where($array, function ($value, $key) { + return is_string($value); + }); + + $this->assertEquals([1 => 200, 3 => 400], $array); + } + + public function testWhereKey() + { + $array = ['10' => 1, 'foo' => 3, 20 => 2]; + + $array = Arr::where($array, function ($value, $key) { + return is_numeric($key); + }); + + $this->assertEquals(['10' => 1, 20 => 2], $array); + } + + public function testForget() + { + $array = ['products' => ['desk' => ['price' => 100]]]; + Arr::forget($array, null); + $this->assertEquals(['products' => ['desk' => ['price' => 100]]], $array); + + $array = ['products' => ['desk' => ['price' => 100]]]; + Arr::forget($array, []); + $this->assertEquals(['products' => ['desk' => ['price' => 100]]], $array); + + $array = ['products' => ['desk' => ['price' => 100]]]; + Arr::forget($array, 'products.desk'); + $this->assertEquals(['products' => []], $array); + + $array = ['products' => ['desk' => ['price' => 100]]]; + Arr::forget($array, 'products.desk.price'); + $this->assertEquals(['products' => ['desk' => []]], $array); + + $array = ['products' => ['desk' => ['price' => 100]]]; + Arr::forget($array, 'products.final.price'); + $this->assertEquals(['products' => ['desk' => ['price' => 100]]], $array); + + $array = ['shop' => ['cart' => [150 => 0]]]; + Arr::forget($array, 'shop.final.cart'); + $this->assertEquals(['shop' => ['cart' => [150 => 0]]], $array); + + $array = ['products' => ['desk' => ['price' => ['original' => 50, 'taxes' => 60]]]]; + Arr::forget($array, 'products.desk.price.taxes'); + $this->assertEquals(['products' => ['desk' => ['price' => ['original' => 50]]]], $array); + + $array = ['products' => ['desk' => ['price' => ['original' => 50, 'taxes' => 60]]]]; + Arr::forget($array, 'products.desk.final.taxes'); + $this->assertEquals(['products' => ['desk' => ['price' => ['original' => 50, 'taxes' => 60]]]], $array); + + $array = ['products' => ['desk' => ['price' => 50], null => 'something']]; + Arr::forget($array, ['products.amount.all', 'products.desk.price']); + $this->assertEquals(['products' => ['desk' => [], null => 'something']], $array); + + // Only works on first level keys + $array = ['joe@example.com' => 'Joe', 'jane@example.com' => 'Jane']; + Arr::forget($array, 'joe@example.com'); + $this->assertEquals(['jane@example.com' => 'Jane'], $array); + + // Does not work for nested keys + $array = ['emails' => ['joe@example.com' => ['name' => 'Joe'], 'jane@localhost' => ['name' => 'Jane']]]; + Arr::forget($array, ['emails.joe@example.com', 'emails.jane@localhost']); + $this->assertEquals(['emails' => ['joe@example.com' => ['name' => 'Joe']]], $array); + } + + public function testWrap() + { + $string = 'a'; + $array = ['a']; + $object = new stdClass; + $object->value = 'a'; + $this->assertEquals(['a'], Arr::wrap($string)); + $this->assertEquals($array, Arr::wrap($array)); + $this->assertEquals([$object], Arr::wrap($object)); + } +} diff --git a/tests/Support/SupportCarbonTest.php b/tests/Support/SupportCarbonTest.php new file mode 100644 index 0000000..1cc38d9 --- /dev/null +++ b/tests/Support/SupportCarbonTest.php @@ -0,0 +1,96 @@ +now = Carbon::create(2017, 6, 27, 13, 14, 15, 'UTC')); + } + + public function tearDown() + { + Carbon::setTestNow(); + Carbon::serializeUsing(null); + + parent::tearDown(); + } + + public function testInstance() + { + $this->assertInstanceOf(DateTime::class, $this->now); + $this->assertInstanceOf(DateTimeInterface::class, $this->now); + $this->assertInstanceOf(BaseCarbon::class, $this->now); + $this->assertInstanceOf(Carbon::class, $this->now); + } + + public function testCarbonIsMacroableWhenNotCalledStatically() + { + Carbon::macro('diffInDecades', function (Carbon $dt = null, $abs = true) { + return (int) ($this->diffInYears($dt, $abs) / 10); + }); + + $this->assertSame(2, $this->now->diffInDecades(Carbon::now()->addYears(25))); + } + + public function testCarbonIsMacroableWhenCalledStatically() + { + Carbon::macro('twoDaysAgoAtNoon', function () { + return Carbon::now()->subDays(2)->setTime(12, 0, 0); + }); + + $this->assertSame('2017-06-25 12:00:00', Carbon::twoDaysAgoAtNoon()->toDateTimeString()); + } + + /** + * @expectedException \BadMethodCallException + * @expectedExceptionMessage Method nonExistingStaticMacro does not exist. + */ + public function testCarbonRaisesExceptionWhenStaticMacroIsNotFound() + { + Carbon::nonExistingStaticMacro(); + } + + /** + * @expectedException \BadMethodCallException + * @expectedExceptionMessage Method nonExistingMacro does not exist. + */ + public function testCarbonRaisesExceptionWhenMacroIsNotFound() + { + Carbon::now()->nonExistingMacro(); + } + + public function testCarbonAllowsCustomSerializer() + { + Carbon::serializeUsing(function (Carbon $carbon) { + return $carbon->getTimestamp(); + }); + + $result = json_decode(json_encode($this->now), true); + + $this->assertSame(1498569255, $result); + } + + public function testCarbonCanSerializeToJson() + { + $this->assertSame([ + 'date' => '2017-06-27 13:14:15.000000', + 'timezone_type' => 3, + 'timezone' => 'UTC', + ], $this->now->jsonSerialize()); + } +} diff --git a/tests/Support/SupportCollectionTest.php b/tests/Support/SupportCollectionTest.php index c49675d..2f6c949 100644 --- a/tests/Support/SupportCollectionTest.php +++ b/tests/Support/SupportCollectionTest.php @@ -1,6 +1,6 @@ shouldReceive('toArray')->once()->andReturn('foo.array'); - $item2 = m::mock('Illuminate\Contracts\Support\Arrayable'); + $item2 = m::mock('Tightenco\Contracts\Support\Arrayable'); $item2->shouldReceive('toArray')->once()->andReturn('bar.array'); $c = new Collection([$item1, $item2]); $results = $c->toArray(); @@ -187,7 +187,7 @@ public function testJsonSerializeCallsToArrayOrJsonSerializeOnEachItemInCollecti { $item1 = m::mock('JsonSerializable'); $item1->shouldReceive('jsonSerialize')->once()->andReturn('foo.json'); - $item2 = m::mock('Illuminate\Contracts\Support\Arrayable'); + $item2 = m::mock('Tightenco\Contracts\Support\Arrayable'); $item2->shouldReceive('toArray')->once()->andReturn('bar.array'); $c = new Collection([$item1, $item2]); $results = $c->jsonSerialize(); @@ -451,16 +451,16 @@ public function testWhere() $c->where('v', '<', null)->values()->all() ); - $c = new Collection([['v' => 1], ['v' => new \Illuminate\Support\HtmlString('hello')]]); + $c = new Collection([['v' => 1], ['v' => new \Tightenco\Support\HtmlString('hello')]]); $this->assertEquals( - [['v' => new \Illuminate\Support\HtmlString('hello')]], + [['v' => new \Tightenco\Support\HtmlString('hello')]], $c->where('v', 'hello')->values()->all() ); $c = new Collection([['v' => 1], ['v' => 'hello']]); $this->assertEquals( [['v' => 'hello']], - $c->where('v', new \Illuminate\Support\HtmlString('hello'))->values()->all() + $c->where('v', new \Tightenco\Support\HtmlString('hello'))->values()->all() ); } diff --git a/tests/Support/SupportMacroableTest.php b/tests/Support/SupportMacroableTest.php new file mode 100644 index 0000000..787a7a6 --- /dev/null +++ b/tests/Support/SupportMacroableTest.php @@ -0,0 +1,92 @@ +macroable = $this->createObjectForTrait(); + } + + private function createObjectForTrait() + { + return $this->getObjectForTrait(Macroable::class); + } + + public function testRegisterMacro() + { + $macroable = $this->macroable; + $macroable::macro(__CLASS__, function () { + return 'Taylor'; + }); + $this->assertEquals('Taylor', $macroable::{__CLASS__}()); + } + + public function testRegisterMacroAndCallWithoutStatic() + { + $macroable = $this->macroable; + $macroable::macro(__CLASS__, function () { + return 'Taylor'; + }); + $this->assertEquals('Taylor', $macroable->{__CLASS__}()); + } + + public function testWhenCallingMacroClosureIsBoundToObject() + { + TestMacroable::macro('tryInstance', function () { + return $this->protectedVariable; + }); + TestMacroable::macro('tryStatic', function () { + return static::getProtectedStatic(); + }); + $instance = new TestMacroable; + + $result = $instance->tryInstance(); + $this->assertEquals('instance', $result); + + $result = TestMacroable::tryStatic(); + $this->assertEquals('static', $result); + } + + public function testClassBasedMacros() + { + TestMacroable::mixin(new TestMixin); + $instance = new TestMacroable; + $this->assertEquals('instance-Adam', $instance->methodOne('Adam')); + } +} + +class TestMacroable +{ + use Macroable; + + protected $protectedVariable = 'instance'; + + protected static function getProtectedStatic() + { + return 'static'; + } +} + +class TestMixin +{ + public function methodOne() + { + return function ($value) { + return $this->methodTwo($value); + }; + } + + protected function methodTwo() + { + return function ($value) { + return $this->protectedVariable.'-'.$value; + }; + } +} diff --git a/tests/Support/SupportStrTest.php b/tests/Support/SupportStrTest.php new file mode 100644 index 0000000..037f78a --- /dev/null +++ b/tests/Support/SupportStrTest.php @@ -0,0 +1,303 @@ +assertEquals('Taylor...', Str::words('Taylor Otwell', 1)); + $this->assertEquals('Taylor___', Str::words('Taylor Otwell', 1, '___')); + $this->assertEquals('Taylor Otwell', Str::words('Taylor Otwell', 3)); + } + + public function testStringTrimmedOnlyWhereNecessary() + { + $this->assertEquals(' Taylor Otwell ', Str::words(' Taylor Otwell ', 3)); + $this->assertEquals(' Taylor...', Str::words(' Taylor Otwell ', 1)); + } + + public function testStringTitle() + { + $this->assertEquals('Jefferson Costella', Str::title('jefferson costella')); + $this->assertEquals('Jefferson Costella', Str::title('jefFErson coSTella')); + } + + public function testStringWithoutWordsDoesntProduceError() + { + $nbsp = chr(0xC2).chr(0xA0); + $this->assertEquals(' ', Str::words(' ')); + $this->assertEquals($nbsp, Str::words($nbsp)); + } + + public function testStringAscii() + { + $this->assertEquals('@', Str::ascii('@')); + $this->assertEquals('u', Str::ascii('ü')); + } + + public function testStringAsciiWithSpecificLocale() + { + $this->assertSame('h H sht SHT a A y Y', Str::ascii('х Х щ Щ ъ Ъ ь Ь', 'bg')); + $this->assertSame('ae oe ue AE OE UE', Str::ascii('ä ö ü Ä Ö Ü', 'de')); + } + + public function testStartsWith() + { + $this->assertTrue(Str::startsWith('jason', 'jas')); + $this->assertTrue(Str::startsWith('jason', 'jason')); + $this->assertTrue(Str::startsWith('jason', ['jas'])); + $this->assertTrue(Str::startsWith('jason', ['day', 'jas'])); + $this->assertFalse(Str::startsWith('jason', 'day')); + $this->assertFalse(Str::startsWith('jason', ['day'])); + $this->assertFalse(Str::startsWith('jason', '')); + $this->assertFalse(Str::startsWith('7', ' 7')); + $this->assertTrue(Str::startsWith('7a', '7')); + $this->assertTrue(Str::startsWith('7a', 7)); + $this->assertTrue(Str::startsWith('7.12a', 7.12)); + $this->assertFalse(Str::startsWith('7.12a', 7.13)); + $this->assertTrue(Str::startsWith(7.123, '7')); + $this->assertTrue(Str::startsWith(7.123, '7.12')); + $this->assertFalse(Str::startsWith(7.123, '7.13')); + // Test for multibyte string support + $this->assertTrue(Str::startsWith('Jönköping', 'Jö')); + $this->assertTrue(Str::startsWith('Malmö', 'Malmö')); + $this->assertFalse(Str::startsWith('Jönköping', 'Jonko')); + $this->assertFalse(Str::startsWith('Malmö', 'Malmo')); + } + + public function testEndsWith() + { + $this->assertTrue(Str::endsWith('jason', 'on')); + $this->assertTrue(Str::endsWith('jason', 'jason')); + $this->assertTrue(Str::endsWith('jason', ['on'])); + $this->assertTrue(Str::endsWith('jason', ['no', 'on'])); + $this->assertFalse(Str::endsWith('jason', 'no')); + $this->assertFalse(Str::endsWith('jason', ['no'])); + $this->assertFalse(Str::endsWith('jason', '')); + $this->assertFalse(Str::endsWith('7', ' 7')); + $this->assertTrue(Str::endsWith('a7', '7')); + $this->assertTrue(Str::endsWith('a7', 7)); + $this->assertTrue(Str::endsWith('a7.12', 7.12)); + $this->assertFalse(Str::endsWith('a7.12', 7.13)); + $this->assertTrue(Str::endsWith(0.27, '7')); + $this->assertTrue(Str::endsWith(0.27, '0.27')); + $this->assertFalse(Str::endsWith(0.27, '8')); + // Test for multibyte string support + $this->assertTrue(Str::endsWith('Jönköping', 'öping')); + $this->assertTrue(Str::endsWith('Malmö', 'mö')); + $this->assertFalse(Str::endsWith('Jönköping', 'oping')); + $this->assertFalse(Str::endsWith('Malmö', 'mo')); + } + + public function testStrBefore() + { + $this->assertEquals('han', Str::before('hannah', 'nah')); + $this->assertEquals('ha', Str::before('hannah', 'n')); + $this->assertEquals('ééé ', Str::before('ééé hannah', 'han')); + $this->assertEquals('hannah', Str::before('hannah', 'xxxx')); + $this->assertEquals('hannah', Str::before('hannah', '')); + $this->assertEquals('han', Str::before('han0nah', '0')); + $this->assertEquals('han', Str::before('han0nah', 0)); + $this->assertEquals('han', Str::before('han2nah', 2)); + } + + public function testStrAfter() + { + $this->assertEquals('nah', Str::after('hannah', 'han')); + $this->assertEquals('nah', Str::after('hannah', 'n')); + $this->assertEquals('nah', Str::after('ééé hannah', 'han')); + $this->assertEquals('hannah', Str::after('hannah', 'xxxx')); + $this->assertEquals('hannah', Str::after('hannah', '')); + $this->assertEquals('nah', Str::after('han0nah', '0')); + $this->assertEquals('nah', Str::after('han0nah', 0)); + $this->assertEquals('nah', Str::after('han2nah', 2)); + } + + public function testStrContains() + { + $this->assertTrue(Str::contains('taylor', 'ylo')); + $this->assertTrue(Str::contains('taylor', 'taylor')); + $this->assertTrue(Str::contains('taylor', ['ylo'])); + $this->assertTrue(Str::contains('taylor', ['xxx', 'ylo'])); + $this->assertFalse(Str::contains('taylor', 'xxx')); + $this->assertFalse(Str::contains('taylor', ['xxx'])); + $this->assertFalse(Str::contains('taylor', '')); + } + + public function testParseCallback() + { + $this->assertEquals(['Class', 'method'], Str::parseCallback('Class@method', 'foo')); + $this->assertEquals(['Class', 'foo'], Str::parseCallback('Class', 'foo')); + } + + public function testSlug() + { + $this->assertEquals('hello-world', Str::slug('hello world')); + $this->assertEquals('hello-world', Str::slug('hello-world')); + $this->assertEquals('hello-world', Str::slug('hello_world')); + $this->assertEquals('hello_world', Str::slug('hello_world', '_')); + $this->assertEquals('user-at-host', Str::slug('user@host')); + } + + public function testFinish() + { + $this->assertEquals('abbc', Str::finish('ab', 'bc')); + $this->assertEquals('abbc', Str::finish('abbcbc', 'bc')); + $this->assertEquals('abcbbc', Str::finish('abcbbcbc', 'bc')); + } + + public function testIs() + { + $this->assertTrue(Str::is('/', '/')); + $this->assertFalse(Str::is('/', ' /')); + $this->assertFalse(Str::is('/', '/a')); + $this->assertTrue(Str::is('foo/*', 'foo/bar/baz')); + $this->assertTrue(Str::is('*/foo', 'blah/baz/foo')); + + $valueObject = new StringableObjectStub('foo/bar/baz'); + $patternObject = new StringableObjectStub('foo/*'); + + $this->assertTrue(Str::is('foo/bar/baz', $valueObject)); + $this->assertTrue(Str::is($patternObject, $valueObject)); + } + + public function testKebab() + { + $this->assertEquals('laravel-php-framework', Str::kebab('LaravelPhpFramework')); + } + + public function testLower() + { + $this->assertEquals('foo bar baz', Str::lower('FOO BAR BAZ')); + $this->assertEquals('foo bar baz', Str::lower('fOo Bar bAz')); + } + + public function testUpper() + { + $this->assertEquals('FOO BAR BAZ', Str::upper('foo bar baz')); + $this->assertEquals('FOO BAR BAZ', Str::upper('foO bAr BaZ')); + } + + public function testLimit() + { + $this->assertEquals('Laravel is...', Str::limit('Laravel is a free, open source PHP web application framework.', 10)); + $this->assertEquals('这是一...', Str::limit('这是一段中文', 6)); + } + + public function testLength() + { + $this->assertEquals(11, Str::length('foo bar baz')); + } + + public function testRandom() + { + $this->assertEquals(16, strlen(Str::random())); + $randomInteger = random_int(1, 100); + $this->assertEquals($randomInteger, strlen(Str::random($randomInteger))); + $this->assertInternalType('string', Str::random()); + } + + public function testReplaceArray() + { + $this->assertEquals('foo/bar/baz', Str::replaceArray('?', ['foo', 'bar', 'baz'], '?/?/?')); + $this->assertEquals('foo/bar/baz/?', Str::replaceArray('?', ['foo', 'bar', 'baz'], '?/?/?/?')); + $this->assertEquals('foo/bar', Str::replaceArray('?', ['foo', 'bar', 'baz'], '?/?')); + $this->assertEquals('?/?/?', Str::replaceArray('x', ['foo', 'bar', 'baz'], '?/?/?')); + } + + public function testReplaceFirst() + { + $this->assertEquals('fooqux foobar', Str::replaceFirst('bar', 'qux', 'foobar foobar')); + $this->assertEquals('foo/qux? foo/bar?', Str::replaceFirst('bar?', 'qux?', 'foo/bar? foo/bar?')); + $this->assertEquals('foo foobar', Str::replaceFirst('bar', '', 'foobar foobar')); + $this->assertEquals('foobar foobar', Str::replaceFirst('xxx', 'yyy', 'foobar foobar')); + $this->assertEquals('foobar foobar', Str::replaceFirst('', 'yyy', 'foobar foobar')); + // Test for multibyte string support + $this->assertEquals('Jxxxnköping Malmö', Str::replaceFirst('ö', 'xxx', 'Jönköping Malmö')); + $this->assertEquals('Jönköping Malmö', Str::replaceFirst('', 'yyy', 'Jönköping Malmö')); + } + + public function testReplaceLast() + { + $this->assertEquals('foobar fooqux', Str::replaceLast('bar', 'qux', 'foobar foobar')); + $this->assertEquals('foo/bar? foo/qux?', Str::replaceLast('bar?', 'qux?', 'foo/bar? foo/bar?')); + $this->assertEquals('foobar foo', Str::replaceLast('bar', '', 'foobar foobar')); + $this->assertEquals('foobar foobar', Str::replaceLast('xxx', 'yyy', 'foobar foobar')); + $this->assertEquals('foobar foobar', Str::replaceLast('', 'yyy', 'foobar foobar')); + // Test for multibyte string support + $this->assertEquals('Malmö Jönkxxxping', Str::replaceLast('ö', 'xxx', 'Malmö Jönköping')); + $this->assertEquals('Malmö Jönköping', Str::replaceLast('', 'yyy', 'Malmö Jönköping')); + } + + public function testSnake() + { + $this->assertEquals('laravel_p_h_p_framework', Str::snake('LaravelPHPFramework')); + $this->assertEquals('laravel_php_framework', Str::snake('LaravelPhpFramework')); + $this->assertEquals('laravel php framework', Str::snake('LaravelPhpFramework', ' ')); + $this->assertEquals('laravel_php_framework', Str::snake('Laravel Php Framework')); + $this->assertEquals('laravel_php_framework', Str::snake('Laravel Php Framework ')); + // ensure cache keys don't overlap + $this->assertEquals('laravel__php__framework', Str::snake('LaravelPhpFramework', '__')); + $this->assertEquals('laravel_php_framework_', Str::snake('LaravelPhpFramework_', '_')); + $this->assertEquals('laravel_php_framework', Str::snake('laravel php Framework')); + $this->assertEquals('laravel_php_frame_work', Str::snake('laravel php FrameWork')); + } + + public function testStudly() + { + $this->assertEquals('LaravelPHPFramework', Str::studly('laravel_p_h_p_framework')); + $this->assertEquals('LaravelPhpFramework', Str::studly('laravel_php_framework')); + $this->assertEquals('LaravelPhPFramework', Str::studly('laravel-phP-framework')); + $this->assertEquals('LaravelPhpFramework', Str::studly('laravel -_- php -_- framework ')); + } + + public function testCamel() + { + $this->assertEquals('laravelPHPFramework', Str::camel('Laravel_p_h_p_framework')); + $this->assertEquals('laravelPhpFramework', Str::camel('Laravel_php_framework')); + $this->assertEquals('laravelPhPFramework', Str::camel('Laravel-phP-framework')); + $this->assertEquals('laravelPhpFramework', Str::camel('Laravel -_- php -_- framework ')); + } + + public function testSubstr() + { + $this->assertEquals('Ё', Str::substr('БГДЖИЛЁ', -1)); + $this->assertEquals('ЛЁ', Str::substr('БГДЖИЛЁ', -2)); + $this->assertEquals('И', Str::substr('БГДЖИЛЁ', -3, 1)); + $this->assertEquals('ДЖИЛ', Str::substr('БГДЖИЛЁ', 2, -1)); + $this->assertEmpty(Str::substr('БГДЖИЛЁ', 4, -4)); + $this->assertEquals('ИЛ', Str::substr('БГДЖИЛЁ', -3, -1)); + $this->assertEquals('ГДЖИЛЁ', Str::substr('БГДЖИЛЁ', 1)); + $this->assertEquals('ГДЖ', Str::substr('БГДЖИЛЁ', 1, 3)); + $this->assertEquals('БГДЖ', Str::substr('БГДЖИЛЁ', 0, 4)); + $this->assertEquals('Ё', Str::substr('БГДЖИЛЁ', -1, 1)); + $this->assertEmpty(Str::substr('Б', 2)); + } + + public function testUcfirst() + { + $this->assertEquals('Laravel', Str::ucfirst('laravel')); + $this->assertEquals('Laravel framework', Str::ucfirst('laravel framework')); + $this->assertEquals('Мама', Str::ucfirst('мама')); + $this->assertEquals('Мама мыла раму', Str::ucfirst('мама мыла раму')); + } +} + +class StringableObjectStub +{ + private $value; + + public function __construct($value) + { + $this->value = $value; + } + + public function __toString() + { + return $this->value; + } +} diff --git a/upgrade.sh b/upgrade.sh new file mode 100755 index 0000000..4c33373 --- /dev/null +++ b/upgrade.sh @@ -0,0 +1,344 @@ +#!/usr/bin/env bash + +## + # Include dotfiles on file operations + # +shopt -s dotglob + +## + # App + # +function main() +{ + echo "Upgrading..." + + prepareEnvironment + + displayVariables + + cleanDirectories + + downloadRepository + + extractZip + + copyClasses + + copyContracts + + copyTraits + + copyStubs + + downloadTests + + renameNamespace + + fillAliases + + cleanupDir + + runTests +} + +## + # Prepare the environment + # +function prepareEnvironment() +{ + ## + # Define all variables + # + rootDir=. + baseDir=${rootDir}/src + vendor=laravel + project=framework + oldNamespace='Illuminate' + newNamespace='Tightenco' + repository=https://github.com/$vendor/$project.git + + getCurrentVersionFromGitHub + + repositoryDir=${rootDir}/$project-${collectionVersion} + repositorySrcDir=${repositoryDir}/src + collectionZip=${rootDir}/$project-${collectionVersion}.zip + collectionZipUrl=https://github.com/$vendor/$project/archive/v${collectionVersion}.zip + oldNamespaceDir=${repositorySrcDir}/${oldNamespace} + newNamespaceDir=${baseDir}/${newNamespace} + testsDir=${rootDir}/tests + testsBaseUrl=https://raw.githubusercontent.com/${vendor}/${project}/v${collectionVersion}/tests + stubsDir=${rootDir}/stubs + aliasFile=${baseDir}/${newNamespace}/Support/alias.php +carriageReturn=" +" + + classes=( + 'Support/Collection' + 'Support/Arr' + 'Support/Carbon' + 'Support/HigherOrderCollectionProxy' + 'Support/HigherOrderTapProxy' + 'Support/HtmlString' + 'Support/Optional' + 'Support/Str' + 'Support/Debug/Dumper' + 'Support/Debug/HtmlDumper' + ) + + traits=( + 'Support/Traits/Macroable.php' + ) + + contracts=( + 'Contracts/Support/Arrayable.php' + 'Contracts/Support/Jsonable.php' + 'Contracts/Support/Htmlable.php' + ) + + tests=( + 'Support/SupportCollectionTest.php' + 'Support/SupportArrTest.php' + 'Support/SupportMacroableTest.php' + 'Support/SupportStrTest.php' + 'Support/SupportCarbonTest.php' + ) + + stubs=( + 'src/Tightenco/Support/helpers.php' + 'src/Tightenco/Support/alias.php' + 'tests/bootstrap.php' + ) +} + +## + # Display all variables + # +function displayVariables() +{ + echo + echo "-- Variables" + echo "---------------------------------------------" + + echo baseDir = ${baseDir} + echo collectionVersion = ${collectionVersion} + echo repositoryDir = ${repositoryDir} + echo repositorySrcDir = ${repositorySrcDir} + echo collectionZip = ${collectionZip} + echo baseDir = ${baseDir} + echo oldNamespace = ${oldNamespace} + echo newNamespace = ${newNamespace} + echo oldNamespaceDir = ${oldNamespaceDir} + echo newNamespaceDir = ${newNamespaceDir} + echo testsDir = ${testsDir} + echo testsBaseUrl = ${testsBaseUrl} + + echo "---------------------------------------------" +} + +## + # Clean the destination directory + # +function cleanDirectories() +{ + echo "Cleaning ${baseDir} and ${testsDir}/Support..." + + if [ -d ${baseDir} ]; then + rm -rf ${baseDir} + fi + + if [ -d ${testsDir}/Support ]; then + rm -rf ${testsDir} + fi + + if [ -d ${repositoryDir} ]; then + rm -rf ${repositoryDir} + fi +} + +## + # Download a new version + # +function downloadRepository() +{ + echo "-- Downloading ${collectionZipUrl} to ${baseDir}" + + wget ${collectionZipUrl} -O ${collectionZip} >/dev/null 2>&1 +} + +## + # Extract from compressed file + # +function extractZip() +{ + echo "-- Extracting $project.zip..." + + unzip ${collectionZip} -d ${rootDir} >/dev/null 2>&1 + + rm ${collectionZip} +} + +## + # Copy classes + # +function copyClasses() +{ + echo "-- Copying classes and contracts..." + + for class in ${classes[@]}; do + echo "Copying ${oldNamespaceDir}.php/${class}.php..." + + mkdir -p $(dirname ${newNamespaceDir}/${class}) + + cp ${oldNamespaceDir}/${class}.php ${newNamespaceDir}/${class}.php + done +} + +## + # Move contracts + # +function copyContracts() +{ + echo "-- Copying contracts..." + + for contract in ${contracts[@]}; do + echo "Copying ${oldNamespaceDir}.php/${contract}..." + + mkdir -p $(dirname ${newNamespaceDir}/${contract}) + + cp ${oldNamespaceDir}/${contract} ${newNamespaceDir}/${contract} + done +} + +## + # Move traits + # +function copyTraits() +{ + echo "-- Copying traits..." + + for trait in ${traits[@]}; do + echo "Copying ${oldNamespaceDir}.php/${trait}..." + + mkdir -p $(dirname ${newNamespaceDir}/${trait}) + + cp ${oldNamespaceDir}/${trait} ${newNamespaceDir}/${trait} + done +} + +## + # Copy classes and contracts + # +function copyStubs() +{ + echo "-- Copying stubs..." + + for stub in ${stubs[@]}; do + echo "Copying ${stubsDir}/${stub} to ${rootDir}/${stub}..." + + mkdir -p $(dirname ${rootDir}/${stub}) + + cp ${stubsDir}/${stub} ${rootDir}/${stub} + done +} + +## + # Fill the alias.php file with the list of aliases + # +function fillAliases() +{ + echo "-- Filling aliases.php..." + + indent=' ' + aliases='CARRIAGERETURN' + + for class in ${classes[@]}; do + aliases="${aliases}${indent}${oldNamespace}/${class}::class => ${newNamespace}/${class}::class,CARRIAGERETURN" + done + + aliases=${aliases//\//\\\\} + + sed -i "" -e "s|/\*--- ALIASES ---\*/|${aliases}|g" $aliasFile + sed -i "" -e "s|CARRIAGERETURN|\\${carriageReturn}|g" $aliasFile +} + +## + # Copy tests to our tests dir + # +function getCurrentVersionFromGitHub() +{ + echo Getting current version from $repository... + + collectionVersion=$(git ls-remote $repository | grep tags/ | grep -v {} | cut -d \/ -f 3 | cut -d v -f 2 | sort --version-sort | tail -1) + + echo Upgrading to $vendor/$project $collectionVersion +} + +## + # Download tests to tests dir + # +function downloadTests() +{ + echo "-- Copying tests..." + + tests=( + 'Support/SupportCollectionTest.php' + 'Support/SupportArrTest.php' + 'Support/SupportMacroableTest.php' + 'Support/SupportStrTest.php' + 'Support/SupportCarbonTest.php' + ) + + for test in ${tests[@]}; do + echo "---- Downloading test ${testsBaseUrl}/${test} to ${testsDir}/${test}..." + + mkdir -p $(dirname ${testsDir}/${test}) + + wget ${testsBaseUrl}/${test} -O ${testsDir}/${test} >/dev/null 2>&1 + done +} + +## + # Rename namespace on all files + # +function renameNamespace() +{ + echo "-- Renaming namespace from $oldNamespace to $newNamespace..." + + find ${newNamespaceDir} -name "*.php" -exec sed -i "" -e "s|${oldNamespace}|${newNamespace}|g" {} \; + find ${testsDir} -name "*.php" -exec sed -i "" -e "s|${oldNamespace}|${newNamespace}|g" {} \; +} + +## + # Clenup dir + # +function cleanupDir() +{ + echo "-- Cleaning up ${repositoryDir}..." + + rm -rf ${repositoryDir} +} + +## + # Run tests + # +function runTests() +{ + echo "-- Running tests..." + + if [ -f ${rootDir}/composer.lock ]; then + rm ${rootDir}/composer.lock + fi + + if [ -d ${rootDir}/vendor ]; then + rm -rf ${rootDir}/vendor + fi + + composer install + + vendor/bin/phpunit +} + +## + # Run the app + # +main $@