Developer manual
Additional columns
checkfaluploads adds two columns to the sys_ table:
cruser_id
checkfaluploads fills this column automatically in TYPO3 backend
context.
fe_cruser_id
This column is filled automatically with the current frontend user, as long as you use TYPO3's official API for FAL files. In any other case, you have to fill it yourself.
FalUploadService
checkfaluploads ships a small API you can use in your own extension to
check whether an uploaded file's user rights checkbox was marked in
frontend context. Add the checkbox to your Fluid template:
Checkbox via Fluid
<f:form.checkbox property="logo.0.rights"
id="logoRights"
class="form-check-input"
value="1" />
Somewhere in your Extbase extension, you should have an UploadTypeConverter. Add the following lines:
if (
ExtensionManagementUtility::isLoaded('checkfaluploads')
&& $error = GeneralUtility::makeInstance(FalUploadService::class)->checkFile($uploadedFile)
) {
return $error;
}
Checkbox via YAML EXT:form
-
label: 'Example image upload'
type: ImageUpload
identifier: image-1
properties:
saveToFileMount: '1:/Extensions/[myExt]'
allowedMimeTypes:
- image/jpg
- image/jpeg
- image/png
elementDescription: 'Select an image'
-
type: Checkbox
identifier: image-1-userrights
label: 'Upload Rights'
properties:
# non-official property. Needed by DynamicUploadValidatorHook. Helps to identify the checkbox
checkboxType: uploadRights
# non-official property. Enter the identifier of the image/file upload
referenceUploadIdentifier: image-1
validators:
# Do not add NotEmpty validator. It will be added dynamically in DynamicUploadValidatorHook
CheckFalUploadValidator
Since TYPO3 13.3, Extbase provides a native API for file upload handling via
the # attribute (see TYPO3 Changelog
Feature-). This attribute does
not support custom validators though, so checkfaluploads ships a
ready-to-use JWeiland
which must be added manually to a property's
TYPO3CMSExtbase. Like any
other file upload validator, it is only ever called by Extbase with an
TYPO3CMSCore instance as the validated value.
As described in the TYPO3 Changelog under "Modifying existing configuration",
this is done in the controller's initialize*Action:
public function initializeCreateAction(): void
{
$validator = $this->validatorResolver->createValidator(
CheckFalUploadValidator::class,
['propertyPath' => 'topic.images'],
$this->request,
);
$argument = $this->arguments->getArgument('topic');
$configuration = $argument->getFileHandlingServiceConfiguration()
->getFileUploadConfigurationForProperty('images');
$configuration?->addValidator($validator);
}
How and where exactly the validator is registered is up to the consuming
extension. initialize*Action is the way shown by the TYPO3 Changelog and
requires no further wiring, but nothing stops you from doing this in a PSR-14
event listener instead, if you prefer to keep your controllers slim.
The $request argument of Validator is
mandatory. It is the only way Check gets access to
the current request, which it needs to resolve the rights configuration -
and the current plugin namespace.
Where "propertyPath" points to, and why it does NOT need the plugin namespace
This is the part most people get wrong on first try, because
$request->get does not return an already-resolved
Extbase argument (as $request->get would). It returns
the raw, unfiltered HTTP POST body, i.e. exactly what PHP's $_
superglobal would contain. Extbase's f: ViewHelper wraps every
field name in the current plugin's namespace (tx_<extension>_<plugin>):
1) Fluid form field, rendered inside <f:form name="topic" ...>:
<f:form.checkbox name="{object}[images][rights]" value="1"/>
2) Extbase prefixes every field name with the plugin namespace
("tx_pforum_forum"), so it ends up here, in the raw and unfiltered
HTTP POST body == $request->getParsedBody():
[
'tx_pforum_forum' => [ // plugin namespace
'topic' => [ // Extbase argument name
'images' => [ // <- "propertyPath" points here,
'rights' => '1', // NOT to "...images.rights"
],
],
],
]
Check resolves the plugin namespace itself, via
TYPO3CMSExtbase
(built as 'tx_' . strtolower), and
prepends it to "propertyPath" before resolving the value:
3) CheckFalUploadValidator reads it back out via:
$propertyPath = str_replace(
'.',
'/',
$pluginNamespace . '.' . $this->options['propertyPath'],
// 'tx_pforum_forum' . 'topic.images'
);
// === 'tx_pforum_forum/topic/images'
ArrayUtility::getValueByPath($parsedBody, $propertyPath)
=== ['rights' => '1']
4) ['rights' => '1'] is passed as $rightsConfiguration into
FalUploadService::checkFile(), which reads
$rightsConfiguration[$fieldName] internally. Pointing "propertyPath"
at "...images.rights" instead would hand over the plain string '1'
rather than an array, and fatal with a TypeError.
Extension developers therefore only ever configure the simple, plugin-agnostic part of the path ("topic.images", "post.images", ...) - the plugin namespace differs per extension/plugin and would otherwise have to be duplicated, error-prone, in every extension using this validator.
Available options
All of the following options are passed as the second argument of
Validator. field, lang and
extension are forwarded 1:1 to the matching parameters of
Fal.
propertyPath - Required. Path in Extbase notation (divided by "."), without the plugin
namespace, pointing to the array that holds the
rightskey, e.g.topic.orimages post.(see above).images fieldName - Optional, default
rights. Key within that array that must be set and not empty for the upload to be allowed. Configurable on purpose: another extension's form might already userightsfor something unrelated at that same array level, so a different name avoids a collision, e.g.['property.Path' => 'topic. images', 'field Name' => 'upload Rights'] langKey - Optional, default
error.. Language key (LLL) of the validation error message shown whenupload File. missing Rights fieldis missing or empty.Name extensionName - Optional, default
checkfaluploads. Extension key used to resolve the language file forlangand the other error messages ofKey Fal.Upload Service:: check File ()
TYPO3's native file upload handling already strips the actual uploaded file
content from the parsed body, so in practice only the small rights array
shown above remains there. Since Extbase supports uploading multiple files
for a single property with <f:, one checkbox is enough to confirm the rights for all
uploaded files at once - no per-file checkbox / index is needed. If rights
is set and not empty, the upload is allowed; otherwise
Fal returns an
TYPO3CMSExtbase, which Check
turns into a validation error via $this->add, so Extbase
actually rejects the upload.
ViewHelpers
ImageRightsMessageViewHelper
This ViewHelper reads the owner property from checkfaluploads extension
settings and inserts it into a localized string. That way you can build a
text like "I give all image rights to jweiland.net".
Declare the ViewHelper namespace in your template first:
<html xmlns:cfu="http://typo3.org/ns/JWeiland/Checkfaluploads/ViewHelpers"
data-namespace-typo3-fluid="true">
Then use the ViewHelper:
<cfu:imageRightsMessage />
Or inline style:
{cfu:imageRightsMessage()}
You can also use your own translation from your own extension. In that
case, make sure your message in locallang. contains the %s
placeholder.
<cfu:imageRightsMessage languageKey="myOwnImageRightsLanguageKey" extensionName="myExtKey" />