From 4418adfd7f94beca8d3da905305c69c4c0f84d7f Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Thu, 17 Mar 2022 11:39:25 +0100 Subject: [PATCH 01/11] Update bug report template --- .github/ISSUE_TEMPLATE/BUG_REPORT.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.md b/.github/ISSUE_TEMPLATE/BUG_REPORT.md index e5a47f1..48f1395 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.md +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.md @@ -12,14 +12,8 @@ assignees: sebastiaanluca ### Steps to reproduce -1. -2. -3. +Please provide a fully working repository that reproduces the bug. -### Traces +### Additional info -Logs, error output, etc. - -### Environment information - -Setup, environment, packages, versions, etc. +Logs, error output, setup, environment, packages, versions, etc. From 857190c55e2444713beeac9c28b03c6f1f06482b Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Thu, 17 Mar 2022 11:40:49 +0100 Subject: [PATCH 02/11] Update GH Action --- .github/workflows/test.yml | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e65c357..92e2c39 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,32 +1,38 @@ -name: test +name: Check code on: push: pull_request: - schedule: - - cron: '0 12 15 * *' jobs: - test: + + check: + name: Run checks - PHP ${{ matrix.php }} - ${{ matrix.dependency-version }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - php: [8.0] + php: [8.0, 8.1] dependency-version: [prefer-lowest, prefer-stable] os: [ubuntu-latest] - name: PHP ${{ matrix.php }} - ${{ matrix.dependency-version }} - ${{ matrix.os }} - steps: - name: Check out code uses: actions/checkout@v2 - - name: Cache dependencies + - name: Cache PHP dependencies + uses: actions/cache@v2 + with: + path: '**/vendor' + key: ${{ runner.os }}-vendor-cache-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-vendor-cache- + + - name: Cache Composer dependencies uses: actions/cache@v2 with: path: ~/.composer/cache/files - key: dependencies-${{ runner.os }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} + key: composer-${{ runner.os }}-php-${{ matrix.php }}-${{ hashFiles('composer.json') }} - name: Validate Composer configuration file run: composer validate --strict @@ -39,8 +45,10 @@ jobs: coverage: none - name: Install dependencies - run: | - composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction + run: composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction --no-progress --optimize-autoloader + + - name: Lint code + run: vendor/bin/php-cs-fixer fix --dry-run --diff - - name: Execute tests + - name: Run tests run: vendor/bin/phpunit From 39deee9b392cedfb2046dbb1bb182d23861c09b1 Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Thu, 17 Mar 2022 11:41:26 +0100 Subject: [PATCH 03/11] Move tests --- tests/{Unit => }/IdentifierTest.php | 0 tests/{Unit => }/MethodsTest.php | 0 tests/{Unit => }/ObjectTest.php | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename tests/{Unit => }/IdentifierTest.php (100%) rename tests/{Unit => }/MethodsTest.php (100%) rename tests/{Unit => }/ObjectTest.php (100%) diff --git a/tests/Unit/IdentifierTest.php b/tests/IdentifierTest.php similarity index 100% rename from tests/Unit/IdentifierTest.php rename to tests/IdentifierTest.php diff --git a/tests/Unit/MethodsTest.php b/tests/MethodsTest.php similarity index 100% rename from tests/Unit/MethodsTest.php rename to tests/MethodsTest.php diff --git a/tests/Unit/ObjectTest.php b/tests/ObjectTest.php similarity index 100% rename from tests/Unit/ObjectTest.php rename to tests/ObjectTest.php From a7913622ef00215a880154dd36454f64e30be65e Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Thu, 17 Mar 2022 12:18:12 +0100 Subject: [PATCH 04/11] Support first class callable syntax --- tests/MethodsTest.php | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/MethodsTest.php b/tests/MethodsTest.php index 98fb6c1..7f2ebca 100644 --- a/tests/MethodsTest.php +++ b/tests/MethodsTest.php @@ -49,6 +49,20 @@ public function it can transform a value using a callable string method ); } + /** + * @test + * @requires PHP >= 8.1 + */ + public function it can transform a value using a first call callable string method using the method directly(): void + { + $this->assertSame( + 'stringggg', + take('STRINGGgg') + ->pipe(strtolower(...)) + ->get() + ); + } + /** * @test */ @@ -90,6 +104,20 @@ public function it can transform a value using a public class method(): ); } + /** + * @test + * @requires PHP >= 8.1 + */ + public function it can transform a value using a first class callable class method(): void + { + $this->assertSame( + 'UPPERCASE', + take('uppercase') + ->pipe($this->uppercase(...)) + ->get() + ); + } + /** * @test */ From 21c0b441ae12d21032917a8f5b64cbf6b8f58553 Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Thu, 17 Mar 2022 12:19:52 +0100 Subject: [PATCH 05/11] Update tests --- CHANGELOG.md | 11 +++++++++++ README.md | 4 ++-- composer.json | 9 +++++---- phpunit.xml.dist | 45 +++++++++++++++++++++------------------------ 4 files changed, 39 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a122c7c..8e4dd69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,17 @@ All notable changes to `sebastiaanluca/php-pipe-operator` will be documented in Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) principles. +## 5.0.0 (2022-03-17) + +### Added + +- Added support for PHP 8.1 +- Added support for first class callable syntax (PHP 8.1) + +### Changed + +- Cleaned up internals + ## 4.0.0 (2021-06-22) ### Added diff --git a/README.md b/README.md index c6307d7..9050fb9 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [![Follow @sebastiaanluca on Twitter][twitter-profile-badge]][link-twitter] [![Share this package on Twitter][twitter-share-badge]][link-twitter-share] -**A (hopefully) temporary solution to implement the pipe operator in PHP.** +Method chaining (or fluent expressions) **for any value using any method.** ## Table of contents @@ -36,7 +36,7 @@ ## Requirements -- PHP 8 or higher +- PHP 8 or 8.1 ## How to install diff --git a/composer.json b/composer.json index 48e6741..7001711 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "sebastiaanluca/php-pipe-operator", "type": "library", - "description": "A (hopefully) temporary solution to implement the pipe operator in PHP.", + "description": "Method chaining (or fluent expressions) for any value using any method.", "keywords": [ "php", "pipe", @@ -14,15 +14,16 @@ { "name": "Sebastiaan Luca", "email": "hello@sebastiaanluca.com", - "homepage": "https://www.sebastiaanluca.com", + "homepage": "https://sebastiaanluca.com", "role": "Author" } ], "require": { - "php": "^8" + "php": "~8.0|~8.1" }, "require-dev": { - "phpunit/phpunit": "^9.5" + "phpunit/phpunit": "^9.5", + "ext-mbstring": "*" }, "autoload": { "psr-4": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 8921335..a753534 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,29 +1,26 @@ - + + + + src/ + + - - ./tests/Unit + + tests - - - src/ - - From 1a10168751e226da0fbb4c5b098e3a539cf16b70 Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Thu, 17 Mar 2022 12:43:00 +0100 Subject: [PATCH 06/11] Add support for first class callable syntax --- README.md | 56 ++++++++++++++++++++++++++++++++++++++++++- tests/MethodsTest.php | 19 ++++++++++++++- 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9050fb9..1885379 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Method chaining (or fluent expressions) **for any value using any method.** - [How to install](#how-to-install) - [How to use](#how-to-use) - [The basics](#the-basics) + - [Using first class callable syntax](#using-first-class-callable-syntax-enabling-ide-autocompletion) - [Using closures](#using-closures) - [Using class methods](#using-class-methods) - [What does it solve?](#what-does-it-solve) @@ -60,7 +61,7 @@ Pipe::from('hello')->strtoupper()->get(); // "HELLO" ``` -A few alternatives to write the same: +A few alternatives to create the same instance: ```php take('hello')->strtoupper()->get(); @@ -107,6 +108,33 @@ Pipe::from(['key' => 'value']) // "key" ``` +### Using first class callable syntax (enabling IDE autocompletion) + +Since PHP 8.1, you can use a first class callable syntax, or simply put an anonymous function, to pipe the value through. This enables **full method autocompletion**. + +```php +take('STRING') + ->pipe(strtolower(...)) + ->get() + +// "string" +``` + +Or using parameters: + +```php +Pipe::from('https://sebastiaanluca.com/blog') + ->pipe(parse_url(...)) + ->end() + ->pipe(substr(...), PIPED_VALUE, 3) + ->pipe(strtoupper(...)) + ->get(), + +// "OG" +``` + + + ### Using closures Sometimes standard methods don't cut it and you need to perform a custom operation on a value in the process. You can do so using a closure: @@ -151,6 +179,32 @@ class MyClass If you don't want to use the internal pipe proxy and pass `$this`, there are two other ways you can use class methods. +Using first class callable syntax: + +```php +class MyClass +{ + public function __construct() + { + Pipe::from('HELLO') + ->pipe($this->lowercase(...)) + ->get(); + + // "hello" + } + + /** + * @param string $value + * + * @return string + */ + public function lowercase(string $value) : string + { + return mb_strtolower($value); + } +} +``` + Using an array (for public methods only): ```php diff --git a/tests/MethodsTest.php b/tests/MethodsTest.php index 7f2ebca..d55f795 100644 --- a/tests/MethodsTest.php +++ b/tests/MethodsTest.php @@ -53,7 +53,7 @@ public function it can transform a value using a callable string method * @test * @requires PHP >= 8.1 */ - public function it can transform a value using a first call callable string method using the method directly(): void + public function it can transform a value using a first class callable method(): void { $this->assertSame( 'stringggg', @@ -63,6 +63,23 @@ public function it can transform a value using a first call callable s ); } + /** + * @test + * @requires PHP >= 8.1 + */ + public function it can transform a value using a first class callable method with parameters(): void + { + $this->assertSame( + 'OG', + Pipe::from('https://sebastiaanluca.com/blog') + ->pipe(parse_url(...)) + ->end() + ->pipe(substr(...), PIPED_VALUE, 3) + ->pipe(strtoupper(...)) + ->get(), + ); + } + /** * @test */ From 252a961f512da762d1fa9d6f8a6a2778a8b1cde7 Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Thu, 17 Mar 2022 12:43:50 +0100 Subject: [PATCH 07/11] Update gitignore --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 38b0505..28188ad 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ +.idea +.php-cs-fixer.cache .phpunit.result.cache -/.idea composer.lock composer.phar phpunit.xml -tests/temp/ vendor/ From a2dc40dc830a2f7c03d8bf85729448429aab9855 Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Thu, 17 Mar 2022 12:44:08 +0100 Subject: [PATCH 08/11] Update gitattributes --- .gitattributes | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitattributes b/.gitattributes index 4e192c9..cdac80f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,9 +2,10 @@ /.editorconfig export-ignore /.gitattributes export-ignore -/.github export-ignore +/.github export-ignore /.gitignore export-ignore -/CODE_OF_CONDUCT.md export-ignore -/CONTRIBUTING.md export-ignore +/.php_cs.dist.php export-ignore +/CODE_OF_CONDUCT.md export-ignore +/CONTRIBUTING.md export-ignore /phpunit.xml.dist export-ignore /tests export-ignore From da2b8d1bc4960229c474b0e67045aa4422524f04 Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Thu, 17 Mar 2022 12:44:17 +0100 Subject: [PATCH 09/11] Update editorconfig --- .editorconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 9d4b1ef..7d38cf2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,5 +11,8 @@ end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true -[*.yml] +[*.md] +trim_trailing_whitespace = false + +[*.{yml,yaml}] indent_size = 2 From 4616f44f7047d03836f15e4bb0b54769337ce9ef Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Thu, 17 Mar 2022 12:45:35 +0100 Subject: [PATCH 10/11] Add PHP CS Fixer and update composer.json --- .php-cs-fixer.dist.php | 242 +++++++++++++++++++++++++++++++++++++++++ composer.json | 24 +++- 2 files changed, 260 insertions(+), 6 deletions(-) create mode 100644 .php-cs-fixer.dist.php diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000..8db5cb0 --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,242 @@ + true, + '@PSR2' => true, + '@PhpCsFixer' => true, + '@Symfony' => true, + '@PHP70Migration' => true, + '@PHP70Migration:risky' => true, + '@PHP71Migration' => true, + '@PHP71Migration:risky' => true, + '@PHP73Migration' => true, + '@PHPUnit75Migration:risky' => true, + 'final_class' => false, + 'new_with_braces' => false, + 'strict_comparison' => true, + 'list_syntax' => ['syntax' => 'short'], + 'mb_str_functions' => true, + 'class_attributes_separation' => [ + 'elements' => [ + 'method' => 'one', + ], + ], + 'no_extra_blank_lines' => [ + 'tokens' => [ + 'break', + 'continue', + 'curly_brace_block', + 'extra', + 'parenthesis_brace_block', + 'return', + 'square_brace_block', + 'throw', + 'use', + 'use_trait', + 'switch', + + 'case', + 'default', + ], + ], + 'no_blank_lines_before_namespace' => false, + 'nullable_type_declaration_for_default_null_value' => true, + 'increment_style' => ['style' => 'pre'], + 'self_static_accessor' => true, + 'static_lambda' => false, + 'no_empty_phpdoc' => true, + 'no_superfluous_phpdoc_tags' => [ + 'remove_inheritdoc' => true, + ], + 'phpdoc_line_span' => [ + 'const' => 'multi', + 'method' => 'multi', + 'property' => 'multi', + ], + 'general_phpdoc_tag_rename' => true, + 'phpdoc_add_missing_param_annotation' => ['only_untyped' => true], + 'phpdoc_align' => ['align' => 'left'], + 'phpdoc_indent' => true, + 'phpdoc_inline_tag_normalizer' => true, + 'phpdoc_no_access' => true, + 'phpdoc_no_empty_return' => false, + 'phpdoc_no_package' => true, + 'phpdoc_no_useless_inheritdoc' => true, + 'phpdoc_order' => true, + 'phpdoc_order_by_value' => false, + 'phpdoc_scalar' => true, + 'phpdoc_single_line_var_spacing' => true, + 'phpdoc_summary' => true, + 'phpdoc_tag_casing' => ['tags' => ['inheritDoc']], + 'phpdoc_tag_type' => true, + 'phpdoc_to_comment' => true, + 'phpdoc_trim' => true, + 'phpdoc_types' => ['groups' => ['simple', 'alias']], + 'phpdoc_types_order' => ['null_adjustment' => 'always_last'], + 'phpdoc_var_annotation_correct_order' => true, + 'phpdoc_var_without_name' => true, + 'align_multiline_comment' => ['comment_type' => 'phpdocs_like'], + 'php_unit_test_class_requires_covers' => false, + 'php_unit_internal_class' => false, + 'yoda_style' => false, + 'ordered_class_elements' => [ + 'order' => [ + 'use_trait', + 'constant_public', + 'constant_protected', + 'constant_private', + + 'property_static', + 'property_public_static', + 'property_protected_static', + 'property_private_static', + + 'property', + 'property_public', + 'property_protected', + 'property_private', + + 'construct', + 'destruct', + 'magic', + + 'method_static', + 'method_public_abstract_static', + 'method_public_static', + 'method_protected_abstract_static', + 'method_protected_static', + 'method_private_static', + 'method_public_abstract', + 'method_public', + 'method_protected_abstract', + 'method_protected', + 'method_private', + ], + ], + 'array_syntax' => ['syntax' => 'short'], + 'blank_line_after_namespace' => true, + 'blank_line_after_opening_tag' => true, + 'braces' => true, + 'cast_spaces' => true, + 'concat_space' => [ + 'spacing' => 'none', + ], + 'declare_equal_normalize' => true, + 'elseif' => true, + 'encoding' => true, + 'full_opening_tag' => true, + 'fully_qualified_strict_types' => true, // added by Shift + 'function_declaration' => true, + 'function_typehint_space' => true, + 'heredoc_to_nowdoc' => true, + 'include' => true, + 'indentation_type' => true, + 'linebreak_after_opening_tag' => true, + 'line_ending' => true, + 'lowercase_cast' => true, + 'lowercase_keywords' => true, + 'lowercase_static_reference' => true, // added from Symfony + 'magic_method_casing' => true, // added from Symfony + 'magic_constant_casing' => true, + 'method_argument_space' => true, + 'native_function_casing' => true, + 'no_alias_functions' => false, + 'no_blank_lines_after_class_opening' => true, + 'no_blank_lines_after_phpdoc' => true, + 'no_closing_tag' => true, + 'no_empty_statement' => true, + 'no_leading_import_slash' => true, + 'no_leading_namespace_whitespace' => true, + 'no_mixed_echo_print' => [ + 'use' => 'echo', + ], + 'no_multiline_whitespace_around_double_arrow' => true, + 'multiline_whitespace_before_semicolons' => [ + 'strategy' => 'no_multi_line', + ], + 'no_short_bool_cast' => true, + 'no_singleline_whitespace_before_semicolons' => true, + 'no_spaces_after_function_name' => true, + 'no_spaces_inside_parenthesis' => true, + 'no_trailing_comma_in_list_call' => false, + 'no_trailing_comma_in_singleline_array' => true, + 'no_trailing_whitespace' => true, + 'no_trailing_whitespace_in_comment' => true, + 'no_unreachable_default_argument_value' => true, + 'no_useless_return' => true, + 'no_whitespace_before_comma_in_array' => true, + 'no_whitespace_in_blank_line' => true, + 'normalize_index_brace' => true, + 'not_operator_with_successor_space' => true, + 'object_operator_without_whitespace' => true, + 'self_accessor' => false, + 'short_scalar_cast' => true, + 'simplified_null_return' => false, // disabled by Shift + 'single_blank_line_at_eof' => true, + 'single_blank_line_before_namespace' => true, + 'single_import_per_statement' => true, + 'single_line_after_imports' => true, + 'single_line_comment_style' => [ + 'comment_types' => ['hash'], + ], + 'single_quote' => true, + 'space_after_semicolon' => true, + 'standardize_not_equals' => true, + 'switch_case_semicolon_to_colon' => true, + 'switch_case_space' => true, + 'ternary_operator_spaces' => true, + 'trim_array_spaces' => true, + 'unary_operator_spaces' => true, + 'whitespace_after_comma_in_array' => true, + 'constant_case' => ['case' => 'lower'], + 'psr_autoloading' => true, + 'trailing_comma_in_multiline' => ['elements' => ['arrays']], + 'binary_operator_spaces' => [ + 'default' => 'single_space', + ], + 'types_spaces' => [ + 'space' => 'none', + ], + 'blank_line_before_statement' => [ + 'statements' => ['return'], + ], + 'class_definition' => [ + 'multi_line_extends_each_single_line' => true, + 'single_item_single_line' => true, + 'single_line' => true, + ], + 'ordered_imports' => [ + 'sort_algorithm' => 'alpha', + ], + 'no_unneeded_control_parentheses' => [ + 'statements' => ['break', 'clone', 'continue', 'echo_print', 'return', 'switch_case', 'yield'], + ], + 'no_spaces_around_offset' => [ + 'positions' => ['inside', 'outside'], + ], + 'visibility_required' => [ + 'elements' => ['property', 'method', 'const'], + ], +]; + +$finder = Finder::create() + ->in([ + __DIR__.'/src', + __DIR__.'/tests', + ]) + ->name('*.php') + ->notName('*.blade.php') + ->ignoreDotFiles(true) + ->ignoreVCS(true); + +return (new Config) + ->setRules($rules) + ->setFinder($finder) + ->setRiskyAllowed(true) + ->setUsingCache(true); diff --git a/composer.json b/composer.json index 7001711..d80e079 100644 --- a/composer.json +++ b/composer.json @@ -22,8 +22,9 @@ "php": "~8.0|~8.1" }, "require-dev": { - "phpunit/phpunit": "^9.5", - "ext-mbstring": "*" + "ext-mbstring": "*", + "friendsofphp/php-cs-fixer": "^3.7", + "phpunit/phpunit": "^9.5" }, "autoload": { "psr-4": { @@ -41,15 +42,26 @@ "config": { "sort-packages": true }, + "minimum-stability": "dev", + "prefer-stable": true, "scripts": { + "composer:validate": "@composer validate --strict --ansi", "test": "vendor/bin/phpunit", - "test-lowest": [ - "composer update --prefer-lowest --prefer-dist --no-interaction --ansi", + "lint": "vendor/bin/php-cs-fixer fix --dry-run --diff --ansi", + "fix": "vendor/bin/php-cs-fixer fix --ansi", + "check": [ + "@composer:validate", + "@lint", "@test" ], - "test-stable": [ + "check:lowest": [ + "composer update --prefer-lowest --prefer-dist --no-interaction --ansi", + "@check" + ], + "check:stable": [ "composer update --prefer-stable --prefer-dist --no-interaction --ansi", - "@test" + "@check" ] } } + From 5321d448fecf1546944dd62d8df845937efc9979 Mon Sep 17 00:00:00 2001 From: Sebastiaan Luca Date: Thu, 17 Mar 2022 12:45:59 +0100 Subject: [PATCH 11/11] Format code --- src/Pipe.php | 10 ++++++---- src/PipeProxy.php | 2 ++ src/functions.php | 2 ++ tests/IdentifierTest.php | 2 ++ tests/MethodsTest.php | 2 ++ tests/ObjectTest.php | 2 ++ 6 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Pipe.php b/src/Pipe.php index 29cb73e..5c7a7c7 100644 --- a/src/Pipe.php +++ b/src/Pipe.php @@ -1,5 +1,7 @@ pipe($name, ...$arguments); } - public function __call(string $name, array $arguments): mixed + public static function from($value): self { - return $this->pipe($name, ...$arguments); + return new self($value); } public function pipe(callable|object|string $callback, mixed ...$arguments): self|PipeProxy diff --git a/src/PipeProxy.php b/src/PipeProxy.php index 3ef2f45..033ce8c 100644 --- a/src/PipeProxy.php +++ b/src/PipeProxy.php @@ -1,5 +1,7 @@