diff --git a/Documentation/7-Controllers/1-Creating-Controllers-and-Actions.rst b/Documentation/7-Controllers/1-Creating-Controllers-and-Actions.rst deleted file mode 100644 index d899821..0000000 --- a/Documentation/7-Controllers/1-Creating-Controllers-and-Actions.rst +++ /dev/null @@ -1,852 +0,0 @@ -.. include:: /Includes.rst.txt -.. index:: - Controllers - Controllers; Actions - -================================ -Creating controllers and actions -================================ - -The controller classes are stored in the folder :file:`EXT:sjr_offer/Classes/Controller/`. The name of the -controller is composed by the name of the domain model and the suffix -:php:`Controller`. So the controller -:php:`\MyVendor\SjrOffers\Controller\OfferController` is assigned -to the Aggregate Root Object -:php:`\MyVendor\SjrOffers\Domain\Model\Offer`. And the name of the -Class file is :file:`OfferController.php`. - -The controller class must extend the class -:php:`\TYPO3\CMS\Extbase\Mvc\Controller\ActionController`, which is -part of Extbase. The individual actions are combined in separate methods. -The method names have to end in :php:`Action`. The body of -:php:`OfferController` thus looks like this: - -.. code-block:: php - :caption: sjr_offers/Classes/Controller/OfferController.php - :name: offer-controller - - offerRepository = $offerRepository; - } - - /** - * Index Action - */ - public function indexAction(): ResponseInterface - { - $offers = $this->offerRepository->findAll(); - $this->view->assign('offers', $offers); - - return $this->htmlResponse(); - } - - -initializeAction -================ - -In old TYPO3 versions the :php:`initializeAction()` was used to get the repository instance. -Later we can use this action to modify the request before the property mapper is executed or -integrate JavaScript libraries. - -The :php:`ActionController` not only calls the method :php:`initializeAction()`, which is executed before any -action in the controller, but also a method in the Form of -:php:`initialize*Foo*Action()`, which is called only before the method -:php:`*foo*Action()`. - -.. tip:: - - The trick of implementing an empty method body in the super - class, which is the "filled" in the subclass is called - *Template Pattern*. - - - -Flow pattern "display a single domain object" -============================================= - -The second pattern is best put into action by a single method as -well. It is called :php:`showAction()`. In contrast to -:php:`indexAction`, this method must be told from -outside which domain object is displayed. In this case the offer to -be shown is passed to the method as argument: - - -.. code-block:: php - :caption: sjr_offers/Classes/Controller/OfferController.php - - /** - * Show action - * - * @param \MyVendor\SjrOffers\Domain\Model\Offer $offer The offer to be shown - * @return ResponseInterface The rendered HTML string - */ - public function showAction(\MyVendor\SjrOffers\Domain\Model\Offer $offer) - { - $this->view->assign('offer', $offer); - return $this->htmlResponse(); - } - -Usually, the display of a single Object is called by a link in the -frontend. In this example extension it connects the list view by something -like the following URL: - -:samp:`https://example.org/index.php?id=123&tx_sjroffers_pi1[offer]=3&tx_sjroffers_pi1[action]=show&tx_sjroffers_pi1[controller]=Offer` - -Due to the 2 Arguments -`tx_sjroffers_pi1[controller]=Offer` and -`tx_sjroffers_pi1[action]=show`, the dispatcher of Extbase -passes the request to the :php:`OfferController`. In the -request we find the information that the action *show* is to be called. Before passing on the further processing to -the method :php:`showAction()`, the controller tries to -map the Arguments received by the URL on the method's arguments. -Extbase maps the arguments by their names. In our example Extbase detects, -that the GET Argument `tx_sjroffers_pi1[offer]=3` corresponds to the method argument -:php:`$offer`: -:php:`showAction(\MyVendor\SjrOffers\Domain\Model\Offer *$offer*)`. -Extbase fetches the type of this Argument from the method signature: -:php:`showAction(*\MyVendor\SjrOffers\Domain\Model\Offer* $offer)`. - -.. deprecated:: 11.3 - Starting with TYPO3 v11.3 omitting the PHP type declaration and only using - the DocBlock annotation :php:`@param` has been deprecated. - -After successfully assigning, the incoming argument's value has -to be cast in the target type and checked for validity (read more -about validation in chapter 9 in the section "Validating domain objects"). In -our case, the incoming value is "3". Target type is the class -:php:`\MyVendor\SjrOffers\Domain\Model\Offer`. So Extbase -interprets the incoming value as uid of the object to be created and sends -a request to the *Storage Backend* to find an Object -with this uid. If the object can be reconstructed fully valid it is passed -to the method as argument. Inside of the method -:php:`showAction()`, the newly created object is passed on -to the view, taking care of the HTML output. - -.. tip:: - - Inside of the template, you can access all properties of the - domain object, including all existing child objects. Thus this Flow - Pattern does not only cover single domain objects but, in the event, - also a complex aggregate. - -If an argument is identified as invalid, the already implemented -method :php:`errorAction()` of -:php:`ActionController` is called instead of the method -:php:`showAction()`. The method then generates a message -for the frontend user and passes the processing to the previous action, in -case it is given. The latter is handy with invalid form field -input, as you'll see in the following. - - -Flow pattern "creating a new domain object" -=========================================== - -For the third Flow Pattern, the one for creating a new Domain -Object, two steps are required: First, a form for inputting the Domain -Data has to be shown in Frontend. Second, a new domain object has to be -created (using the incoming form data) and put in the appropriate -repository. These two steps are implemented in the methods -:php:`newAction() `and -:php:`createAction()`. - -.. tip:: - - These steps are described in chapter 3 in section - "Alternative route: creating a new posting". - -First the method :php:`newAction()` is called by a -link in frontend with the following URL: - -:samp:`https://example.org/index.php?id=123&tx_sjroffers_pi1[organization]=5&tx_sjroffers_pi1[action]=new&tx_sjroffers_pi1[controller]=Offer` - -Extbase instantiates the :php:`Organization `Object -mapped to the Argument :php:`$organization,` just -as it was the case with the :php:`Offer` object in the -method :php:`showAction()`. In the URL, there is no information -(yet), though, which value the Argument :php:`$newOffer` shall have. So the default value -(:php:`=null`) set in the method signature is used. With -these Arguments, the controller passes the further processing to the -method :php:`newAction()`. - - -.. code-block:: php - :caption: sjr_offers/Classes/Controller/OfferController.php - - view->assign('organization', $organization); - $this->view->assign('newOffer', $newOffer); - $this->view->assign('regions', $this->regionRepository->findAll()); - - return $this->htmlResponse(); - } - - // ... - } - -This action passes to the view in :php:`organization` the :php:`Organization` object, in :php:`newOffer` -:php:`null` (to begin with) the and in :php:`region` all :php:`Region` Objects contained in the -:php:`RegionRepository`. The view creates the output of -the form in the frontend, using a template, which has a focus on in chapter 8 in -section "Template Creation by example". After the user filled in the offer's data -and submitted the form, the Method -:php:`createAction()` shall be called. It expects as Arguments -an :php:`Organization` Object and an Object of the class -:php:`\MyVendor\SjrOffers\Domain\Model\Offer`. Therefore Extbase -instantiates the Object and "fills" its Properties with the appropriate -Form data. If all Arguments are valid, the action -:php:`createAction()` is called. - - -.. code-block:: php - :caption: sjr_offers/Classes/Controller/OfferController.php - - // use \MyVendor\SjrOffers\Domain\Model\Organization; - // use \MyVendor\SjrOffers\Domain\Model\Offer - - /** - * @param Organization $organization The organization the offer belongs to - * @param Offer $newOffer A fresh Offer object which has not yet been added to the repository - * @return void - */ - public function createAction(Organization $organization, Offer $newOffer): void - { - $organization->addOffer($newOffer); - $newOffer->setOrganization($organization); - $this->redirect('show', 'Organization', NULL, ['organization' => $organization]); - } - -.. note:: - The redirect methods do not return any response, any method using them should return `void` accordingly. This has been `deprecated in TYPO3v11 `__ and was `dropped in TYPO3v12 where every action must return a response now `__. - -The new offer is allocated to the organization, and inversely the -organization is allocated to the offer. Thanks to this allocation, Extbase -will cause the persistence of the new offer in the dispatcher before -returning to TYPO3. - -After creating the new offer, the appropriate organization is to be -displayed with all of its offers. Therefore a new request is started -(*request-response-cycle*) by redirecting to -:php:`showAction()` of the -:php:`OrganizationController` using the Method -:php:`redirect()`. The actual organization is hereby -passed on as an argument. Inside the -:php:`ActionController` the following methods are at disposal for -redirecting to other action controllers: - - -.. code-block:: php - :caption: sjr_offers/Classes/Controller/OfferController.php - - redirect($actionName, $controllerName = NULL, $extensionName = NULL, - array $arguments = NULL, $pageUid = NULL, $delay = 0, $statusCode = 303) - redirectToURI($uri, $delay = 0, $statusCode = 303) - return new :php:`ForwardResponse('actionName')`; - -Using the :php:`redirect()` method, you can start a - -new request-response-cycle on the spot, similar to clicking on a link: - -#. The destimation action is specified in :php:`$actionName`. -#. The appropriate controller is defined in - :php:`$controllerName`). -#. The extension name is passed over to the method - in :php:`$extensionName`). -#. In the fourth parameter :php:`$arguments` - you can pass an array of arguments. In our example :php:`['organization' => $organization]` - would look like this in the URL: - :php:`tx_sjroffers_pi1[organization]=5`. The array key is - transcribed to the parameter name, while the organization object in - :php:`$organization` is transformed into the number 5, - which is the appropriate UID. -#. If you want to link to another page inside - the TYPO3 installation, you can pass its uid in the 5th parameter - (:php:`$pageUid`). -#. A delay before redirecting can be - achieved by using the 6th parameter (:php:`$delay`). By - default the reason for redirecting is set to status code 303 (which means - *See Other*). -#. You can use the 7th parameter - (:php:`$statusCode`) to override this (for example, with - 301, which means *Moved Permanently*). - -.. tip:: - - If you do not specify a controller or extension, Extbase assumes that you stay in the - same context. - -In this example, the following code is sent to the browser. It -provokes the immediate reload of the page with the given URL: - -.. code-block:: html - :caption: Example frontend output - - - -The method :php:`redirectToURI()` corresponds to the -method :php:`redirect()`, but you can directly set a URL -respectively URI as string, e.g. ``. -With this, you have all the freedom to do what you need. Returning -a :php:`ForwardResponse` object redirects the request -to another action, just as the other two redirect methods do. In -contrast to them, no new request-response cycle is started, though. The -request object is updated with the details concerning the action, -controller and extension. It is then being passed back to the dispatcher for -processing. Then the dispatcher passes on the actual -:php:`Request` object to the appropriate controller. -Here, too, applies: If no controller or extension is set, the actual -context is kept. - -This procedure can be done multiple times when calling a page. The -risk, though, is that the process runs into an infinite loop (A -redirects to B, B redirects to A again). In this case, Extbase stops the -processing after some steps. - -There is another important difference between the redirect methods. Using -the :php:`ForwardResponse()` to redirect, new objects -will not (yet) be persisted to database. They will be persisted at the end -of the request-response-cycle. Therefore no UID has been assigned to a -new object yet, and therefore the transcription to a URL parameter fails. You can -manually trigger the persisting before you return the :php:`ForwardResponse`, -by using :php:`$persistenceManager->persistAll()`, -though. - -When calling the method :php:`createAction(),` the case of all arguments being valid has already been described. -But what happens if a frontend user inserts invalid data or even manipulates the form to -attack the website deliberately? - -.. tip:: - - You find detailed information about validation and security in - chapter 9 - -Fluid adds multiple hidden fields to the form generated by the -Method :php:`newAction()`. These contain information about -the origin of the form (:php:`__referrer`) as well as, in -encrypted form (:php:`__trustedProperties`), the structure of the form -(shorted in the example below). - -.. code-block:: html - :caption: Example frontend output - - - - - - -If now a validation error occurs when calling the method -:php:`createAction()`, an error message is saved and the -processing is passed back to the previous action, including all already -inserted form data. Extbase reads the necessary information from the -hidden fields :php:`__referrer`. In our case the Method -:php:`newAction()` is called again. In contrast to the -first call, Extbase now tries to create an (invalid) -:php:`Offer` Object from the form data and pass it to -the Method in :php:`$newOffer`. Due to the annotation -:php:`@Extbase\IgnoreValidation("newOffer")` Extbase this time accepts -the invalid object and displays the form once more. Formerly filled in -data is put in the fields again, and the previously saved error message is -displayed if the template is intending so. - -.. figure:: /Images/ManualScreenshots/7-Controllers/figure-7-1.png - :align: center - - Figure 7-1: Wrong input in the form of an offer leads to an error message - (in this case, a modal JavaScript window) - -.. tip:: - - Standard error messages of Extbase are not yet localized in - Version 1.2 (TYPO3 v4.4). In the section "Localize error messages" in chapter 8 - a possibility is described how to translate them. - -Using the hidden field :php:`__trustedProperties`, the Extbase property -mapper compares the incoming property data with the allowed ones. -If the request contains data for non-whitelisted properties, the property -mapper throws an exception. - -Using the :php:`\TYPO3\CMS\Extbase\Annotation\IgnoreValidation("parameterName")` annotation, -you tell Extbase that the argument is not to be validated. If the argument is an Object, the -validation of its properties is also bypassed. - - -Flow pattern "editing an existing domain object" -================================================ - -The flow pattern presented to you is quite similar to the -previous one. Aain need two action methods are neede, which this time call -:php:`editAction()` and -:php:`updateAction()`. The method -:php:`editAction()` provides the form for editing, while -:php:`updateAction()` updates the object in the -repository. In contrast to :php:`newAction()` it is not -necessary to pass an organization to the method -:php:`editAction()`. It is sufficient to pass the offer to -be edited as an argument. - -.. code-block:: php - :caption: sjr_offers/Classes/Controller/OfferController.php - - view->assign('offer', $offer); - $this->view->assign('regions', $this->regionRepository->findAll()); - - return $this->htmlResponse(); - } - - // ... - } - -Note once again the annotation :php:`@Extbase\IgnoreValidation("offer")`. -The Method :php:`updateAction()` -receives the changed offer and updates it in the repository. Afterward, a -new request is started, and the organization is shown with its updated -offers. - -.. code-block:: php - :caption: sjr_offers/Classes/Controller/OfferController.php - - // use \MyVendor\SjrOffers\Domain\Model\Offer; - - /** - * @param Offer $offer The modified offer - * @return ResponseInterface - */ - public function updateAction(Offer $offer) : ResponseInterface - { - $this->offerRepository->update($offer); - return $this->redirect('show', 'Organization', NULL, ['organization' => $offer->getOrganization()]); - } - -.. warning:: - Do not forget to explicitly update the changed domain object - using :php:`update()`. Extbase will not do this - automatically for you. Not doing so could lead to unexpected results. - For example, if you have to manipulate the incoming domain object - inside your action method. - -At this point it is necessary to prevent -unauthorized changes in the domain data. The organization and offer data -are not to be changed by all visitors after all. An -*administrator* is allocated to each organization, -authorized to change the organization's data. The administrator can -change the organization's contact data, create and delete offers, and -contact persons as well as edit existing offers. Securing against -unauthorized access can be done on different levels: - -* On the level of TYPO3, access to the page and/or plugin is prohibited. -* Inside the action, it is checked if access is authorized. In - our case, it has to be checked if the administrator of the - organization is logged in. -* In the template, links to Actions, to which the frontend user - has no access, are blinded. - -Of these three levels, only the first two offer reliable -protection. The first level is not described in this book. -You can find detailed information for setting up permissions in -your TYPO3 system in the :ref:`Core API `. -The second levelis implemented here in all "critical" actions. -Let's look at an example with the Method -:php:`updateAction()`. - - -.. code-block:: php - :caption: sjr_offers/Classes/Controller/OfferController.php - - use TYPO3\CMS\Core\Utility\GeneralUtility; - use \MyVendor\SjrOffers\Service\AccessControlService; - - public function initializeAction() - { - $this->accessControlService = GeneralUtility::makeInstance(AccessControlService::class); - } - - public function updateAction(\MyVendor\SjrOffers\Domain\Model\Offer $offer) - { - $administrator = $offer->getOrganization()->getAdministrator(); - if ($this->accessControlService->isLoggedIn($administrator)) { - $this->offerRepository->update($offer); - } else { - $this->flashMessages->add('Please sign in.'); - } - return $this->redirect('show', 'Organization', NULL, ['organization' => $offer->getOrganization()]); - } - -A previously instantiated -:php:`AccessControlService` is asked if the organization's administrator is -responsible for the offer is logged in the frontend. If yes, do update the offer. -If no, an error message is generated, which is -displayed in the subsequently called organization overview. - -Extbase does not yet offer an API for access control. Therefore -an :php:`AccessControlService` is implemented. -The description of the class is to be found in the file -:file:`EXT:sjr_offers/Classes/Service/AccessControlService.php`. - - -.. code-block:: php - :caption: EXT:sjr_offers/Classes/Service/AccessControlService.php - - getUid() === $this->getFrontendUserUid()) { - return TRUE; - } - } - return FALSE; - } - - public function getFrontendUserUid() - { - if($this->hasLoggedInFrontendUser() && !empty($GLOBALS['TSFE']->fe_user-> - user['uid'])) { - return intval($GLOBALS['TSFE']->fe_user->user['uid']); - } - return NULL; - } - - public function hasLoggedInFrontendUser() - { - return $GLOBALS['TSFE']->loginUser === 1 ? TRUE : FALSE; - } - - } - -The third level can easily be bypassed by manually typing the link -or the form data. It, therefore, only reduces the confusion for honest -visitors and the stimulus for the bad ones. Let's take a short look at -this snippet from a template: - - -.. code-block:: html - :caption: EXT:sjr_offers/Resources/Private/Templates/SomeTemplate.html - - {namespace sjr=MyVendor\SjrOffers\ViewHelpers} - - - - - - - - -.. tip:: - - A *Service* is often used to implement - functionalities that are needed in multiple places in your extensions - and are not related to one domain object. - - Services are often stateless. In this context, that means that - their function does not depend on previous access. This does not - rule out the dependency on the "environment". In our example, you can be - sure, that a verification by :php:`isLoggedIn()` - always leads to the same result, regardless of any earlier - verification - given that the "environment" has not changed - (considerably), e.g., by the Administrator logging out or even losing - his access rights. - - Services usually can be built as *Singleton* - (:php:`implements t3lib_Singleton`). You can find - detailed information on *Singleton* in chapter 2 in - section "Singleton". - - The :php:`AccessControlService` is not part of - the Domain of our extension. It "belongs" to the Domain of the Content - Management System. There are Domain Services also, of course, like a - Service creating a continuous invoice number. They are usually located - in `EXT:my_ext/Classes/Domain/Service/`. - -It is made use of an :php:`IfAuthenticatedViewHelper` -to access the :php:`AccessControlService`. The class file -`IfAuthenticatedViewHelper.php` is in our case -located in :file:`EXT:sjr_offers/Classes/ViewHelpers/Security/`. - -.. code-block:: php - :caption: sjr_offers/Classes/ViewHelpers/Security/IfAuthenticatedViewHelper.php - - namespace MyVendor\SjrOffers\ViewHelper\Security; - - use MyVendor\SjrOffers\Service\AccessControlService; - use TYPO3Fluid\Fluid\ViewHelpers\IfViewHelper; - use TYPO3\CMS\Core\Utility\GeneralUtility; - - class IfAuthenticatedViewHelper extends IfViewHelper - { - /** - * @param mixed $person The person to be tested for login - * @return string The output - */ - public function render(mixed $person = NULL) - { - $accessControlService = GeneralUtility::makeInstance(AccessControlService::class); - if ($accessControlService->isLoggedIn($person)) { - return $this->renderThenChild(); - } else { - return $this->renderElseChild(); - } - } - - } - -The :php:`IfAuthenticatedViewHelper` extends the -:php:`If`-ViewHelper of Fluid and therefore provides the -opportunity to use if-else branches. It delegates the access check to the -:php:`AccessControlService`. If the check gives a positive -result, in our case, a link with an edit icon is generated, which leads to -the method :php:`editAction()` of the -:php:`OfferController`. - - -Flow pattern "deleting a domain object" -======================================= - -The last flow pattern realizes the deletion of an existing domain -Object in one single action. The appropriate Method -:php:`deleteAction()` is kind of straightforward: - -.. code-block:: php - :caption: sjr_offers/Classes/Controller/OfferController.php - - // use \MyVendor\SjrOffers\Domain\Model\Offer - - /** - * @param Offer $offer The offer to be deleted - * @return ResponseInterface - */ - public function deleteAction(Offer $offer) : ResponseInterface - { - $administrator = $offer->getOrganization()->getAdministrator(); - if ($this->accessControlService->isLoggedIn($administrator)) { - $this->offerRepository->remove($offer); - } else { - $this->flashMessages->add('Please sign in.'); - } - return $this->redirect('show', 'Organization', NULL, ['organization' => $offer->getOrganization()]); - } - -The important thing here is that you delete the given Offer from the -repository using the method :php:`remove()`. After running -through your extension, Extbase will delete the associated record from -the Database by marking it as deleted. - -.. tip:: - - In principle, it doesn't matter how you generate the result - (usually HTML code) inside the action. You can even decide to use the - traditional way of building extensions in your action - with SQL - Queries and maker-based Templating. We invite you to pursue the path - we chose up till now, though. - -The flow patterns we present here are meant to be blueprints for -your own flows. In real-life projects, they may get way more complex. The -Method :php:`indexAction()` of the -:php:`OfferController` looks like this in it's "final -stage": - -.. code-block:: php - :caption: sjr_offers/Classes/Controller/OfferController.php - - // use \MyVendor\SjrOffers\Domain\Model\Demand; - - /** - * @param Demand $demand A demand (filter) - * @return ResponseInterface - */ - public function indexAction(Demand $demand = NULL): ResponseInterface - { - $allowedStates = (strlen($this->settings['allowedStates']) > 0) ? - t3lib_div::intExplode(',', $this->settings['allowedStates']) : []; - $listCategories = (strlen($this->settings['listCategories']) > 0) ? - t3lib_div::intExplode(',', $this->settings['listCategories']) : []; - $selectableCategories = (strlen($this->settings['selectableCategories']) > 0) ? - t3lib_div::intExplode(',', $this->settings['selectableCategories']) : []; - $propertiesToSearch = (strlen($this->settings['propertiesToSearch']) > 0) ? - t3lib_div::trimExplode(',', $this->settings['propertiesToSearch']) : []; - - $this->view->assign('offers', - $this->offerRepository->findDemanded( - $demand, - $propertiesToSearch, - $listCategories, - $allowedStates - ) - ); - $this->view->assign('demand', $demand); - $this->view->assign('organizations', - array_merge( - [0 => 'All Organisations'], - $this->organizationRepository->findByStates($allowedStates) - ) - ); - $this->view->assign('categories', - array_merge( - [0 => 'All Categories'], - $this->categoryRepository->findSelectableCategories($selectableCategories) - ) - ); - $this->view->assign('regions', - array_merge( - [0 => 'All Districts'], - $this->regionRepository->findAll() - ) - ); - - return $this->htmlResponse(); - } - -In the script's first few lines, configuration options, set in -the TypoScript template as a comma-separated list, are transcribed to -arrays. Then this information is passed to the *View* -piece by piece. - -One requirement our extension has to realize is that a website visitor -can define a special demand, which is then used to filter the -range of offers. An appropriate Method -:php:`findDemanded()` has already been implemented (see :ref:`chapter 6 `). -To define his demand, the visitor chooses -the accordant options in a form (see pic. 7-2). - -.. figure:: /Images/ManualScreenshots/Frontend/7-Controllers/figure-7-2.png - :align: center - - Figure 7-2: The buildup of the "demand" in a form above the offer list. - -.. warning:: - Watch out that you do not implement logic, which - belongs in the controller domain. Concentrate on the - mere Flow. - -.. tip:: - - In real life, you will often need similar functionality in some - or even all controllers. The previously mentioned access control is a - simple example. In the example extension it is sourced out to a - *service* object. Another possibility is to create - a basis controller which extends the - :php:`ActionController` of Extbase. Inside, you - implement the shared functionality. Then the concrete controllers with - your Actions extend this Basis controller again. - -The Flow inside of a controller is triggered from outside by -TYPO3. For extensions that generate content for the frontend, this is -usually done by a plugin placed on the appropriate page. How to configure -such a plugin you'll see in the following section. diff --git a/Documentation/7-Controllers/2-Configuring-and-embedding-Frontend-Plugins.rst b/Documentation/7-Controllers/2-Configuring-and-embedding-Frontend-Plugins.rst deleted file mode 100644 index 9368a8d..0000000 --- a/Documentation/7-Controllers/2-Configuring-and-embedding-Frontend-Plugins.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. include:: /Includes.rst.txt -.. index:: - Frontend plugins - Plugins - -========================================== -Configuring and embedding frontend plugins -========================================== - -This content was updated and moved. Please see -:ref:`t3coreapi:extbase_registration_of_frontend_plugins`. diff --git a/Documentation/7-Controllers/3-Configuring-the-behavior-of-the-extension.rst b/Documentation/7-Controllers/3-Configuring-the-behavior-of-the-extension.rst deleted file mode 100644 index a535222..0000000 --- a/Documentation/7-Controllers/3-Configuring-the-behavior-of-the-extension.rst +++ /dev/null @@ -1,68 +0,0 @@ -.. include:: /Includes.rst.txt - -========================================= -Configuring the behavior of the extension -========================================= - -Not all organizations are to be displayed in our example extensions, -but just the ones belonging to a certain status (like, e.g., internal, -external, non-member). In the TypoScript template of our page, we therefore -establish an option `allowedStates` under the path -`tx_sjroffers.settings`: - -.. code-block:: typoscript - :caption: EXT:sjr_offers/Configuration/TypoScript/setup.typoscript - - plugin.tx_sjroffers { - settings { - allowedStates = 1,2 - } - } - -Extbase makes the settings inside of the path -:php:`plugin.tx_sjroffers.settings` available as an array in -the class variable :php:`$this->settings`. Our action -thus looks like this: - - -.. code-block:: php - :caption: EXT:sjr_offers/Classes/Controller/OrganizationController.php - - use TYPO3\CMS\Core\Utility\GeneralUtility; - - public function indexAction(): ResponseInterface - { - $this->view->assign( - 'organizations', - $this->organizationRepository->findByStates( - GeneralUtility::intExplode(',', $this->settings['allowedStates']) - ) - ); - - // ... - } - -In the :php:`OrganizationRepository`, we implemented a -Method :php:`findByStates()`, which we do not further -investigate here (see more in chapter 6, section "Implement individual -database queries"). The method expects an array containing the allowed -states. We generate it from the comma-separated list using the TYPO3 API -function :php:`\TYPO3\CMS\Core\Utility\GeneralUtility::intExplode()`. -We then pass on the returned choice of organizations to the view, just as -we are used to doing. - -.. tip:: - - Of course, we could also have passed the comma-separated list - directly to the Method :php:`findByStates()`. We do - recommend, though, to prepare all parameter coming from outside - (settings, form input) before passing them on to the two other - components Model and View. - -In this chapter, you've learned how to set the Objects of your domain -in motion and how to control the flow of a page visit. You now can -realize the two components *model* and -*Controller* of the MVC paradigm inside your extension. -In the following chapter, we will address the third component, the -*View*. We'll present the substantial scope of the -template engine Fluid. diff --git a/Documentation/7-Controllers/Index.rst b/Documentation/7-Controllers/Index.rst deleted file mode 100644 index 9355cf4..0000000 --- a/Documentation/7-Controllers/Index.rst +++ /dev/null @@ -1,75 +0,0 @@ -.. include:: /Includes.rst.txt -.. _controlling-the-flow-with-controllers: -.. _controllers: - -===================================== -Controlling the flow with controllers -===================================== - -In the previous chapters, we already transcribed the Domain of our -example extension *SJROffers* to a software-based domain -model. This leads to multiple files with class definitions in -the extension subfolder :file:`sjr_offers/Classes/Domain/Model/`. Furthermore, we -set up the persistence layer. As a result, we are already able to deposit -our domain's data in the form of domain Objects and retrieve it -again. - -In this chapter, you'll see how to control the flow inside of your -extension. The bottom line is to evaluate requests of the website user, in -order to trigger the appropriate action. Regarding our example extension -*SJROffers*, it may make sense to show a list of all -offers or to give out all relevant information to one offer. Further -examples of actions are: - -* Deleting a specific offer -* Deleting all offers of one organization -* Displaying a form to change the data of an offer -* Updating an offer -* Listing the newest offers - -The code for receiving the request and for executing the -appropriate action is combined in controllers. A controller is a component -of the model-view-controller architecture, of which the basics are described -in chapter 2, section "model-view-controller in Extbase". The operation of a -Controller interconnected with the other components is described in chapter -3. - -A controller is an object of an extension, which is instantiated and -called inside of Extbase by the :php:`Dispatcher` object. -The controller takes care of the complete flow inside of the extension. It -is the link between the :php:`Request`, the domain model, and the reaction in the form -of the :php:`Response`. Inside of the *controller*, the data -necessary for the flow is fetched from the respective repositories, prepared -according to the demand from outside, and passed to the code responsible for -the output (*View*). Besides this main task, a controller -is responsible for: - -* accepting the :php:`Request` object, respectively rejecting it, - in case it cannot be processed. -* inducing a check of the data coming in from the URL (especially - from links) or the Frontend forms. This data has to be checked for - type and validity. -* checking which method (*Action*) of the - controller shall be called for further processing. -* preparing the incoming data so that it can be passed to the method - in charge (*Argument Mapping*) -* initiating the rendering process. -* creating the :php:`Response` object. - -In the following section, we'll create the necessary -Controller Classes of our extension and therein implement the adequate -*Action* methods. For this, we'll first have to decide -which Actions have to be implemented. For an extension usually needs -multiple different Actions, we'll group them in different controller -Classes. A very "natural" way of grouping would be: Every Aggregate Root -Class, containing objects on which an action shall be applied, is -administered by a proper controller. In our case, the two classes -:php:`Organization` and :php:`Offer` are -indicated. Now let's start with our first controller. - -.. toctree:: - :hidden: - - 1-Creating-Controllers-and-Actions - 2-Configuring-and-embedding-Frontend-Plugins - 3-Configuring-the-behavior-of-the-extension diff --git a/Documentation/Index.rst b/Documentation/Index.rst index dbc7d43..17209d1 100644 --- a/Documentation/Index.rst +++ b/Documentation/Index.rst @@ -46,7 +46,6 @@ Developing TYPO3 Extensions with Extbase and Fluid 5-Domain/Index 6-Persistence/Index - 7-Controllers/Index 8-Fluid/Index .. toctree::