From 190e55d6ea5b193d8c2a3c2cc9498240787c4859 Mon Sep 17 00:00:00 2001 From: kkamara Date: Tue, 15 Jun 2021 20:05:18 +0100 Subject: [PATCH] Upload product images to aws s3 #49 --- .env.example | 3 + app/Helpers/CommonHelper.php | 16 ++- app/Models/Product/Product.php | 41 ++++++- composer.json | 1 + composer.lock | 206 ++++++++++++++++++++++++++++++++- config/cache.php | 4 + 6 files changed, 264 insertions(+), 7 deletions(-) diff --git a/.env.example b/.env.example index 73ffb60..ea12c7a 100644 --- a/.env.example +++ b/.env.example @@ -38,6 +38,9 @@ MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS=null MAIL_FROM_NAME="${APP_NAME}" +FILESYSTEM_DRIVER=local +AWS_S3_URL= + AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_DEFAULT_REGION=us-east-1 diff --git a/app/Helpers/CommonHelper.php b/app/Helpers/CommonHelper.php index 3c3acea..0bf0aa6 100755 --- a/app/Helpers/CommonHelper.php +++ b/app/Helpers/CommonHelper.php @@ -1,9 +1,21 @@ "Afghanistan", "AX" => "Ă…land Islands","AL" => "Albania","DZ" => "Algeria","AS" => "American Samoa","AD" => "Andorra","AO" => "Angola","AI" => "Anguilla","AQ" => "Antarctica","AG" => "Antigua and Barbuda","AR" => "Argentina","AM" => "Armenia","AW" => "Aruba","AU" => "Australia","AT" => "Austria","AZ" => "Azerbaijan","BS" => "Bahamas","BH" => "Bahrain","BD" => "Bangladesh","BB" => "Barbados","BY" => "Belarus","BE" => "Belgium","BZ" => "Belize","BJ" => "Benin","BM" => "Bermuda","BT" => "Bhutan","BO" => "Bolivia","BA" => "Bosnia and Herzegovina","BW" => "Botswana","BV" => "Bouvet Island","BR" => "Brazil","IO" => "British Indian Ocean Territory","BN" => "Brunei Darussalam","BG" => "Bulgaria","BF" => "Burkina Faso","BI" => "Burundi","KH" => "Cambodia","CM" => "Cameroon","CA" => "Canada","CV" => "Cape Verde","KY" => "Cayman Islands","CF" => "Central African Republic","TD" => "Chad","CL" => "Chile","CN" => "China","CX" => "Christmas Island","CC" => "Cocos (Keeling) Islands","CO" => "Colombia","KM" => "Comoros","CG" => "Congo","CD" => "Congo,The Democratic Republic of The","CK" => "Cook Islands","CR" => "Costa Rica","CI" => "Cote D'ivoire","HR" => "Croatia","CU" => "Cuba","CY" => "Cyprus","CZ" => "Czech Republic","DK" => "Denmark","DJ" => "Djibouti","DM" => "Dominica","DO" => "Dominican Republic","EC" => "Ecuador","EG" => "Egypt","SV" => "El Salvador","GQ" => "Equatorial Guinea","ER" => "Eritrea","EE" => "Estonia","ET" => "Ethiopia","FK" => "Falkland Islands (Malvinas)","FO" => "Faroe Islands","FJ" => "Fiji","FI" => "Finland","FR" => "France","GF" => "French Guiana","PF" => "French Polynesia","TF" => "French Southern Territories","GA" => "Gabon","GM" => "Gambia","GE" => "Georgia","DE" => "Germany","GH" => "Ghana","GI" => "Gibraltar","GR" => "Greece","GL" => "Greenland","GD" => "Grenada","GP" => "Guadeloupe","GU" => "Guam","GT" => "Guatemala","GG" => "Guernsey","GN" => "Guinea","GW" => "Guinea-bissau","GY" => "Guyana","HT" => "Haiti","HM" => "Heard Island and Mcdonald Islands","VA" => "Holy See (Vatican City State)","HN" => "Honduras","HK" => "Hong Kong","HU" => "Hungary","IS" => "Iceland","IN" => "India","ID" => "Indonesia","IR" => "Iran,Islamic Republic of","IQ" => "Iraq","IE" => "Ireland","IM" => "Isle of Man","IL" => "Israel","IT" => "Italy","JM" => "Jamaica","JP" => "Japan","JE" => "Jersey","JO" => "Jordan","KZ" => "Kazakhstan","KE" => "Kenya","KI" => "Kiribati","KP" => "Korea,Democratic People's Republic of","KR" => "Korea,Republic of","KW" => "Kuwait","KG" => "Kyrgyzstan","LA" => "Lao People's Democratic Republic","LV" => "Latvia","LB" => "Lebanon","LS" => "Lesotho","LR" => "Liberia","LY" => "Libyan Arab Jamahiriya","LI" => "Liechtenstein","LT" => "Lithuania","LU" => "Luxembourg","MO" => "Macao","MK" => "Macedonia,The Former Yugoslav Republic of","MG" => "Madagascar","MW" => "Malawi","MY" => "Malaysia","MV" => "Maldives","ML" => "Mali","MT" => "Malta","MH" => "Marshall Islands","MQ" => "Martinique","MR" => "Mauritania","MU" => "Mauritius","YT" => "Mayotte","MX" => "Mexico","FM" => "Micronesia,Federated States of","MD" => "Moldova,Republic of","MC" => "Monaco","MN" => "Mongolia","ME" => "Montenegro","MS" => "Montserrat","MA" => "Morocco","MZ" => "Mozambique","MM" => "Myanmar","NA" => "Namibia","NR" => "Nauru","NP" => "Nepal","NL" => "Netherlands","AN" => "Netherlands Antilles","NC" => "New Caledonia","NZ" => "New Zealand","NI" => "Nicaragua","NE" => "Niger","NG" => "Nigeria","NU" => "Niue","NF" => "Norfolk Island","MP" => "Northern Mariana Islands","NO" => "Norway","OM" => "Oman","PK" => "Pakistan","PW" => "Palau","PS" => "Palestinian Territory,Occupied","PA" => "Panama","PG" => "Papua New Guinea","PY" => "Paraguay","PE" => "Peru","PH" => "Philippines","PN" => "Pitcairn","PL" => "Poland","PT" => "Portugal","PR" => "Puerto Rico","QA" => "Qatar","RE" => "Reunion","RO" => "Romania","RU" => "Russian Federation","RW" => "Rwanda","SH" => "Saint Helena","KN" => "Saint Kitts and Nevis","LC" => "Saint Lucia","PM" => "Saint Pierre and Miquelon","VC" => "Saint Vincent and The Grenadines","WS" => "Samoa","SM" => "San Marino","ST" => "Sao Tome and Principe","SA" => "Saudi Arabia","SN" => "Senegal","RS" => "Serbia","SC" => "Seychelles","SL" => "Sierra Leone","SG" => "Singapore","SK" => "Slovakia","SI" => "Slovenia","SB" => "Solomon Islands","SO" => "Somalia","ZA" => "South Africa","GS" => "South Georgia and The South Sandwich Islands","ES" => "Spain","LK" => "Sri Lanka","SD" => "Sudan","SR" => "Suriname","SJ" => "Svalbard and Jan Mayen","SZ" => "Swaziland","SE" => "Sweden","CH" => "Switzerland","SY" => "Syrian Arab Republic","TW" => "Taiwan,Province of China","TJ" => "Tajikistan","TZ" => "Tanzania,United Republic of","TH" => "Thailand","TL" => "Timor-leste","TG" => "Togo","TK" => "Tokelau","TO" => "Tonga","TT" => "Trinidad and Tobago","TN" => "Tunisia","TR" => "Turkey","TM" => "Turkmenistan","TC" => "Turks and Caicos Islands","TV" => "Tuvalu","UG" => "Uganda","UA" => "Ukraine","AE" => "United Arab Emirates","GB" => "United Kingdom","US" => "United States","UM" => "United States Minor Outlying Islands","UY" => "Uruguay","UZ" => "Uzbekistan","VU" => "Vanuatu","VE" => "Venezuela","VN" => "Viet Nam","VG" => "Virgin Islands,British","VI" => "Virgin Islands,U.S.","WF" => "Wallis and Futuna","EH" => "Western Sahara","YE" => "Yemen","ZM" => "Zambia","ZW" => "Zimbabwe"); -} \ No newline at end of file +} + +/** + * @return bool + */ +function awsCredsExist() { + return isset($_ENV['AWS_ACCESS_KEY_ID']) && + isset($_ENV['AWS_SECRET_ACCESS_KEY']) && + isset($_ENV['AWS_DEFAULT_REGION']) && + isset($_ENV['AWS_BUCKET']); +} diff --git a/app/Models/Product/Product.php b/app/Models/Product/Product.php index 8fcd4a9..abdc6d5 100755 --- a/app/Models/Product/Product.php +++ b/app/Models/Product/Product.php @@ -9,6 +9,7 @@ use App\Models\Product\Traits\ProductRelations; use App\Models\Product\Traits\ProductScopes; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Storage; use Validator; class Product extends Model @@ -47,7 +48,29 @@ public function getPathAttribute() */ public function getImagePathAttribute() { - return $this->attributes['image_path'] ?? '/image/products/default/not-found.jpg'; + $result = '/image/products/default/not-found.jpg'; + + if ( + null !== $this->attributes['image_path'] && + '/image/products/default/not-found.jpg' !== $this->attributes['image_path'] && + true === awsCredsExist() && + true === Storage::disk('s3')->exists($this->attributes['image_path']) + ) { + $result = sprintf( + '%s%s', + $_ENV['AWS_S3_URL'], + str_replace( + '//', + '/', + Storage::path($this->attributes['image_path']) + ), + ); + if (false !== $result) { + return $result; + } + } + + return $result; } /** @@ -144,7 +167,7 @@ public function doesUserOwnProduct() */ public function usingDefaultImage() { - return $this->attributes['image_path'] === NULL; + return $this->attributes['image_path'] === '/image/products/default/not-found.jpg'; } /** @@ -207,6 +230,19 @@ public function uploadImage(Request $request) { $file = $request->file('image'); $imageName = $file->getClientOriginalName(); + /** + * @var string $storagePath + */ + $storagePath = '/uploads/companies/'.$this->company->id.'/images/'; + + if (true === awsCredsExist()) { + /** Note: aws removes the forwarding slash from $storagePath. */ + $result = $file->storePublicly($storagePath, 's3'); + if (false !== $result) { + return $result; + } + } + if ( null === $file || null === $imageName @@ -214,7 +250,6 @@ public function uploadImage(Request $request) { return $result; } - $storagePath = '/uploads/companies/'.$this->company->id.'/images/'; $file->move(public_path($storagePath), $imageName); $result = $storagePath . $imageName; diff --git a/composer.json b/composer.json index a015c76..3dd176a 100644 --- a/composer.json +++ b/composer.json @@ -12,6 +12,7 @@ "guzzlehttp/guzzle": "^7.0.1", "laravel/framework": "^8.40", "laravel/tinker": "^2.5", + "league/flysystem-aws-s3-v3": "~1.0", "spatie/laravel-permission": "^4.0" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 5a2b18c..cc91a01 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": "1990d55f6490603f09a9d25a3c95e056", + "content-hash": "bb1ed95da4913245d33a7f54201d07c7", "packages": [ { "name": "asm89/stack-cors", @@ -62,6 +62,96 @@ }, "time": "2021-03-11T06:42:03+00:00" }, + { + "name": "aws/aws-sdk-php", + "version": "3.184.3", + "source": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-php.git", + "reference": "2e1e8544258ea1a8f6c6ccaf651c8b5830a03a03" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2e1e8544258ea1a8f6c6ccaf651c8b5830a03a03", + "reference": "2e1e8544258ea1a8f6c6ccaf651c8b5830a03a03", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-pcre": "*", + "ext-simplexml": "*", + "guzzlehttp/guzzle": "^5.3.3|^6.2.1|^7.0", + "guzzlehttp/promises": "^1.4.0", + "guzzlehttp/psr7": "^1.7.0", + "mtdowling/jmespath.php": "^2.6", + "php": ">=5.5" + }, + "require-dev": { + "andrewsville/php-token-reflection": "^1.4", + "aws/aws-php-sns-message-validator": "~1.0", + "behat/behat": "~3.0", + "doctrine/cache": "~1.4", + "ext-dom": "*", + "ext-openssl": "*", + "ext-pcntl": "*", + "ext-sockets": "*", + "nette/neon": "^2.3", + "paragonie/random_compat": ">= 2", + "phpunit/phpunit": "^4.8.35|^5.4.3", + "psr/cache": "^1.0", + "psr/simple-cache": "^1.0", + "sebastian/comparator": "^1.2.3" + }, + "suggest": { + "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", + "doctrine/cache": "To use the DoctrineCacheAdapter", + "ext-curl": "To send requests using cURL", + "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", + "ext-sockets": "To use client-side monitoring" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Aws\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Amazon Web Services", + "homepage": "http://aws.amazon.com" + } + ], + "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", + "homepage": "http://aws.amazon.com/sdkforphp", + "keywords": [ + "amazon", + "aws", + "cloud", + "dynamodb", + "ec2", + "glacier", + "s3", + "sdk" + ], + "support": { + "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", + "issues": "https://github.com/aws/aws-sdk-php/issues", + "source": "https://github.com/aws/aws-sdk-php/tree/3.184.3" + }, + "time": "2021-06-14T18:18:58+00:00" + }, { "name": "brick/math", "version": "0.9.2", @@ -1705,6 +1795,57 @@ ], "time": "2020-08-23T07:39:11+00:00" }, + { + "name": "league/flysystem-aws-s3-v3", + "version": "1.0.29", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", + "reference": "4e25cc0582a36a786c31115e419c6e40498f6972" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/4e25cc0582a36a786c31115e419c6e40498f6972", + "reference": "4e25cc0582a36a786c31115e419c6e40498f6972", + "shasum": "" + }, + "require": { + "aws/aws-sdk-php": "^3.20.0", + "league/flysystem": "^1.0.40", + "php": ">=5.5.0" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "~1.0.1", + "phpspec/phpspec": "^2.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Flysystem\\AwsS3v3\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Flysystem adapter for the AWS S3 SDK v3.x", + "support": { + "issues": "https://github.com/thephpleague/flysystem-aws-s3-v3/issues", + "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/1.0.29" + }, + "time": "2020-10-08T18:58:37+00:00" + }, { "name": "league/mime-type-detection", "version": "1.7.0", @@ -1857,6 +1998,67 @@ ], "time": "2020-12-14T13:15:25+00:00" }, + { + "name": "mtdowling/jmespath.php", + "version": "2.6.0", + "source": { + "type": "git", + "url": "https://github.com/jmespath/jmespath.php.git", + "reference": "42dae2cbd13154083ca6d70099692fef8ca84bfb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/42dae2cbd13154083ca6d70099692fef8ca84bfb", + "reference": "42dae2cbd13154083ca6d70099692fef8ca84bfb", + "shasum": "" + }, + "require": { + "php": "^5.4 || ^7.0 || ^8.0", + "symfony/polyfill-mbstring": "^1.17" + }, + "require-dev": { + "composer/xdebug-handler": "^1.4", + "phpunit/phpunit": "^4.8.36 || ^7.5.15" + }, + "bin": [ + "bin/jp.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-4": { + "JmesPath\\": "src/" + }, + "files": [ + "src/JmesPath.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Declaratively specify how to extract elements from a JSON document", + "keywords": [ + "json", + "jsonpath" + ], + "support": { + "issues": "https://github.com/jmespath/jmespath.php/issues", + "source": "https://github.com/jmespath/jmespath.php/tree/2.6.0" + }, + "time": "2020-07-31T21:01:56+00:00" + }, { "name": "nesbot/carbon", "version": "2.48.0", @@ -7971,5 +8173,5 @@ "php": "^7.3|^8.0" }, "platform-dev": [], - "plugin-api-version": "2.0.0" + "plugin-api-version": "2.1.0" } diff --git a/config/cache.php b/config/cache.php index 8736c7a..edd75d5 100644 --- a/config/cache.php +++ b/config/cache.php @@ -92,6 +92,10 @@ 'driver' => 'octane', ], + 's3' => [ + 'driver' => 's3', + ], + ], /*