From be86f161a26856d597b83ccf1ae24f51f7847846 Mon Sep 17 00:00:00 2001 From: Pig Fang Date: Tue, 3 Sep 2019 18:41:19 +0800 Subject: [PATCH] Reinvent wheel: Filters API --- app/Http/Controllers/PlayerController.php | 12 +- app/Providers/AppServiceProvider.php | 1 + app/Services/Filter.php | 52 +++++ app/helpers.php | 7 - composer.json | 3 +- composer.lock | 227 +++++----------------- tests/PlayerControllerTest.php | 10 +- tests/ServicesTest/FilterTest.php | 57 ++++-- 8 files changed, 158 insertions(+), 211 deletions(-) create mode 100644 app/Services/Filter.php diff --git a/app/Http/Controllers/PlayerController.php b/app/Http/Controllers/PlayerController.php index 0e7a7526..f7de47f5 100644 --- a/app/Http/Controllers/PlayerController.php +++ b/app/Http/Controllers/PlayerController.php @@ -4,11 +4,11 @@ namespace App\Http\Controllers; use View; use Event; -use Eventy; use Option; use App\Models\User; use App\Models\Player; use App\Models\Texture; +use App\Services\Filter; use App\Services\Rejection; use Illuminate\Http\Request; use App\Events\PlayerWasAdded; @@ -119,8 +119,12 @@ class PlayerController extends Controller return json(trans('user.player.delete.success', ['name' => $playerName]), 0); } - public function rename(Request $request, Dispatcher $dispatcher, $pid) - { + public function rename( + Request $request, + Dispatcher $dispatcher, + Filter $filter, + $pid + ) { $newName = $this->validate($request, [ 'name' => 'required|player_name|min:'.option('player_name_length_min').'|max:'.option('player_name_length_max'), ])['name']; @@ -128,7 +132,7 @@ class PlayerController extends Controller $dispatcher->dispatch('player.renaming', [$player, $newName]); - $can = Eventy::filter('can_rename_player', $player, $newName); + $can = $filter->apply('can_rename_player', [$player, $newName]); if ($can instanceof Rejection) { return json($can->getReason(), 1); } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index a1e5b4e6..a07130af 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -25,6 +25,7 @@ class AppServiceProvider extends ServiceProvider $this->app->alias(\App\Services\Option::class, 'options'); $this->app->singleton('parsedown', \Parsedown::class); $this->app->singleton('webpack', \App\Services\Webpack::class); + $this->app->singleton(\App\Services\Filter::class); } /** diff --git a/app/Services/Filter.php b/app/Services/Filter.php new file mode 100644 index 00000000..8867f893 --- /dev/null +++ b/app/Services/Filter.php @@ -0,0 +1,52 @@ +listeners[$hook])) { + $this->listeners[$hook] = collect(); + } + + $this->listeners[$hook]->push([ + 'callback' => $callback, + 'priority' => $priority, + ]); + } + + public function apply(string $hook, array $payload) + { + $listeners = $this->getListeners($hook); + if ($listeners->isNotEmpty()) { + $value = $payload[0]; + unset($payload[0]); + $args = array_values($payload); + + return $this->listeners[$hook] + ->sortByDesc('priority') + ->reduce(function ($carry, $item) use ($args) { + return call_user_func($item['callback'], $carry, ...$args); + }, $value); + } else { + return $payload[0]; + } + } + + public function remove(string $hook) + { + unset($this->listeners[$hook]); + } + + public function getListeners(string $hook): Collection + { + return Arr::get($this->listeners, $hook, collect()); + } +} diff --git a/app/helpers.php b/app/helpers.php index cd497f52..5d10f72d 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -66,13 +66,6 @@ if (! function_exists('json')) { } } -if (! function_exists('add_filter')) { - function add_filter($hook, $callback, $priority = 20, $arguments = 1): void - { - app('eventy')->addFilter($hook, $callback, $priority, $arguments); - } -} - if (! function_exists('bs_footer_extra')) { function bs_footer_extra(): string { diff --git a/composer.json b/composer.json index 5cfc7cfc..3e8542e2 100644 --- a/composer.json +++ b/composer.json @@ -25,8 +25,7 @@ "doctrine/dbal": "^2.9", "tymon/jwt-auth": "dev-develop", "laravel/passport": "^7.3", - "composer/ca-bundle": "^1.2", - "tormjens/eventy": "^0.5.7" + "composer/ca-bundle": "^1.2" }, "require-dev": { "fzaninotto/faker": "~1.8", diff --git a/composer.lock b/composer.lock index 5e3979ae..5bd9fd0c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "cc8c73538e2bc6907ba1778db5da12c4", + "content-hash": "c7430b05e825f77006591003ca2ccfd0", "packages": [ { "name": "composer/ca-bundle", @@ -1054,64 +1054,6 @@ ], "time": "2019-06-24T14:06:31+00:00" }, - { - "name": "jeremeamia/superclosure", - "version": "2.4.0", - "source": { - "type": "git", - "url": "https://github.com/jeremeamia/super_closure.git", - "reference": "5707d5821b30b9a07acfb4d76949784aaa0e9ce9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/jeremeamia/super_closure/zipball/5707d5821b30b9a07acfb4d76949784aaa0e9ce9", - "reference": "5707d5821b30b9a07acfb4d76949784aaa0e9ce9", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^1.2|^2.0|^3.0|^4.0", - "php": ">=5.4", - "symfony/polyfill-php56": "^1.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0|^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.4-dev" - } - }, - "autoload": { - "psr-4": { - "SuperClosure\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jeremy Lindblom", - "role": "Developer", - "email": "jeremeamia@gmail.com", - "homepage": "https://github.com/jeremeamia" - } - ], - "description": "Serialize Closure objects, including their context and binding", - "homepage": "https://github.com/jeremeamia/super_closure", - "keywords": [ - "closure", - "function", - "lambda", - "parser", - "serializable", - "serialize", - "tokenizer" - ], - "time": "2018-03-21T22:21:57+00:00" - }, { "name": "laravel/framework", "version": "v5.8.33", @@ -1871,57 +1813,6 @@ ], "time": "2019-08-17T13:57:34+00:00" }, - { - "name": "nikic/php-parser", - "version": "v4.2.3", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "e612609022e935f3d0337c1295176505b41188c8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/e612609022e935f3d0337c1295176505b41188c8", - "reference": "e612609022e935f3d0337c1295176505b41188c8", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.2-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "time": "2019-08-12T20:17:41+00:00" - }, { "name": "opis/closure", "version": "3.3.1", @@ -4290,71 +4181,6 @@ "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", "time": "2017-11-27T11:13:29+00:00" }, - { - "name": "tormjens/eventy", - "version": "0.5.7", - "source": { - "type": "git", - "url": "https://github.com/tormjens/eventy.git", - "reference": "4c4501aa085fbdc214af0e2b535d700a617dbc9e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/tormjens/eventy/zipball/4c4501aa085fbdc214af0e2b535d700a617dbc9e", - "reference": "4c4501aa085fbdc214af0e2b535d700a617dbc9e", - "shasum": "" - }, - "require": { - "illuminate/support": ">=5.3", - "jeremeamia/superclosure": "^2.4", - "php": ">=7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "TorMorten\\Eventy\\EventServiceProvider", - "TorMorten\\Eventy\\EventBladeServiceProvider" - ], - "aliases": { - "Eventy": "TorMorten\\Eventy\\Facades\\Events" - } - } - }, - "autoload": { - "psr-4": { - "TorMorten\\Eventy\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Tor Morten Jensen", - "homepage": "https://tormorten.no" - } - ], - "description": "The WordPress filter/action system in Laravel", - "homepage": "https://github.com/tormjens/eventy", - "keywords": [ - "HOOK", - "action", - "actions", - "event", - "events", - "filter", - "filters", - "hooks", - "laravel", - "wordpress" - ], - "time": "2019-06-25T09:36:50+00:00" - }, { "name": "tymon/jwt-auth", "version": "dev-develop", @@ -5686,6 +5512,57 @@ ], "time": "2019-08-09T12:45:53+00:00" }, + { + "name": "nikic/php-parser", + "version": "v4.2.4", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "97e59c7a16464196a8b9c77c47df68e4a39a45c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/97e59c7a16464196a8b9c77c47df68e4a39a45c4", + "reference": "97e59c7a16464196a8b9c77c47df68e4a39a45c4", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "time": "2019-09-01T07:51:21+00:00" + }, { "name": "phar-io/manifest", "version": "1.0.3", diff --git a/tests/PlayerControllerTest.php b/tests/PlayerControllerTest.php index b90f5990..5705c63f 100644 --- a/tests/PlayerControllerTest.php +++ b/tests/PlayerControllerTest.php @@ -3,11 +3,11 @@ namespace Tests; use Event; -use Eventy; use App\Events; use App\Models\User; use App\Models\Player; use App\Models\Texture; +use App\Services\Filter; use App\Services\Rejection; use Illuminate\Foundation\Testing\DatabaseTransactions; @@ -190,17 +190,19 @@ class PlayerControllerTest extends TestCase Event::assertDispatched('player.renaming'); // Rejected by filter + $filter = resolve(Filter::class); $pid = $player->pid; - Eventy::addFilter('can_rename_player', function ($player) { + $filter->add('can_rename_player', function ($player, $newName) { + $this->assertEquals('new', $newName); return new Rejection('rejected'); - }, 20, 1); + }); $name = factory(Player::class)->create()->name; $this->postJson('/user/player/rename/'.$player->pid, ['name' => 'new']) ->assertJson([ 'code' => 1, 'message' => 'rejected', ]); - Eventy::removeAllFilters('can_rename_player'); + $filter->remove('can_rename_player'); // Success Event::fake(); diff --git a/tests/ServicesTest/FilterTest.php b/tests/ServicesTest/FilterTest.php index a797fe4d..25122a02 100644 --- a/tests/ServicesTest/FilterTest.php +++ b/tests/ServicesTest/FilterTest.php @@ -2,32 +2,51 @@ namespace Tests; -use Eventy; +use App\Services\Filter; class FilterTest extends TestCase { - public function testAddFilter() + public function testAdd() { - $this->mock('eventy', function ($mock) { - $mock->shouldReceive('addFilter') - ->withArgs(function ($hook, $callback) { - $this->assertEquals('my.hook', $hook); - $this->assertEquals('Filtered text', $callback('text')); - - return true; - }) - ->once(); - }); - add_filter('my.hook', function ($value) { - return "Filtered $value"; - }); + $filter = new Filter(); + $filter->add('hook', function () {}); + $filter->add('hook', function () {}, 10); + $this->assertCount(2, $filter->getListeners('hook')); } - public function testIntegration() + public function testApply() { - add_filter('hook.test', function ($value) { - return $value.'ed'; + $filter = new Filter(); + $this->assertEquals('value', $filter->apply('hook', ['value', 'add'])); + + $filter->add('hook', function ($value, $addition) { + $this->assertEquals('add', $addition); + return $value.'_medium'; }); - $this->assertEquals('tested', Eventy::filter('hook.test', 'test')); + $filter->add('hook', function ($value) { + return $value.'_low'; + }, 10); + $filter->add('hook', function ($value) { + return $value.'_high'; + }, 30); + $this->assertEquals('value_high_medium_low', $filter->apply('hook', ['value', 'add'])); + } + + public function testRemove() + { + $filter = new Filter(); + $filter->remove('hook'); + $this->assertCount(0, $filter->getListeners('hook')); + + $filter->add('hook', function () {}); + $this->assertCount(1, $filter->getListeners('hook')); + $filter->remove('hook'); + $this->assertCount(0, $filter->getListeners('hook')); + } + + public function testGetListeners() + { + $filter = new Filter(); + $this->assertCount(0, $filter->getListeners('hook')); } }