ImageFieldsTrait
Product set gallery: the Bazaar uploader (see `AdvertUploaderTrait` / `UploaderDropzone`).
IMPORTANT: the Api contract is unchanged. $meta['images'] is a sorted list of rows
{assetId: int, image?: {name: string, data: string}}
(ProductSetManager::processImages(), assetRels in
defaultSkipFields). collectProductSetImageMeta() translates the uploader output (POST
array uploaderItems[i][type|value] plus dropzone temp files) into that shape.
The uploader runs on dropzone AJAX signals (upload!/remove!) as a standalone request where
editForm and render() are not built. Its configuration (subDir, existing images, token) therefore
lives in ProductSetEdit::createComponentImgUploader(),
which runs on every request, not in addProductSetImageFields().
Table of Contents
Methods
- addProductSetImageFields() : void
- Adds the hidden dropzone temp folder token (on an AJAX re-render after a validation error {@see resolveUploaderToken()} recovers it from the POST) and the form `enctype`; the classic fallback below sends files as multipart even though the dropzone itself uploads through fetch/FormData outside the form.
- cleanupImageUploader() : void
- Deletes the dropzone temp folder after a successful save.
- collectProductSetImageMeta() : array<int, array{assetId: int, image?: array{name: string, data?: string, path?: string}}>
- Builds `$meta['images']`, the sorted gallery rows (unchanged Api contract, see the trait docblock).
- configureImageUploader() : void
- Configures the dropzone uploader; called from the component factory on every request, also on the upload/remove AJAX signals where the rest of the form is not built. Existing images come only from the loaded set (edit); a new set gets an empty dropzone.
- isProcessableImageData() : bool
- Returns whether GD can process the base64 image (non-fatal validation).
- isProcessableImageFile() : bool
- Same check for a file from the dropzone temp folder. Only the `path` reference goes to the Api; the content is read one file at a time and released immediately.
- prepareExistingAssets() : array<int, array{imageId: int, thumbPath: string, isMain: bool, order: int}>
- Returns the existing set images for the dropzone, sorted by `order` (`order === 1` is the main photo, see {@see \App\Core\Base\Shared\Eshop\Models\Entities\ProductSetImageRel::isMain()}).
- resolveUploaderToken() : string|null
- Returns the dropzone temp folder token: null on a fresh GET (the uploader generates one in `configureImageUploader()`), on a POST (submit or validation error) it is read from the hidden field so the same temp folder is reused.
Methods
addProductSetImageFields()
Adds the hidden dropzone temp folder token (on an AJAX re-render after a validation error {@see resolveUploaderToken()} recovers it from the POST) and the form `enctype`; the classic fallback below sends files as multipart even though the dropzone itself uploads through fetch/FormData outside the form.
private
addProductSetImageFields(Form $form) : void
Parameters
- $form : Form
cleanupImageUploader()
Deletes the dropzone temp folder after a successful save.
private
cleanupImageUploader() : void
Call from saveProductSetForm() / saveProductVariantForm() after a successful productSetManager->save().
collectProductSetImageMeta()
Builds `$meta['images']`, the sorted gallery rows (unchanged Api contract, see the trait docblock).
private
collectProductSetImageMeta(ArrayHash<string|int, mixed> $values) : array<int, array{assetId: int, image?: array{name: string, data?: string, path?: string}}>
The dropzone order comes first (uploaderItems: existing assetId and new uploads as a path
reference, global order from the JS reindexing), then the classic fallback (new files from
imagesClassic, appended at the end because the classic input carries no existing images or order).
Parameters
- $values : ArrayHash<string|int, mixed>
Return values
array<int, array{assetId: int, image?: array{name: string, data?: string, path?: string}}>configureImageUploader()
Configures the dropzone uploader; called from the component factory on every request, also on the upload/remove AJAX signals where the rest of the form is not built. Existing images come only from the loaded set (edit); a new set gets an empty dropzone.
private
configureImageUploader(UploaderDropzone $uploader) : void
Parameters
- $uploader : UploaderDropzone
isProcessableImageData()
Returns whether GD can process the base64 image (non-fatal validation).
private
isProcessableImageData(string $base64) : bool
It uses the same library as the Api afterSave (imagecreatefromstring), so what passes here
passes there. An empty, invalid or unprocessable image returns false and
collectProductSetImageMeta() skips it instead of failing the whole variant save.
Parameters
- $base64 : string
Return values
boolisProcessableImageFile()
Same check for a file from the dropzone temp folder. Only the `path` reference goes to the Api; the content is read one file at a time and released immediately.
private
isProcessableImageFile(string $path) : bool
Parameters
- $path : string
Return values
boolprepareExistingAssets()
Returns the existing set images for the dropzone, sorted by `order` (`order === 1` is the main photo, see {@see \App\Core\Base\Shared\Eshop\Models\Entities\ProductSetImageRel::isMain()}).
private
prepareExistingAssets(ProductSet $set) : array<int, array{imageId: int, thumbPath: string, isMain: bool, order: int}>
Parameters
- $set : ProductSet
Return values
array<int, array{imageId: int, thumbPath: string, isMain: bool, order: int}>resolveUploaderToken()
Returns the dropzone temp folder token: null on a fresh GET (the uploader generates one in `configureImageUploader()`), on a POST (submit or validation error) it is read from the hidden field so the same temp folder is reused.
private
resolveUploaderToken() : string|null