diff --git a/CHANGELOG.md b/CHANGELOG.md index aab09fa..7859821 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [UNRELEASED] +- Added `EditorJsImageUploaded` event that triggers when an image is uploaded. Via #98 by @woeler. +- Added `EditorJsThumbnailCreated` event that triggers when a thumbnail is generated. Via #98 by @woeler. + ## [3.3.0] - Fixed invalid image reference `image.url` in `views/link.blade.php`, via #101 by @roelofr. diff --git a/composer.json b/composer.json index 9f92d24..dc0d434 100644 --- a/composer.json +++ b/composer.json @@ -16,6 +16,7 @@ "codex-team/editor.js": "*", "guzzlehttp/guzzle": "^6.0 || ^7.0", "illuminate/support": "^8.0 || ^9.0 || ^10.0", + "illuminate/events": "^8.0 || ^9.0 || ^10.0", "laravel/nova": "^4.0", "spatie/image": "^1.7 || ^2.0" }, diff --git a/composer.lock b/composer.lock index f719ae1..2234041 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": "2327bf03ef3fc3d719b370bbcda09a77", + "content-hash": "bd2526552fd92454360a6dfa7de62fb5", "packages": [ { "name": "brick/math", @@ -334,16 +334,16 @@ }, { "name": "doctrine/dbal", - "version": "3.7.1", + "version": "3.7.2", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "5b7bd66c9ff58c04c5474ab85edce442f8081cb2" + "reference": "0ac3c270590e54910715e9a1a044cc368df282b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/5b7bd66c9ff58c04c5474ab85edce442f8081cb2", - "reference": "5b7bd66c9ff58c04c5474ab85edce442f8081cb2", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/0ac3c270590e54910715e9a1a044cc368df282b2", + "reference": "0ac3c270590e54910715e9a1a044cc368df282b2", "shasum": "" }, "require": { @@ -359,7 +359,7 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.10.35", + "phpstan/phpstan": "1.10.42", "phpstan/phpstan-strict-rules": "^1.5", "phpunit/phpunit": "9.6.13", "psalm/plugin-phpunit": "0.18.4", @@ -427,7 +427,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.7.1" + "source": "https://github.com/doctrine/dbal/tree/3.7.2" }, "funding": [ { @@ -443,7 +443,7 @@ "type": "tidelift" } ], - "time": "2023-10-06T05:06:20+00:00" + "time": "2023-11-19T08:06:58+00:00" }, { "name": "doctrine/deprecations", @@ -1838,17 +1838,17 @@ }, { "name": "laravel/nova", - "version": "4.23.0", + "version": "4.31.3", "source": { "type": "git", "url": "git@github.com:laravel/nova.git", - "reference": "6a14d83663f0484889a7f73ffaed7262bba7a26a" + "reference": "f3ecfc18f9466a217e1b0ff61bb21433e03ed03c" }, "dist": { "type": "zip", - "url": "https://nova.laravel.com/dist/laravel/nova/laravel-nova-6a14d83663f0484889a7f73ffaed7262bba7a26a-zip-1df780.zip", - "reference": "6a14d83663f0484889a7f73ffaed7262bba7a26a", - "shasum": "fd7c3f363f0a6f28c7aaac5cf5ea06193d8be9aa" + "url": "https://nova.laravel.com/dist/laravel/nova/laravel-nova-f3ecfc18f9466a217e1b0ff61bb21433e03ed03c-zip-0c207c.zip", + "reference": "f3ecfc18f9466a217e1b0ff61bb21433e03ed03c", + "shasum": "c5819555543e9ce3fd226bf13040973b7c1c5453" }, "require": { "brick/money": "^0.5.0|^0.6.0|^0.7.0|^0.8.0", @@ -1873,7 +1873,7 @@ "mockery/mockery": "^1.4.4", "nunomaduro/larastan": "^1.0.1|^2.5.1", "orchestra/testbench-dusk": "^6.24|^7.21|^8.0", - "phpunit/phpunit": "^9.6|^10.0", + "phpunit/phpunit": "^9.6|^10.1", "predis/predis": "^1.1.9|^2.0" }, "suggest": { @@ -1904,26 +1904,43 @@ } }, "scripts": { + "post-autoload-dump": [ + "@clear", + "@php vendor/bin/dusk-updater detect --auto-update --ansi", + "@php vendor/bin/testbench-dusk package:discover --ansi" + ], + "clear": [ + "@php vendor/bin/testbench-dusk package:purge-skeleton --ansi", + "@php vendor/bin/testbench-dusk package:dusk-purge --ansi" + ], "dusk:prepare": [ - "./vendor/bin/dusk-updater detect --auto-update", "@php -r \"file_exists('phpunit.dusk.xml') || copy('phpunit.dusk.xml.dist', 'phpunit.dusk.xml'); \"", - "@php -r \"if (file_exists('.env.dusk')) { copy('.env.dusk', 'vendor/laravel/nova-dusk-suite/.env'); } else { copy('.env.dusk.example', 'vendor/laravel/nova-dusk-suite/.env'); }\"", - "./vendor/bin/testbench-dusk package:discover" + "@php -r \"if (file_exists('workbench/.env.dusk')) { copy('workbench/.env.dusk', 'vendor/laravel/nova-dusk-suite/.env'); } else { copy('workbench/.env.dusk.example', 'vendor/laravel/nova-dusk-suite/.env'); }\"" ], "dusk:dev-assets": [ "TAILWIND_MODE=build npm run dev", - "./vendor/bin/testbench-dusk nova:publish --force" + "@php vendor/bin/testbench-dusk nova:publish --force --ansi" ], "dusk:assets": [ "TAILWIND_MODE=build npm run prod", - "./vendor/bin/testbench-dusk nova:publish --force" + "@php vendor/bin/testbench-dusk nova:publish --force --ansi" ], "dusk:test": [ - "./vendor/bin/testbench-dusk package:dusk-purge", - "./vendor/bin/phpunit -c phpunit.dusk.xml" + "@php vendor/bin/testbench-dusk package:dusk-purge --ansi", + "@php vendor/bin/phpunit -c phpunit.dusk.xml --stop-on-failure --stop-on-error" ], "dusk:filter": [ - "./vendor/bin/testbench-dusk package:dusk-purge && ./vendor/bin/phpunit -c phpunit.dusk.xml --filter" + "./vendor/bin/testbench-dusk package:dusk-purge --ansi && ./vendor/bin/phpunit -c phpunit.dusk.xml --filter" + ], + "test:local": [ + "@php vendor/bin/phpunit -c phpunit.xml --group date-field,datetime-field,external-network --testdox", + "@php vendor/bin/phpunit -c phpunit.dusk.xml --group date-field,datetime-field,external-network --testdox" + ], + "serve": [ + "@clear", + "@php vendor/bin/testbench package:discover --ansi", + "@php vendor/bin/testbench workbench:build --ansi", + "@php vendor/bin/testbench serve" ] }, "license": [ @@ -1941,9 +1958,9 @@ "laravel" ], "support": { - "source": "https://github.com/laravel/nova/tree/v4.23.0" + "source": "https://github.com/laravel/nova/tree/v4.31.3" }, - "time": "2023-04-07T18:14:13+00:00" + "time": "2023-11-15T19:40:34+00:00" }, { "name": "laravel/prompts", @@ -3026,16 +3043,16 @@ }, { "name": "openspout/openspout", - "version": "v4.19.0", + "version": "v4.20.0", "source": { "type": "git", "url": "https://github.com/openspout/openspout.git", - "reference": "b2d9a007eff4cbdf0a3befe63d696c365ad1abc0" + "reference": "74c9e23ec512856f326fea96503646660919b8f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/openspout/openspout/zipball/b2d9a007eff4cbdf0a3befe63d696c365ad1abc0", - "reference": "b2d9a007eff4cbdf0a3befe63d696c365ad1abc0", + "url": "https://api.github.com/repos/openspout/openspout/zipball/74c9e23ec512856f326fea96503646660919b8f6", + "reference": "74c9e23ec512856f326fea96503646660919b8f6", "shasum": "" }, "require": { @@ -3049,13 +3066,13 @@ }, "require-dev": { "ext-zlib": "*", - "friendsofphp/php-cs-fixer": "^3.35.1", - "infection/infection": "^0.27.6", + "friendsofphp/php-cs-fixer": "^3.38.2", + "infection/infection": "^0.27.8", "phpbench/phpbench": "^1.2.14", - "phpstan/phpstan": "^1.10.39", + "phpstan/phpstan": "^1.10.43", "phpstan/phpstan-phpunit": "^1.3.15", - "phpstan/phpstan-strict-rules": "^1.5.1", - "phpunit/phpunit": "^10.4.1" + "phpstan/phpstan-strict-rules": "^1.5.2", + "phpunit/phpunit": "^10.4.2" }, "suggest": { "ext-iconv": "To handle non UTF-8 CSV files (if \"php-mbstring\" is not already installed or is too limited)", @@ -3103,7 +3120,7 @@ ], "support": { "issues": "https://github.com/openspout/openspout/issues", - "source": "https://github.com/openspout/openspout/tree/v4.19.0" + "source": "https://github.com/openspout/openspout/tree/v4.20.0" }, "funding": [ { @@ -3115,7 +3132,7 @@ "type": "github" } ], - "time": "2023-10-19T11:52:22+00:00" + "time": "2023-11-20T10:10:28+00:00" }, { "name": "phpoption/phpoption", @@ -7702,16 +7719,16 @@ }, { "name": "orchestra/testbench-core", - "version": "v8.15.1", + "version": "v8.15.2", "source": { "type": "git", "url": "https://github.com/orchestral/testbench-core.git", - "reference": "428628ef2fecffe30c1c922536242ebe0da1c47e" + "reference": "1bd2aa77c0fdd674d28e8d6e44fe5f6528ff966a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/orchestral/testbench-core/zipball/428628ef2fecffe30c1c922536242ebe0da1c47e", - "reference": "428628ef2fecffe30c1c922536242ebe0da1c47e", + "url": "https://api.github.com/repos/orchestral/testbench-core/zipball/1bd2aa77c0fdd674d28e8d6e44fe5f6528ff966a", + "reference": "1bd2aa77c0fdd674d28e8d6e44fe5f6528ff966a", "shasum": "" }, "require": { @@ -7786,7 +7803,7 @@ "issues": "https://github.com/orchestral/testbench/issues", "source": "https://github.com/orchestral/testbench-core" }, - "time": "2023-11-10T04:43:17+00:00" + "time": "2023-11-20T22:34:56+00:00" }, { "name": "orchestra/workbench", @@ -9691,16 +9708,16 @@ }, { "name": "spatie/ray", - "version": "1.40.0", + "version": "1.40.1", "source": { "type": "git", "url": "https://github.com/spatie/ray.git", - "reference": "d2477d80996416ac33066f4fef8c6bd6e393fedd" + "reference": "8e6547ff47aae2e4f615a5dcea1e5e4911b1dc9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ray/zipball/d2477d80996416ac33066f4fef8c6bd6e393fedd", - "reference": "d2477d80996416ac33066f4fef8c6bd6e393fedd", + "url": "https://api.github.com/repos/spatie/ray/zipball/8e6547ff47aae2e4f615a5dcea1e5e4911b1dc9f", + "reference": "8e6547ff47aae2e4f615a5dcea1e5e4911b1dc9f", "shasum": "" }, "require": { @@ -9751,7 +9768,7 @@ ], "support": { "issues": "https://github.com/spatie/ray/issues", - "source": "https://github.com/spatie/ray/tree/1.40.0" + "source": "https://github.com/spatie/ray/tree/1.40.1" }, "funding": [ { @@ -9763,7 +9780,7 @@ "type": "other" } ], - "time": "2023-11-07T13:53:06+00:00" + "time": "2023-11-20T08:20:15+00:00" }, { "name": "symfony/filesystem", @@ -10193,16 +10210,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.2.1", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", "shasum": "" }, "require": { @@ -10231,7 +10248,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + "source": "https://github.com/theseer/tokenizer/tree/1.2.2" }, "funding": [ { @@ -10239,7 +10256,7 @@ "type": "github" } ], - "time": "2021-07-28T10:34:58+00:00" + "time": "2023-11-20T00:12:19+00:00" }, { "name": "zbateson/mail-mime-parser", @@ -10463,5 +10480,5 @@ "platform-overrides": { "php": "8.1.25" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/src/Events/EditorJsImageUploaded.php b/src/Events/EditorJsImageUploaded.php new file mode 100644 index 0000000..17366bc --- /dev/null +++ b/src/Events/EditorJsImageUploaded.php @@ -0,0 +1,16 @@ +applyThumbnails($path); } + event(new EditorJsImageUploaded(config('nova-editor-js.toolSettings.image.disk'), $path)); + return response()->json([ 'success' => 1, 'file' => [ @@ -109,6 +113,7 @@ public function url(Request $request): JsonResponse $urlBasename = basename(parse_url(url($url), PHP_URL_PATH)); $nameWithPath = config('nova-editor-js.toolSettings.image.path') . '/' . uniqid() . $urlBasename; Storage::disk(config('nova-editor-js.toolSettings.image.disk'))->put($nameWithPath, $response->body()); + event(new EditorJsImageUploaded(config('nova-editor-js.toolSettings.image.disk'), $nameWithPath)); return response()->json([ 'success' => 1, @@ -213,6 +218,8 @@ private function applyThumbnails($path) $this->applyAlterations($newPath, $setting); + event(new EditorJsThumbnailCreated(config('nova-editor-js.toolSettings.image.disk'), $newThumbnailPath)); + $generatedThumbnails[] = Storage::disk(config('nova-editor-js.toolSettings.image.disk'))->url($newThumbnailPath); } } diff --git a/tests/Feature/Http/Controllers/EditorJsImageUploadControllerTest.php b/tests/Feature/Http/Controllers/EditorJsImageUploadControllerTest.php index e092ca9..ccf2b49 100644 --- a/tests/Feature/Http/Controllers/EditorJsImageUploadControllerTest.php +++ b/tests/Feature/Http/Controllers/EditorJsImageUploadControllerTest.php @@ -4,11 +4,15 @@ namespace Tests\Feature\Http\Controllers; +use Advoor\NovaEditorJs\Events\EditorJsImageUploaded; +use Advoor\NovaEditorJs\Events\EditorJsThumbnailCreated; use Advoor\NovaEditorJs\Http\Controllers\EditorJsImageUploadController; use finfo; use Illuminate\Http\Response; use Illuminate\Http\UploadedFile; use Illuminate\Support\Arr; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Storage; @@ -37,6 +41,8 @@ public function testImageUpload(string $path): void { Storage::fake(); Storage::fake('public'); + $fake = Event::fake(); + DB::setEventDispatcher($fake); $uploadedFile = UploadedFile::fake()->create('file', 1024, (new finfo())->file($path, FILEINFO_MIME_TYPE)); if ($fp = $uploadedFile->openFile('w')) { @@ -61,6 +67,8 @@ public function testImageUpload(string $path): void fn ($file) => Str::endsWith($file, basename($responseUrl)), ); + Event::assertDispatched(EditorJsImageUploaded::class); + Event::assertDispatched(EditorJsThumbnailCreated::class); $this->assertCount(1, $filesThatLookLikeTheUpload, 'Storage doesn\'t seem to contain a file with the same name as the returned URL'); } @@ -89,6 +97,8 @@ public function testValidImageUrlSubmission(string $file): void { Storage::fake(); Storage::fake('public'); + $fake = Event::fake(); + DB::setEventDispatcher($fake); Http::fake([ 'https://example.com/image.bin' => Http::response(file_get_contents($file)), @@ -107,6 +117,7 @@ public function testValidImageUrlSubmission(string $file): void $createdFiles = Storage::disk()->allFiles(); $this->assertCount(1, $createdFiles, 'Storage seems to not contain exactly one file'); + Event::assertDispatched(EditorJsImageUploaded::class); $this->assertEquals(basename($createdFiles[0]), basename($responseUrl), 'Response URL filename doesn\'t match created file basename'); }