diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 07bbdee..0230b29 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -6,27 +6,27 @@ permissions: contents: read jobs: - run: + run: runs-on: ubuntu-latest strategy: matrix: - php-versions: ['8.1', '8.2', '8.3'] + php-versions: [ '8.1', '8.2', '8.3' ] name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }} steps: - - uses: actions/checkout@v4 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - tools: phpunit-bridge - extensions: mbstring, xml, ctype, iconv, intl - coverage: xdebug - - - name: Get composer cache directory + - uses: actions/checkout@v4 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: phpunit-bridge + extensions: mbstring, xml, ctype, iconv, intl + coverage: xdebug + + - name: Get composer cache directory id: composer-cache run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Cache composer dependencies + + - name: Cache composer dependencies uses: actions/cache@v3 with: path: ${{ steps.composer-cache.outputs.dir }} @@ -35,11 +35,11 @@ jobs: key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: ${{ runner.os }}-composer- - - name: Install Composer dependencies + - name: Install Composer dependencies run: composer install --no-progress --prefer-dist --optimize-autoloader - # Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit" - # Docs: https://getcomposer.org/doc/articles/scripts.md + # Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit" + # Docs: https://getcomposer.org/doc/articles/scripts.md - - name: Run test suite - run: composer run-script test + - name: Run test suite + run: composer run-script test diff --git a/README.md b/README.md index 31d5977..f0a5dba 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ PHP defer function schedules a function call (the deferred function) to be run i executing the defer returns. It's an unusual but effective way to deal with situations such as resources that must be released regardless of which path a function takes to return. The canonical examples are unlocking a mutex or closing a file. + ```php // Contents returns the file's contents as a string. function contents($filename) { @@ -15,7 +16,7 @@ function contents($filename) { if ($f === false) { throw new Exception("Error opening the file"); } - defer(fclose(...),$f); // fclose will run when we're finished. + $defer = defer(fclose(...),$f); // fclose will run when we're finished. $result = ""; @@ -33,7 +34,9 @@ function contents($filename) { } ``` -Deferring a call to a function such as Close has two advantages. First, it guarantees that you will never forget to close the file, a mistake that's easy to make if you later edit the function to add a new return path. Second, it means that the close sits near the open, which is much clearer than placing it at the end of the function. +Deferring a call to a function such as Close has two advantages. First, it guarantees that you will never forget to +close the file, a mistake that's easy to make if you later edit the function to add a new return path. Second, it means +that the close sits near the open, which is much clearer than placing it at the end of the function. --- @@ -47,14 +50,14 @@ composer require tito10074/defer ```php function foo($a){ - echo "in defer {$a}".PHP_EOL; + echo "in defer {$a}".PHP_EOL; } function a() { - echo "before defer".PHP_EOL; - $defer = defer(foo(...),1); - $defer(foo(...),2); - $defer(foo(...),3); - echo "after defer".PHP_EOL; + echo "before defer".PHP_EOL; + $defer = defer(foo(...),1); + $defer(foo(...),2); + $defer(foo(...),3); + echo "after defer".PHP_EOL; }; echo "start".PHP_EOL; @@ -86,9 +89,9 @@ The deferred call will print `0` after the function returns. ```php function a(){ - $i=0; - defer(printf(...),$i); - $i++; + $i=0; + $_ = defer(printf(...),$i); + $i++; } ``` @@ -102,9 +105,9 @@ This function prints `3210`: ```php function b(){ $defer = defer(); - for($i=0;$i<4;$i++){ - $defer(printf(...),$i); - } + for($i=0;$i<4;$i++){ + $defer(printf(...),$i); + } } ``` @@ -116,16 +119,16 @@ function returns but not modify returned `$i`. This example print `2-3`: ```php function c() { - $i=1; - $o=new \stdClass(); - $o->i=2; - defer(function () use (&$i, $o) { - $o->i++; - $i++; - }); - - $i++; - return [$i,$o]; + $i=1; + $o=new \stdClass(); + $o->i=2; + $defer = defer(function () use (&$i, $o) { + $o->i++; + $i++; + }); + + $i++; + return [$i,$o]; } list($i,$o) = c(); echo "{$i}-{$o->i}".PHP_EOL; @@ -149,23 +152,23 @@ require_once __DIR__.'/../vendor/autoload.php'; function myFunc(){} class Foo{ - public function myMethod(){} + public function myMethod(){} } function a(){ - // defer custom function without parameter - // function name must be with his namespace - $defer = defer('test\myFunc'); - // defer function with one parameter - $defer(printf(...),"test"); - // defer function with more parameters - $defer('printf',"%s-%s",10,12); - // defer with anonymous function - $defer(function (){}); - $func = function (){}; - $defer($func); - //defer method - $foo = new Foo(); - $defer([$foo,'myMethod']); + // defer custom function without parameter + // function name must be with his namespace + $defer = defer('test\myFunc'); + // defer function with one parameter + $defer(printf(...),"test"); + // defer function with more parameters + $defer('printf',"%s-%s",10,12); + // defer with anonymous function + $defer(function (){}); + $func = function (){}; + $defer($func); + //defer method + $foo = new Foo(); + $defer([$foo,'myMethod']); } a(); ``` \ No newline at end of file diff --git a/composer.json b/composer.json index 9aaee1f..2545e75 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,8 @@ "license": "Apache-2.0", "description": "A defer function defers the execution of a function until the surrounding function returns.", "keywords": [ - "php","defer" + "php", + "defer" ], "require": { "php": ">=8.1" @@ -19,7 +20,9 @@ "psr-4": { "Defer\\": "src/" }, - "files": ["shortcuts.php"] + "files": [ + "shortcuts.php" + ] }, "autoload-dev": { "psr-4": { diff --git a/examples/example1.php b/examples/example1.php index bae2b86..d34576a 100644 --- a/examples/example1.php +++ b/examples/example1.php @@ -6,8 +6,8 @@ * Time: 10:15 */ -require_once __DIR__.'/../Defer.php'; -require_once __DIR__.'/../shortcuts.php'; +require_once __DIR__ . '/../Defer.php'; +require_once __DIR__ . '/../shortcuts.php'; /** * @param $dstName @@ -15,48 +15,51 @@ * * @return bool */ -function copyFileBad($srcName, $dstName){ - $src = fopen($srcName, 'r'); - if ($src===false){ - return false; - } - $dst = fopen($dstName, 'w'); - if ($dst===false){ - return false; - } - $size=filesize($srcName); - while($size>0){ - $s = $size>1000?1000:$size; - fwrite($dst,fread($src,$s)); - $size-=1000; - } +function copyFileBad($srcName, $dstName) +{ + $src = fopen($srcName, 'r'); + if ($src === false) { + return false; + } + $dst = fopen($dstName, 'w'); + if ($dst === false) { + return false; + } + $size = filesize($srcName); + while ($size > 0) { + $s = $size > 1000 ? 1000 : $size; + fwrite($dst, fread($src, $s)); + $size -= 1000; + } - fclose($src); - fclose($dst); - return true; + fclose($src); + fclose($dst); + return true; } -function copyFile($srcName, $dstName){ - $src = fopen($srcName, 'r'); - if ($src===false){ - return false; - } - $defer = defer(fclose(...),$src); - $dst = fopen($dstName, 'w'); - if ($dst===false){ - return false; - } - $defer(fclose(...),$dst); +function copyFile($srcName, $dstName) +{ + $src = fopen($srcName, 'r'); + if ($src === false) { + return false; + } + $defer = defer(fclose(...), $src); - $size=filesize($srcName); - while($size>0){ - $s = $size>1000?1000:$size; - $b=fwrite($dst,fread($src,$s)); - if ($s!=$b){ - return false; - } - $size-=1000; - } + $dst = fopen($dstName, 'w'); + if ($dst === false) { + return false; + } + $defer(fclose(...), $dst); - return true; + $size = filesize($srcName); + while ($size > 0) { + $s = $size > 1000 ? 1000 : $size; + $b = fwrite($dst, fread($src, $s)); + if ($s != $b) { + return false; + } + $size -= 1000; + } + + return true; } diff --git a/examples/test.php b/examples/test.php index fa2343f..a4ad53d 100644 --- a/examples/test.php +++ b/examples/test.php @@ -6,19 +6,24 @@ * Time: 10:35 */ -require_once __DIR__.'/../Defer.php'; -require_once __DIR__.'/../shortcuts.php'; +require_once __DIR__ . '/../Defer.php'; +require_once __DIR__ . '/../shortcuts.php'; -echo "start".PHP_EOL; -function foo($a){ - echo "in defer 3-{$a}".PHP_EOL; +echo "start" . PHP_EOL; +function foo($a) +{ + echo "in defer 3-{$a}" . PHP_EOL; } -function a() { - echo "before defer".PHP_EOL; - $defer = defer( "foo",1); - $defer( "foo",2); - $defer("foo",3); - echo "after defer".PHP_EOL; -}; + +function a() +{ + echo "before defer" . PHP_EOL; + $defer = defer("foo", 1); + $defer("foo", 2); + $defer("foo", 3); + echo "after defer" . PHP_EOL; +} + +; a(); -echo "end".PHP_EOL; \ No newline at end of file +echo "end" . PHP_EOL; \ No newline at end of file diff --git a/examples/test2.php b/examples/test2.php index e3569c9..54a3aaf 100644 --- a/examples/test2.php +++ b/examples/test2.php @@ -1,5 +1,7 @@ i=2; +b(); +echo PHP_EOL; + +function c() +{ + $i = 1; + $o = new \stdClass(); + $o->i = 2; defer(function () use (&$i, $o) { - $o->i++; - $i++; - }); + $o->i++; + $i++; + }); - $i++; - return [$i,$o]; + $i++; + return [$i, $o]; } -list($i,$o) = c(); -echo "{$i}-{$o->i}".PHP_EOL; \ No newline at end of file + +list($i, $o) = c(); +echo "{$i}-{$o->i}" . PHP_EOL; \ No newline at end of file diff --git a/shortcuts.php b/shortcuts.php index 73b6211..1e54842 100644 --- a/shortcuts.php +++ b/shortcuts.php @@ -1,4 +1,5 @@ callbacks[] = [$callback, $args];; @@ -32,10 +33,10 @@ function __destruct() $this->flush(); } - public function flush():void + public function flush(): void { - while([$callback,$args] = array_pop($this->callbacks)){ - call_user_func_array($callback,$args); + while ([$callback, $args] = array_pop($this->callbacks)) { + call_user_func_array($callback, $args); } } } \ No newline at end of file diff --git a/tests/AnonymousFunctionTest.php b/tests/AnonymousFunctionTest.php index 09a618a..15869a0 100644 --- a/tests/AnonymousFunctionTest.php +++ b/tests/AnonymousFunctionTest.php @@ -5,6 +5,7 @@ * Date: 27. 8. 2024 * Time: 14:38 */ + namespace Defer\Tests; use Defer\Defer; @@ -13,17 +14,17 @@ class AnonymousFunctionTest extends TestCase { - public function testBasics():void + public function testBasics(): void { $foo = 1; - $this->calDefer(function ($param) use(&$foo){ + $this->calDefer(function ($param) use (&$foo) { $foo = $param; }, 2); $this->assertEquals(2, $foo); } - private function calDefer(callable $method, $param):void + private function calDefer(callable $method, $param): void { - $defer = new Defer($method,$param); + $defer = new Defer($method, $param); } } \ No newline at end of file diff --git a/tests/BlankConstructorTest.php b/tests/BlankConstructorTest.php index ac04cdb..375ee5e 100644 --- a/tests/BlankConstructorTest.php +++ b/tests/BlankConstructorTest.php @@ -5,31 +5,31 @@ * Date: 27. 8. 2024 * Time: 14:38 */ + namespace Defer\Tests; -use Defer\Defer; use PHPUnit\Framework\TestCase; class BlankConstructorTest extends TestCase { - public function testBasics():void + public function testBasics(): void { $stack = []; - $this->calDefer(function($item) use (&$stack){ - $stack[]=$item; + $this->calDefer(function ($item) use (&$stack) { + $stack[] = $item; }); $stack[] = "end"; - for($i=5;$i>=0;$i--){ + for ($i = 5; $i >= 0; $i--) { $this->assertEquals($i, array_shift($stack)); } } - private function calDefer(callable $callback):void + private function calDefer(callable $callback): void { $defer = defer(); - for($i=0;$i<5;$i++){ - $defer->defer($callback,$i); + for ($i = 0; $i < 5; $i++) { + $defer->defer($callback, $i); } $defer->defer($callback, $i); } diff --git a/tests/CustomFunctionTest.php b/tests/CustomFunctionTest.php index 8ac9881..a389eff 100644 --- a/tests/CustomFunctionTest.php +++ b/tests/CustomFunctionTest.php @@ -5,6 +5,7 @@ * Date: 27. 8. 2024 * Time: 14:38 */ + namespace Defer\Tests; use Defer\Defer; @@ -12,21 +13,22 @@ global $fpp; $fpp = 0; -function foo(int $a):void{ +function foo(int $a): void +{ global $fpp; - $fpp+=$a; + $fpp += $a; } class CustomFunctionTest extends TestCase { - public function testBasics():void + public function testBasics(): void { $this->incrementFpp(); global $fpp; $this->assertEquals(1, $fpp); } - private function incrementFpp():void + private function incrementFpp(): void { $defer = new Defer('Defer\Tests\foo', 1); } diff --git a/tests/FlushTest.php b/tests/FlushTest.php index ce5dc8f..7440d29 100644 --- a/tests/FlushTest.php +++ b/tests/FlushTest.php @@ -5,6 +5,7 @@ * Date: 27. 8. 2024 * Time: 14:38 */ + namespace Defer\Tests; use Defer\Defer; @@ -13,7 +14,7 @@ class FlushTest extends TestCase { - public function testBasics():void + public function testBasics(): void { $foo = 0; $this->testDefer($foo); @@ -21,7 +22,7 @@ public function testBasics():void $this->assertSame(1, $foo); } - private function testDefer(int &$foo):void + private function testDefer(int &$foo): void { $defer = new Defer(function () use (&$foo) { $foo++; @@ -33,5 +34,4 @@ private function testDefer(int &$foo):void } - } \ No newline at end of file diff --git a/tests/GlobalFunctionTest.php b/tests/GlobalFunctionTest.php index 6fac9ca..281d41d 100644 --- a/tests/GlobalFunctionTest.php +++ b/tests/GlobalFunctionTest.php @@ -5,6 +5,7 @@ * Date: 27. 8. 2024 * Time: 14:38 */ + namespace Defer\Tests; use Defer\Defer; @@ -13,16 +14,16 @@ class GlobalFunctionTest extends TestCase { - public function testBasics():void + public function testBasics(): void { - $file = fopen(__DIR__.'/test.txt', 'w+'); + $file = fopen(__DIR__ . '/test.txt', 'w+'); $this->calDefer($file); $this->assertIsClosedResource($file); - unlink(__DIR__.'/test.txt'); + unlink(__DIR__ . '/test.txt'); } - private function calDefer($param):void + private function calDefer($param): void { - $defer = new Defer(fclose(...),$param); + $defer = new Defer(fclose(...), $param); } } \ No newline at end of file diff --git a/tests/InvokeTest.php b/tests/InvokeTest.php index 78831e7..6b965b9 100644 --- a/tests/InvokeTest.php +++ b/tests/InvokeTest.php @@ -5,6 +5,7 @@ * Date: 27. 8. 2024 * Time: 14:38 */ + namespace Defer\Tests; use PHPUnit\Framework\TestCase; diff --git a/tests/ShortcutTest.php b/tests/ShortcutTest.php index dd52381..34d3794 100644 --- a/tests/ShortcutTest.php +++ b/tests/ShortcutTest.php @@ -5,9 +5,9 @@ * Date: 27. 8. 2024 * Time: 14:38 */ + namespace Defer\Tests; -use Defer\Defer; use PHPUnit\Framework\TestCase; diff --git a/tests/StackTest.php b/tests/StackTest.php index c162f06..886e365 100644 --- a/tests/StackTest.php +++ b/tests/StackTest.php @@ -5,6 +5,7 @@ * Date: 27. 8. 2024 * Time: 14:38 */ + namespace Defer\Tests; use Defer\Defer; @@ -13,23 +14,23 @@ class StackTest extends TestCase { - public function testBasics():void + public function testBasics(): void { $stack = []; - $this->calDefer(function($item) use (&$stack){ - $stack[]=$item; + $this->calDefer(function ($item) use (&$stack) { + $stack[] = $item; }); $stack[] = "end"; - for($i=5;$i>=0;$i--){ + for ($i = 5; $i >= 0; $i--) { $this->assertEquals($i, array_shift($stack)); } } - private function calDefer(callable $callback):void + private function calDefer(callable $callback): void { - $defer = new Defer($callback,0); - for($i=1;$i<5;$i++){ - $defer->defer($callback,$i); + $defer = new Defer($callback, 0); + for ($i = 1; $i < 5; $i++) { + $defer->defer($callback, $i); } $defer->defer($callback, $i); }