diff --git a/CodeExamples/localPackages/example_extension/Classes/Controller/AddressController.php b/CodeExamples/localPackages/example_extension/Classes/Controller/AddressController.php
new file mode 100644
index 0000000..f63f311
--- /dev/null
+++ b/CodeExamples/localPackages/example_extension/Classes/Controller/AddressController.php
@@ -0,0 +1,60 @@
+
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
+use Workshop\ExampleExtension\Domain\Model\Address;
+use Workshop\ExampleExtension\Domain\Repository\AddressRepository;
+
+class AddressController extends ActionController
+{
+ /**
+ * @var AddressRepository
+ */
+ protected $addressRepository;
+
+ public function __construct(AddressRepository $addressRepository)
+ {
+ $this->addressRepository = $addressRepository;
+ }
+
+ public function indexAction()
+ {
+ $this->view->assign('addresses', $this->addressRepository->findAll());
+ }
+
+ public function editAction(Address $address)
+ {
+ $this->view->assign('address', $address);
+ }
+
+ public function updateAction(Address $address)
+ {
+ $this->addressRepository->update($address);
+
+ $this->addFlashMessage(
+ $address->getCompanyName() . ' was updated.',
+ 'Update successfully'
+ );
+ $this->redirect('index');
+ }
+}
diff --git a/CodeExamples/localPackages/example_extension/Classes/Domain/Model/Address.php b/CodeExamples/localPackages/example_extension/Classes/Domain/Model/Address.php
index 304206d..dd439b8 100644
--- a/CodeExamples/localPackages/example_extension/Classes/Domain/Model/Address.php
+++ b/CodeExamples/localPackages/example_extension/Classes/Domain/Model/Address.php
@@ -55,31 +55,61 @@ class Address extends AbstractEntity
*/
protected $country;
+ public function setCompanyName(string $companyName)
+ {
+ $this->companyName = $companyName;
+ }
+
public function getCompanyName(): string
{
return $this->companyName;
}
+ public function setStreet(string $street)
+ {
+ $this->street = $street;
+ }
+
public function getStreet(): string
{
return $this->street;
}
+ public function setHouseNumber(string $houseNumber)
+ {
+ $this->houseNumber = $houseNumber;
+ }
+
public function getHouseNumber(): string
{
return $this->houseNumber;
}
+ public function setZip(string $zip)
+ {
+ $this->zip = $zip;
+ }
+
public function getZip(): string
{
return $this->zip;
}
+ public function setCity(string $city)
+ {
+ $this->city = $city;
+ }
+
public function getCity(): string
{
return $this->city;
}
+ public function setCountry(string $country)
+ {
+ $this->country = $country;
+ }
+
public function getCountry(): string
{
return $this->country;
diff --git a/CodeExamples/localPackages/example_extension/Configuration/TCA/Overrides/tt_content.php b/CodeExamples/localPackages/example_extension/Configuration/TCA/Overrides/tt_content.php
index bca38a0..529b61a 100644
--- a/CodeExamples/localPackages/example_extension/Configuration/TCA/Overrides/tt_content.php
+++ b/CodeExamples/localPackages/example_extension/Configuration/TCA/Overrides/tt_content.php
@@ -6,4 +6,9 @@
'pluginkey',
'Example Plugin'
);
+ \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
+ 'Workshop.ExampleExtension',
+ 'Address',
+ 'Address Plugin'
+ );
})();
diff --git a/CodeExamples/localPackages/example_extension/Resources/Private/Language/locallang.xlf b/CodeExamples/localPackages/example_extension/Resources/Private/Language/locallang.xlf
new file mode 100644
index 0000000..e69f7d0
--- /dev/null
+++ b/CodeExamples/localPackages/example_extension/Resources/Private/Language/locallang.xlf
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CodeExamples/localPackages/example_extension/Resources/Private/Templates/Address/Edit.html b/CodeExamples/localPackages/example_extension/Resources/Private/Templates/Address/Edit.html
new file mode 100644
index 0000000..c26a48f
--- /dev/null
+++ b/CodeExamples/localPackages/example_extension/Resources/Private/Templates/Address/Edit.html
@@ -0,0 +1,24 @@
+
+
+ {address.street} {address.houseNumber}
+ {address.zip} {address.city}
+ {address.country}
+
+
+ Edit
+
diff --git a/CodeExamples/localPackages/example_extension/ext_localconf.php b/CodeExamples/localPackages/example_extension/ext_localconf.php
index 13dcce3..cd5656e 100644
--- a/CodeExamples/localPackages/example_extension/ext_localconf.php
+++ b/CodeExamples/localPackages/example_extension/ext_localconf.php
@@ -8,4 +8,15 @@
'Example' => 'example'
]
);
+
+ \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
+ 'Workshop.ExampleExtension',
+ 'Address',
+ [
+ 'Address' => 'index, edit, update'
+ ],
+ [
+ 'Address' => 'update'
+ ]
+ );
})();
diff --git a/Documentation/source/AddFirstPlugin.rst b/Documentation/source/AddFirstPlugin.rst
index b6130b4..9cf8c87 100644
--- a/Documentation/source/AddFirstPlugin.rst
+++ b/Documentation/source/AddFirstPlugin.rst
@@ -31,8 +31,15 @@ available as a new option for the content element *Insert Plugin*.
This is done with the following code in file
:file:`Configuration/TCA/Overrides/tt_content.php`:
-.. literalinclude:: ../../CodeExamples/localPackages/example_extension/Configuration/TCA/Overrides/tt_content.php
- :language: php
+.. code-block:: php
+
+ (function () {
+ \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
+ 'Workshop.ExampleExtension',
+ 'pluginkey',
+ 'Example Plugin'
+ );
+ })();
Configure Plugin for Frontend
-----------------------------
@@ -44,8 +51,18 @@ Configure Plugin for Frontend
To actually call some PHP Code when the content element is rendered, we need to
configure the plugin in :file:`ext_localconf.php`:
-.. literalinclude:: ../../CodeExamples/localPackages/example_extension/ext_localconf.php
- :language: php
+.. code-block:: php
+
+ (function () {
+ \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
+ 'Workshop.ExampleExtension',
+ 'pluginkey',
+ [
+ 'Example' => 'example'
+ ]
+ );
+ })();
+
Write necessary Code
--------------------
diff --git a/Documentation/source/CustomRecords.rst b/Documentation/source/CustomRecords.rst
index 32645f6..061aa31 100644
--- a/Documentation/source/CustomRecords.rst
+++ b/Documentation/source/CustomRecords.rst
@@ -90,7 +90,7 @@ Each model is a PHP class structure like:
.. literalinclude:: ../../CodeExamples/localPackages/example_extension/Classes/Domain/Model/Address.php
:language: php
:linenos:
- :lines: 1-4,24-32,58-61,87
+ :lines: 1-4,24-32,63-66,87
Repository
----------
@@ -121,24 +121,10 @@ Controller
In order to provide records in form of models to our template, we first need an
instance of our repository:
-.. code-block:: php
+.. literalinclude:: ../../CodeExamples/localPackages/example_extension/Classes/Controller/AddressController.php
+ :language: php
:linenos:
-
- use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
- use Workshop\ExampleExtension\Domain\Repository\AddressRepository;
-
- class ExampleController extends ActionController
- {
- /**
- * @var AddressRepository
- */
- protected $addressRepository;
-
- public function __construct(AddressRepository $addressRepository)
- {
- $this->addressRepository = $addressRepository;
- }
- }
+ :lines: 1-4, 24-38,66
With the above code we only can create instances of the controller if an instance of
the Repository is provided.
@@ -151,16 +137,10 @@ work in other PHP Frameworks and without any Dependency Injection at all.
We then can call the accordingly method to fetch records, which then can be assigned
to the view:
-.. code-block:: php
+.. literalinclude:: ../../CodeExamples/localPackages/example_extension/Classes/Controller/AddressController.php
+ :language: php
:linenos:
-
- class ExampleController extends ActionController
- {
- public function exampleAction()
- {
- $this->view->assign('addresses', $this->addressRepository->findAll());
- }
- }
+ :lines: 28-29,40-43,66
The ``AddressRepository`` extends the base ``Repository`` class and inherits some
methods, e.g. ``findAll``.
@@ -170,19 +150,12 @@ Template
With our records in our template, we can iterate over them to display them.
-:file:`Resources/Private/Templates/Example/Example.html`:
+:file:`Resources/Private/Templates/Address/Index.html`:
-.. code-block:: html
+.. literalinclude:: ../../CodeExamples/localPackages/example_extension/Resources/Private/Templates/Address/Index.html
+ :language: html
:linenos:
-
-
-
{address.companyName}
-
- {address.street} {address.houseNumber}
- {address.zip} {address.city}
- {address.country}
-
-
+ :lines: 1-7,10
Configure storage pid
---------------------
diff --git a/Documentation/source/UpdatingRecords.rst b/Documentation/source/UpdatingRecords.rst
index fb8b144..368a817 100644
--- a/Documentation/source/UpdatingRecords.rst
+++ b/Documentation/source/UpdatingRecords.rst
@@ -1,12 +1,174 @@
+.. highlight:: php
+
Updating records
================
-Form
-----
+For everything we have done so far, you do not need a plugin at all. Custom records
+only need :file:`ext_tables.sql` the TCA and TypoScript for rendering.
+
+Extbase is needed if you provide interaction to the user, e.g. updating or adding
+records.
+
+Even that can nowadays achieved using the system extension "Form". Still we will
+cover how to update a record next.
+
+We need a form where we can adjust the values of the record, e.g. change the
+companies name.
+
+Therefore we will add a new ``editAction()``. This will receive a single ``Address``
+for editing and provides the form. We also will add an ``updateAction()`` which
+receives a single ``Address``. This action is the target of the submit form and will
+update the database record.
+
+To start editing an address, we will add an link from :file:`index.html` to
+``editAction()``.
+
+Link to another action
+----------------------
+
+.. admonition:: Task
+
+ Create a link to the ``editAction()`` providing the "current" Address record.
+
+TYPO3 provides ViewHelpers to create links to different actions. To insert a Link to
+edit a record, you could use the following:
+
+.. literalinclude:: ../../CodeExamples/localPackages/example_extension/Resources/Private/Templates/Address/Index.html
+ :language: html
+ :linenos:
+ :dedent: 4
+ :lines: 9
+
+The ViewHelper generates a link, thanks to the current plugin context, all arguments
+are prefixed with the plugin namespace.
+
+Creating Forms
+--------------
+
+.. admonition:: Task
+
+ Create a form which will show the current values of a single ``Address`` to the
+ user.
+
+TYPO3 also provides ViewHelpers to create forms. Of course you could create form with
+pure HTML, but TYPO3 / Fluid adds some security aspects and makes things easier.
+
+E.g. a proper validation that forms were not manipulated are added out of the box.
+Also you do not need to take care of proper names of the inputs to allow Extbase to
+map incoming inputs.
+
+A basic form looks like:
+
+.. code-block:: html
+ :linenos:
+
+
+
+
+
Persistence
-----------
+.. admonition:: Task
+
+ Save changes to database.
+
+Once the user submits the form, the ``updateAction()`` method within our controller is
+called. We therefore have to implement this method and to persist the changes that
+were submitted.
+
+We already have an instance of the accordingly repository within our controller. We
+also receive the modified object as an argument within our action. All we have to do
+is to update the record within the repository::
+
+ public function updateAction(Address $address)
+ {
+ $this->addressRepository->update($address);
+ }
+
+At the end of the "request", Extbase will cleanup everything and persist the updates
+to the backend, which in our case is MySQL.
+
+Redirect
+--------
+
+.. admonition:: Task
+
+ Redirect back to index.
+
+All our changes are already saved to database, but the user receives an error that no
+template could be found. We actually do not need any template for our
+``updateAction()``. Instead we will redirect the user back to the ``indexAction()``.
+This way he can check whether the change has effected the output and works as
+expected.
+
+.. note::
+
+ Following REST, an update returns the updated resource, which is the uri to the
+ resource, in our case the redirect.
+
+ As Browsers do not support ``PATCH``, which would be the request method, we use
+ ``POST``, see: https://en.wikipedia.org/wiki/Representational_state_transfer#Relationship_between_URL_and_HTTP_methods
+
+As we extend ``ActionController`` we can use the following line to redirect to
+another action::
+
+ $this->redirect('index');
+
+Cache clearing
+--------------
+
+Even if the user is redirected, he does not see any difference. That's due to TYPO3
+caching.
+
+.. admonition:: Task
+
+ Make changes visible in index action.
+
+Extbase, by default, clears the cache for all updated records. Therefore the page
+cache for the pages holding the records is cleared. As our plugin resists on a
+different page, we have to configure TYPO3.
+
+Same is true for plain TYPO3 Backend. As soon as a record is edited, the page cache
+is cleared. If this record is displayed on another page, the caching has to be
+configured, so this is not Extbase specific.
+
+The caching can be configured using Page TS Config:
+
+.. code-block:: typoscript
+
+ TCEMAIN {
+ clearCacheCmd = 1
+ }
+
+See: https://docs.typo3.org/typo3cms/TSconfigReference/PageTsconfig/TceMain.html#clearcachecmd
+
+Flash message
+-------------
+
+.. admonition:: Task
+
+ Inform user about what happened.
+
+We now have a fully working process. Still in a long list of records, the user might
+not notice a difference. Also if he leaves the computer and comes back, he will not
+know what was done before.
+
+Extbase has a feature called "Flashmessages" which are also used within TYPO3
+Backend. They inform a user on next page about some thing that happened during
+the last request. We could use that to add a message about which record was updated.
+This is also just one line within a controller::
+
+ $this->addFlashMessage(
+ $address->getCompanyName() . ' was updated.',
+ 'Update successfully'
+ );
+
Validation
----------
+.. admonition:: Task
+
+ Prevent invalid data.
+
diff --git a/Documentation/source/_static/css/custom.css b/Documentation/source/_static/css/custom.css
new file mode 100644
index 0000000..915c825
--- /dev/null
+++ b/Documentation/source/_static/css/custom.css
@@ -0,0 +1,3 @@
+.admonition-task {
+ border-left-color: #ad7526;
+}
diff --git a/Documentation/source/conf.py b/Documentation/source/conf.py
index cf712d6..e5a4a18 100644
--- a/Documentation/source/conf.py
+++ b/Documentation/source/conf.py
@@ -317,3 +317,7 @@ intersphinx_mapping = {
from sphinx.highlighting import lexers
from pygments.lexers.web import PhpLexer
lexers['php'] = PhpLexer(startinline=True, linenos=1)
+
+# Add custom css
+def setup(app):
+ app.add_stylesheet('css/custom.css')