Project

General

Profile

Actions

Feature #104763

open

Allow Models used in Request Validation to be XClass overridden

Added by Jannis Bell 3 months ago. Updated 3 months ago.

Status:
Needs Feedback
Priority:
Should have
Assignee:
-
Category:
Extbase
Target version:
-
Start date:
2024-08-28
Due date:
% Done:

0%

Estimated time:
PHP Version:
Tags:
Complexity:
medium
Sprint Focus:

Description

My Company uses a self-developed extension for some forms.
We use the Request Argument Objects extensively.
And we have to overwrite and adapt the forms constantly for our customers.
Specifically the Validators are impossible to change:

class BaseInquiry {
    /** @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty") */
    protected string $inquiry = '';
    protected string $message = '';
}

class OverriderInquiry extends BaseInquiry {
    protected string $inquiry = '';
    /** @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty") */
    protected string $message = '';
}

class InquiryController extends ActionController {
    public function processAction(BaseInquiry $inquiry = NULL): ResponseInterface
    // a OverriderInquiry arrives here
    // but is validated for a BaseInquiry

//localconf
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][BaseInquiry::class] = ['className' => OverriderInquiry::class];

Expected: Validates $message for NotEmpty and does not validate $inquiry
Reality: Validates $inquiry for NotEmpty and does not validate $message

This would be my patch to fix this:
https://github.com/TYPO3/typo3/blob/main/typo3/sysext/extbase/Classes/Mvc/Controller/ActionController.php#L238

    protected function initializeActionMethodArguments(): void
    {
        $methodParameters = $this->reflectionService
            ->getClassSchema(static::class)
            ->getMethod($this->actionMethodName)->getParameters();

        foreach ($methodParameters as $parameterName => $parameter) {
            $dataType = null;
            if ($parameter->getType() !== null) {
                $dataType = $parameter->getType();
                /** This is the new part:*/
                // this can overwrite the Datatype aka Classname to match the given XClass counterpart
                if (array_key_exists($dataType, $GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'])) {
                    $dataType = $GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][$dataType]['className'];
                }
                /** end of the new part */
            } elseif ($parameter->isArray()) {
                $dataType = 'array';
            }
            if ($dataType === null) {
                throw new InvalidArgumentTypeException('The argument type for parameter $' . $parameterName . ' of method ' . static::class . '->' . $this->actionMethodName . '() could not be detected.', 1253175643);
            }
            $defaultValue = $parameter->hasDefaultValue() ? $parameter->getDefaultValue() : null;
            $this->arguments->addNewArgument($parameterName, $dataType, !$parameter->isOptional(), $defaultValue);
        }
    }

I am not sure about the code standards in the core:
Im not sure if you rather use isset() than array_key_exists()
Or if the XClass has no 'classname', if the core should crash or warn or cover this

Also im sry if this is very gibberish and poorly explained

Actions #1

Updated by Jannis Bell 3 months ago

  • Description updated (diff)

more Context for visualitzation

Actions #2

Updated by Garvin Hicking 3 months ago

  • Status changed from New to Needs Feedback

I am not sure I properly understand your scenario, maybe more code examples could help.

Generally you should be able to use XCLasses on domain models, see https://www.derhansen.de/2019/03/extending-extbase-domain-models-and.html and https://github.com/derhansen/sf_event_mgt_extend_demo for example.

Or do you use one central processAction for different kinds of models, and want the same action to be able to handle different kinds of $inquiry objects? In that case I would suggest to actually create individual actions like processInquiryAction, processOtherInquieryAction, processSomeOtherInquiryTooAction, do your validation there, and then use services or abstract methods to do the processing that every action has in common; this would be way cleaner to manage in the future and has less "magic" going on.

But I might not properly understand this, so a basic extbase example of what you do could help me and others to understand

Adding the patch like suggested at this place is IMO a bit "too soon" to involve this kind of magic, because it could influence TypeConverter functionality and make it harder to maintain all of the complex 'extbase magic'. I do hope that it shouldn't be needed, if some design decisions can be revisited in your implementation.

Actions #3

Updated by Jannis Bell 3 months ago

  • Subject changed from Allow Models used in Requests to be XClass overridden to Allow Models used in Request Validation to be XClass overridden
  • Description updated (diff)

Better explanation, hopefully

Actions

Also available in: Atom PDF