diff --git a/README.md b/README.md index cb48536..118688c 100644 --- a/README.md +++ b/README.md @@ -64,3 +64,20 @@ In `app/Http/Controllers/OfficeController.php` file, in the `store()` method, up Test method `test_public_file_show()`. --- + +## Task 6. Resize Image with Intervention/Image + +In `app/Http/Controllers/ShopController.php` file, in the `store()` method, the uploaded image file needs to be resized to 500x500 and stored in /storage/app/shops/resized-$filename. Use intervention/image package, it's already pre-installed for you. + +Test method `test_upload_resize()`. + +--- + +## Task 7. Spatie Media Library + +In `app/Http/Controllers/CompanyController.php` file, in the `show()` method, use Spatie Media Library package methods to get the full URL of the file that was just uploaded. + +Test method `test_spatie_media_library()`. + +--- + diff --git a/app/Http/Controllers/CompanyController.php b/app/Http/Controllers/CompanyController.php new file mode 100644 index 0000000..12fcb81 --- /dev/null +++ b/app/Http/Controllers/CompanyController.php @@ -0,0 +1,28 @@ + $request->name, + ]); + $company->addMediaFromRequest('photo')->toMediaCollection('companies'); + + return 'Success'; + } + + public function show(Company $company) + { + // TASK: retrieve the full URL to the uploaded photo file, using Spatie Media Library + $photo = '???'; + + return view('companies.show', compact('company', 'photo')); + } + +} diff --git a/app/Http/Controllers/ShopController.php b/app/Http/Controllers/ShopController.php new file mode 100644 index 0000000..b2c485a --- /dev/null +++ b/app/Http/Controllers/ShopController.php @@ -0,0 +1,21 @@ +file('photo')->getClientOriginalName(); + $request->file('photo')->storeAs('shops', $filename); + + // TASK: resize the uploaded image from /storage/app/shops/$filename + // to size of 500x500 and store it as /storage/app/shops/resized-$filename + // Use intervention/image package, it's already pre-installed for you + + return 'Success'; + } +} diff --git a/app/Models/Company.php b/app/Models/Company.php new file mode 100644 index 0000000..009cf4c --- /dev/null +++ b/app/Models/Company.php @@ -0,0 +1,15 @@ +=5.4.0" + }, + "require-dev": { + "mockery/mockery": "~0.9.2", + "phpunit/phpunit": "^4.8 || ^5.7 || ^7.5.15" + }, + "suggest": { + "ext-gd": "to use GD library based image processing.", + "ext-imagick": "to use Imagick based image processing.", + "intervention/imagecache": "Caching extension for the Intervention Image library" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + }, + "laravel": { + "providers": [ + "Intervention\\Image\\ImageServiceProvider" + ], + "aliases": { + "Image": "Intervention\\Image\\Facades\\Image" + } + } + }, + "autoload": { + "psr-4": { + "Intervention\\Image\\": "src/Intervention/Image" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oliver Vogel", + "email": "oliver@olivervogel.com", + "homepage": "http://olivervogel.com/" + } + ], + "description": "Image handling and manipulation library with support for Laravel integration", + "homepage": "http://image.intervention.io/", + "keywords": [ + "gd", + "image", + "imagick", + "laravel", + "thumbnail", + "watermark" + ], + "support": { + "issues": "https://github.com/Intervention/image/issues", + "source": "https://github.com/Intervention/image/tree/2.7.0" + }, + "funding": [ + { + "url": "https://www.paypal.me/interventionphp", + "type": "custom" + }, + { + "url": "https://github.com/Intervention", + "type": "github" + } + ], + "time": "2021-10-03T14:17:12+00:00" + }, { "name": "laravel/framework", "version": "v8.74.0", @@ -1609,6 +1693,71 @@ ], "time": "2021-11-28T21:50:23+00:00" }, + { + "name": "league/glide", + "version": "1.7.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/glide.git", + "reference": "ae5e26700573cb678919d28e425a8b87bc71c546" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/glide/zipball/ae5e26700573cb678919d28e425a8b87bc71c546", + "reference": "ae5e26700573cb678919d28e425a8b87bc71c546", + "shasum": "" + }, + "require": { + "intervention/image": "^2.4", + "league/flysystem": "^1.0", + "php": "^7.2|^8.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^1.3.3", + "phpunit/php-token-stream": "^3.1|^4.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Glide\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonathan Reinink", + "email": "jonathan@reinink.ca", + "homepage": "http://reinink.ca" + } + ], + "description": "Wonderfully easy on-demand image manipulation library with an HTTP based API.", + "homepage": "http://glide.thephpleague.com", + "keywords": [ + "ImageMagick", + "editing", + "gd", + "image", + "imagick", + "league", + "manipulation", + "processing" + ], + "support": { + "issues": "https://github.com/thephpleague/glide/issues", + "source": "https://github.com/thephpleague/glide/tree/1.7.0" + }, + "time": "2020-11-05T17:34:03+00:00" + }, { "name": "league/mime-type-detection", "version": "1.9.0", @@ -1665,6 +1814,77 @@ ], "time": "2021-11-21T11:48:40+00:00" }, + { + "name": "maennchen/zipstream-php", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/maennchen/ZipStream-PHP.git", + "reference": "c4c5803cc1f93df3d2448478ef79394a5981cc58" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/c4c5803cc1f93df3d2448478ef79394a5981cc58", + "reference": "c4c5803cc1f93df3d2448478ef79394a5981cc58", + "shasum": "" + }, + "require": { + "myclabs/php-enum": "^1.5", + "php": ">= 7.1", + "psr/http-message": "^1.0", + "symfony/polyfill-mbstring": "^1.0" + }, + "require-dev": { + "ext-zip": "*", + "guzzlehttp/guzzle": ">= 6.3", + "mikey179/vfsstream": "^1.6", + "phpunit/phpunit": ">= 7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "ZipStream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paul Duncan", + "email": "pabs@pablotron.org" + }, + { + "name": "Jonatan Männchen", + "email": "jonatan@maennchen.ch" + }, + { + "name": "Jesse Donat", + "email": "donatj@gmail.com" + }, + { + "name": "András Kolesár", + "email": "kolesar@kolesar.hu" + } + ], + "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.", + "keywords": [ + "stream", + "zip" + ], + "support": { + "issues": "https://github.com/maennchen/ZipStream-PHP/issues", + "source": "https://github.com/maennchen/ZipStream-PHP/tree/master" + }, + "funding": [ + { + "url": "https://opencollective.com/zipstream", + "type": "open_collective" + } + ], + "time": "2020-05-30T13:11:16+00:00" + }, { "name": "monolog/monolog", "version": "2.3.5", @@ -1764,6 +1984,66 @@ ], "time": "2021-10-01T21:08:31+00:00" }, + { + "name": "myclabs/php-enum", + "version": "1.8.3", + "source": { + "type": "git", + "url": "https://github.com/myclabs/php-enum.git", + "reference": "b942d263c641ddb5190929ff840c68f78713e937" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/php-enum/zipball/b942d263c641ddb5190929ff840c68f78713e937", + "reference": "b942d263c641ddb5190929ff840c68f78713e937", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.3 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "1.*", + "vimeo/psalm": "^4.6.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "MyCLabs\\Enum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP Enum contributors", + "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" + } + ], + "description": "PHP Enum implementation", + "homepage": "http://github.com/myclabs/php-enum", + "keywords": [ + "enum" + ], + "support": { + "issues": "https://github.com/myclabs/php-enum/issues", + "source": "https://github.com/myclabs/php-enum/tree/1.8.3" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum", + "type": "tidelift" + } + ], + "time": "2021-07-05T08:18:36+00:00" + }, { "name": "nesbot/carbon", "version": "2.55.2", @@ -2854,6 +3134,297 @@ ], "time": "2021-09-25T23:10:38+00:00" }, + { + "name": "spatie/image", + "version": "1.10.5", + "source": { + "type": "git", + "url": "https://github.com/spatie/image.git", + "reference": "63a963d0200fb26f2564bf7201fc7272d9b22933" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/image/zipball/63a963d0200fb26f2564bf7201fc7272d9b22933", + "reference": "63a963d0200fb26f2564bf7201fc7272d9b22933", + "shasum": "" + }, + "require": { + "ext-exif": "*", + "ext-json": "*", + "ext-mbstring": "*", + "league/glide": "^1.6", + "php": "^7.2|^8.0", + "spatie/image-optimizer": "^1.1", + "spatie/temporary-directory": "^1.0|^2.0", + "symfony/process": "^3.0|^4.0|^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.0|^9.0", + "symfony/var-dumper": "^4.0|^5.0", + "vimeo/psalm": "^4.6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\Image\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Manipulate images with an expressive API", + "homepage": "https://github.com/spatie/image", + "keywords": [ + "image", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/image/issues", + "source": "https://github.com/spatie/image/tree/1.10.5" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2021-04-07T08:42:24+00:00" + }, + { + "name": "spatie/image-optimizer", + "version": "1.6.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/image-optimizer.git", + "reference": "8bad7f04fd7d31d021b4752ee89f8a450dad8017" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/image-optimizer/zipball/8bad7f04fd7d31d021b4752ee89f8a450dad8017", + "reference": "8bad7f04fd7d31d021b4752ee89f8a450dad8017", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.3|^8.0", + "psr/log": "^1.0 | ^2.0 | ^3.0", + "symfony/process": "^4.2|^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.21|^9.4.4", + "symfony/var-dumper": "^4.2|^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\ImageOptimizer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Easily optimize images using PHP", + "homepage": "https://github.com/spatie/image-optimizer", + "keywords": [ + "image-optimizer", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/image-optimizer/issues", + "source": "https://github.com/spatie/image-optimizer/tree/1.6.1" + }, + "time": "2021-11-17T10:36:45+00:00" + }, + { + "name": "spatie/laravel-medialibrary", + "version": "9.9.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-medialibrary.git", + "reference": "cd9626c2f522d6e833afe3d8be0364202cbd165e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-medialibrary/zipball/cd9626c2f522d6e833afe3d8be0364202cbd165e", + "reference": "cd9626c2f522d6e833afe3d8be0364202cbd165e", + "shasum": "" + }, + "require": { + "ext-exif": "*", + "ext-fileinfo": "*", + "ext-json": "*", + "illuminate/bus": "^8.71", + "illuminate/console": "^8.71", + "illuminate/database": "^8.71", + "illuminate/pipeline": "^8.71", + "illuminate/support": "^8.71", + "intervention/image": "^2.7", + "league/flysystem": "^1.0.64", + "league/glide": "^1.7", + "maennchen/zipstream-php": "^1.0|^2.0", + "php": "^7.4|^8.0", + "spatie/image": "^1.10.5", + "spatie/temporary-directory": "^1.1|^2.0", + "symfony/console": "^4.4|^5.0" + }, + "conflict": { + "php-ffmpeg/php-ffmpeg": "<0.6.1" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.133.11", + "doctrine/dbal": "^2.12", + "ext-pdo_sqlite": "*", + "ext-zip": "*", + "guzzlehttp/guzzle": "^7.0", + "league/flysystem-aws-s3-v3": "^1.0.23", + "mockery/mockery": "^1.4", + "orchestra/testbench": "^5.20|^6.23", + "phpunit/phpunit": "^9.3", + "spatie/laravel-ray": "^1.24", + "spatie/pdf-to-image": "^2.1", + "spatie/phpunit-snapshot-assertions": "^4.0" + }, + "suggest": { + "league/flysystem-aws-s3-v3": "Required to use AWS S3 file storage", + "php-ffmpeg/php-ffmpeg": "Required for generating video thumbnails", + "spatie/pdf-to-image": "Required for generating thumbsnails of PDFs and SVGs" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\MediaLibrary\\MediaLibraryServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\MediaLibrary\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Associate files with Eloquent models", + "homepage": "https://github.com/spatie/laravel-medialibrary", + "keywords": [ + "cms", + "conversion", + "downloads", + "images", + "laravel", + "laravel-medialibrary", + "media", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-medialibrary/issues", + "source": "https://github.com/spatie/laravel-medialibrary/tree/9.9.1" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2021-12-03T19:56:58+00:00" + }, + { + "name": "spatie/temporary-directory", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/temporary-directory.git", + "reference": "06fe0f10d068fdf145c9b2235030e568c913bb61" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/06fe0f10d068fdf145c9b2235030e568c913bb61", + "reference": "06fe0f10d068fdf145c9b2235030e568c913bb61", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\TemporaryDirectory\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alex Vanderbist", + "email": "alex@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Easily create, use and destroy temporary directories", + "homepage": "https://github.com/spatie/temporary-directory", + "keywords": [ + "php", + "spatie", + "temporary-directory" + ], + "support": { + "issues": "https://github.com/spatie/temporary-directory/issues", + "source": "https://github.com/spatie/temporary-directory/tree/2.0.0" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2021-03-30T19:46:13+00:00" + }, { "name": "swiftmailer/swiftmailer", "version": "v6.3.0", diff --git a/database/migrations/2021_12_06_090808_create_shops_table.php b/database/migrations/2021_12_06_090808_create_shops_table.php new file mode 100644 index 0000000..8dde815 --- /dev/null +++ b/database/migrations/2021_12_06_090808_create_shops_table.php @@ -0,0 +1,33 @@ +id(); + $table->string('name'); + $table->string('photo'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('shops'); + } +} diff --git a/database/migrations/2021_12_06_092816_create_companies_table.php b/database/migrations/2021_12_06_092816_create_companies_table.php new file mode 100644 index 0000000..7c2c288 --- /dev/null +++ b/database/migrations/2021_12_06_092816_create_companies_table.php @@ -0,0 +1,32 @@ +id(); + $table->string('name'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('companies'); + } +} diff --git a/database/migrations/2021_12_06_092833_create_media_table.php b/database/migrations/2021_12_06_092833_create_media_table.php new file mode 100644 index 0000000..378b046 --- /dev/null +++ b/database/migrations/2021_12_06_092833_create_media_table.php @@ -0,0 +1,32 @@ +bigIncrements('id'); + + $table->morphs('model'); + $table->uuid('uuid')->nullable()->unique(); + $table->string('collection_name'); + $table->string('name'); + $table->string('file_name'); + $table->string('mime_type')->nullable(); + $table->string('disk'); + $table->string('conversions_disk')->nullable(); + $table->unsignedBigInteger('size'); + $table->json('manipulations'); + $table->json('custom_properties'); + $table->json('generated_conversions'); + $table->json('responsive_images'); + $table->unsignedInteger('order_column')->nullable(); + + $table->nullableTimestamps(); + }); + } +} diff --git a/resources/views/companies/show.blade.php b/resources/views/companies/show.blade.php new file mode 100644 index 0000000..98e0a17 --- /dev/null +++ b/resources/views/companies/show.blade.php @@ -0,0 +1,5 @@ +Company: {{ $company->name }} + +
+ + diff --git a/routes/web.php b/routes/web.php index ed68b5d..ae781b3 100644 --- a/routes/web.php +++ b/routes/web.php @@ -23,3 +23,7 @@ Route::get('houses/download/{house}', [\App\Http\Controllers\HouseController::cl Route::resource('houses', \App\Http\Controllers\HouseController::class); Route::resource('offices', \App\Http\Controllers\OfficeController::class); + +Route::post('shops', [\App\Http\Controllers\ShopController::class, 'store']); + +Route::resource('companies', \App\Http\Controllers\CompanyController::class); diff --git a/tests/Feature/FileUploadTest.php b/tests/Feature/FileUploadTest.php index 1ccf1cc..956fa01 100644 --- a/tests/Feature/FileUploadTest.php +++ b/tests/Feature/FileUploadTest.php @@ -2,6 +2,7 @@ namespace Tests\Feature; +use App\Models\Company; use App\Models\House; use App\Models\Office; use App\Models\Project; @@ -9,6 +10,7 @@ use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; +use Intervention\Image\Facades\Image; use Tests\TestCase; class FileUploadTest extends TestCase @@ -93,4 +95,35 @@ class FileUploadTest extends TestCase $response->assertStatus(200); $response->assertSee(public_path('offices/' . $filename)); } + + public function test_upload_resize() + { + $filename = Str::random(8) . '.jpg'; + + $response = $this->post('shops', [ + 'name' => 'Some name', + 'photo' => UploadedFile::fake()->image($filename, 1000, 1000) + ]); + $response->assertStatus(200); + + $image = Image::make(storage_path('app/shops/resized-' . $filename)); + $this->assertEquals(500, $image->width()); + $this->assertEquals(500, $image->height()); + } + + public function test_spatie_media_library() + { + $filename = Str::random(8) . '.jpg'; + + $response = $this->post('companies', [ + 'name' => 'Some name', + 'photo' => UploadedFile::fake()->image($filename) + ]); + $response->assertStatus(200); + + $company = Company::first(); + $response = $this->get('companies/' . $company->id); + $response->assertStatus(200); + $response->assertSee('storage/' . $company->id . '/' . $filename); + } }