generated from boboko/starter
product custom fields
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
/**
|
||||
* Stores the shopper's photo for a product custom field of type `file` (see
|
||||
* boboko-core's Product::$custom_fields) the moment it's picked on the product
|
||||
* page — before add-to-cart, see custom-field-upload-controller.js.
|
||||
*
|
||||
* Which files are acceptable is a per-site decision (this site: photographs),
|
||||
* so it lives here in the storefront, not in the checkout module. The module's
|
||||
* add-to-cart endpoint only ever receives the opaque `reference` returned
|
||||
* below — an encrypted {disk, path, name, mime} payload, so a shopper can
|
||||
* neither forge a reference to some other private file nor read the path —
|
||||
* and copies it onto the cart line's meta (see Checkout\CartController::
|
||||
* customFieldsMeta()).
|
||||
*
|
||||
* Stored on the private `local` disk: these are customers' personal photos,
|
||||
* never reachable by a public URL. Uploads nobody added to a cart are removed
|
||||
* by the custom-fields:prune-uploads command (see PruneCustomFieldUploads).
|
||||
*/
|
||||
class CustomFieldUploadController extends Controller
|
||||
{
|
||||
public const DISK = 'local';
|
||||
|
||||
public const DIRECTORY = 'custom-field-uploads';
|
||||
|
||||
public const MAX_KILOBYTES = 10240;
|
||||
|
||||
public const EXTENSIONS = ['jpg', 'jpeg', 'png', 'webp', 'heic', 'heif'];
|
||||
|
||||
/**
|
||||
* For the file input's `accept` attribute — same list the server enforces.
|
||||
*/
|
||||
public static function accept(): string
|
||||
{
|
||||
return '.'.implode(',.', self::EXTENSIONS);
|
||||
}
|
||||
|
||||
public function store(string $locale, Request $request): JsonResponse
|
||||
{
|
||||
// `label` is the admin-authored field label, only used as the
|
||||
// :attribute in the validation message shown next to that field.
|
||||
$validator = Validator::make(
|
||||
$request->all(),
|
||||
['file' => ['required', 'file', 'mimes:'.implode(',', self::EXTENSIONS), 'max:'.self::MAX_KILOBYTES]],
|
||||
[],
|
||||
['file' => (string) $request->input('label', 'file')],
|
||||
);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json(['error' => $validator->errors()->first('file')], 422);
|
||||
}
|
||||
|
||||
$file = $request->file('file');
|
||||
$path = $file->store(self::DIRECTORY, self::DISK);
|
||||
|
||||
abort_if($path === false, 500);
|
||||
|
||||
return response()->json([
|
||||
'reference' => Crypt::encryptString(json_encode([
|
||||
'disk' => self::DISK,
|
||||
'path' => $path,
|
||||
'name' => $file->getClientOriginalName(),
|
||||
'mime' => $file->getMimeType(),
|
||||
])),
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user