Photo of Torben Hansen

A TechBlog by Torben Hansen


Freelance Full Stack Web Developer located in Germany.
I create web applications mainly using TYPO3, PHP, Python and JavaScript.
Home Archive Tags

How to manually create the default crop variant string for an imported image in TYPO3 CMS

When data in TYPO3 is created automatically (e.g. through a custom API or by an import script), it is very common, that also new files (especially images) are imported. TYPO3 has the well documented FAL (File Abstraction Layer), which provides an API for common tasks.

One typical task is to import an image to FAL and next creating a file reference for the imported image to a record (e.g. event record of ext:sf_event_mgt). Such a task is easy to implement in a custom extension when you follow the example documentation from the TYPO3 FAL API. This all works fine as described, as long as the referenced image does not use Crop Variants. For image fields, where crop variants are configured, no crop variants will be created for imported images and as a result, TYPO3 will always use the aspect ratio of the imported image no matter which crop variant is configured for output.

TYPO3 internals

Available crop variants for image fields are defined in TCA. When an editor adds an image to a record in the TYPO3 backend, TYPO3 will automatically calculate the default crop variants. The result is saved to the table sys_file_reference in the field crop as a JSON encoded string like the shown example crop variant string below:

{"heroimage":{"cropArea":{"x":0,"y":0.23,"width":1,"height":0.54},"selectedRatio":"16:9","focusArea":null},"teaserimage":{"cropArea":{"x":0,"y":0.14,"width":1,"height":0.72},"selectedRatio":"4:3","focusArea":null}}

This process if performed in ImageManipulationElement. When an editor for example edits a record with an imported image and opens an image inline element, then the ImageManipulationElement is rendered and the default crop variant string is calculated for the imported image and saved, as soon as the editor saves the record.

Manually calculating the default crop variant string

In order to manually calculate the default crop variant string in an image import process, it is required to extract 2 code snippets from the ImageManipulationElement, since both are not public available:

  1. The default crop configuration - see code
  2. The function populateConfiguration - see code

Both is extracted to a class named CropVariantUtility and an additional public function is added which returns the crop variant string for a given file as shown below:

/**
 * Returns a crop variant string to be used in sys_file_reference field "crop" for the given file and table/fieldname
 *
 * @param File $file
 * @param string $tableName
 * @param string $fieldname
 * @return string
 * @throws InvalidConfigurationException
 */
public static function getCropVariantString(File $file, string $tableName, string $fieldname): string
{
    $config = $GLOBALS['TCA'][$tableName]['columns'][$fieldname]['config']['overrideChildTca']['columns']['crop']['config'];
    $cropVariants = self::populateConfiguration($config);
    $cropVariantCollection = CropVariantCollection::create('', $cropVariants['cropVariants']);
    if (!empty($file->getProperty('width'))) {
        $cropVariantCollection = $cropVariantCollection->applyRatioRestrictionToSelectedCropArea($file);
    }

    return (string)$cropVariantCollection;
}

The whole class is available in this gist.

Finally the new CropVariantUtility can be used in a file import routine as shown in the example below:

protected function addFileToEvent(File $file, int $eventUid): void
{
    $eventRecord = BackendUtility::getRecord(self::EVENT_TABLE, $eventUid);

    $fileReferenceUid = StringUtility::getUniqueId('NEW');

    $dataMap = [];
    $dataMap['sys_file_reference'][$fileReferenceUid] = [
        'table_local' => 'sys_file',
        'tablenames' => self::EVENT_TABLE,
        'uid_foreign' => $eventUid,
        'uid_local' => $file->getUid(),
        'fieldname' => 'image',
        'pid' => $eventRecord['pid'],
        'show_in_views' => 0,
        'crop' => CropVariantUtility::getCropVariantString($file, self::EVENT_TABLE, 'image'),
    ];

    $dataMap[self::EVENT_TABLE][$eventUid] = [
        'image' => $fileReferenceUid
    ];

    $this->dataHandler->start($dataMap, []);
    $this->dataHandler->process_datamap();
}

The example code will create a new file reference for the given file object for the table self::EVENT_TABLE ( tx_sfeventmgt_domain_model_event in this case) and the given event UID. The usage of the new CropVariantUtility ensures, that the new file relation has a default crop variant string and configured crop variants can directly be used for imported images.