Files
3dealer/app/Http/Controllers/CustomFieldUploadController.php
T
2026-09-23 17:53:23 +03:00

75 lines
2.6 KiB
PHP

<?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(),
])),
]);
}
}