CoolCMS API

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
bool

isProcessableImageFile()

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
bool

prepareExistingAssets()

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
Return values
string|null
On this page

Search results