From 82ae8718c6de65c7d98d122f8e14102086ac2e37 Mon Sep 17 00:00:00 2001
From: siwa_pparzer <p.parzer@siwa.at>
Date: Thu, 1 Oct 2020 16:41:03 +0200
Subject: [PATCH] [FEATURE] Add `defaultValues` argument to newRecord
 ViewHelpers

The <be:link.newRecord> and <be:url.newRecord> ViewHelpers now
have a new optional argument `defaultValues` which can be used to
set default values (`defVals`) for fields of the new record.

Resolves: #92462
Releases: master
Change-Id: I32d886720d10d864c6b5883f77406068a227a245
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/65992
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Oliver Bartsch <bo@cedev.de>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Oliver Bartsch <bo@cedev.de>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
---
 .../ViewHelpers/Link/NewRecordViewHelper.php  | 24 ++++++++-
 .../ViewHelpers/Uri/NewRecordViewHelper.php   | 14 +++++-
 .../WithPidTableAndDefaultValue.html          |  3 ++
 .../WithPidTableAndDefaultValues.html         |  3 ++
 .../WithPidTableAndDefaultValue.html          |  3 ++
 .../WithPidTableAndDefaultValues.html         |  3 ++
 .../Link/NewRecordViewHelperTest.php          | 25 ++++++++--
 .../Uri/NewRecordViewHelperTest.php           | 28 +++++++++++
 ...ltValuesArgumentToNewRecordViewHelpers.rst | 49 +++++++++++++++++++
 9 files changed, 145 insertions(+), 7 deletions(-)
 create mode 100644 typo3/sysext/backend/Tests/Functional/ViewHelpers/Fixtures/Link/NewRecordViewHelper/WithPidTableAndDefaultValue.html
 create mode 100644 typo3/sysext/backend/Tests/Functional/ViewHelpers/Fixtures/Link/NewRecordViewHelper/WithPidTableAndDefaultValues.html
 create mode 100644 typo3/sysext/backend/Tests/Functional/ViewHelpers/Fixtures/Uri/NewRecordViewHelper/WithPidTableAndDefaultValue.html
 create mode 100644 typo3/sysext/backend/Tests/Functional/ViewHelpers/Fixtures/Uri/NewRecordViewHelper/WithPidTableAndDefaultValues.html
 create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Feature-92462-AddOptionalDefaultValuesArgumentToNewRecordViewHelpers.rst

diff --git a/typo3/sysext/backend/Classes/ViewHelpers/Link/NewRecordViewHelper.php b/typo3/sysext/backend/Classes/ViewHelpers/Link/NewRecordViewHelper.php
index 117c1e0e1d98..5002d69ec1bd 100644
--- a/typo3/sysext/backend/Classes/ViewHelpers/Link/NewRecordViewHelper.php
+++ b/typo3/sysext/backend/Classes/ViewHelpers/Link/NewRecordViewHelper.php
@@ -69,13 +69,29 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper;
  *
  * Output::
  *
- *    <a href="/typo3/index.php?route=/record/edit&edit[a_table][-17]=new&returnUrl=foo/bar">
+ *    <a href="/typo3/index.php?route=/record/edit&edit[a_table][17]=new&returnUrl=foo/bar">
  *        Edit record
  *    </a>
  *
  * Link to create a new record then return back to the BE module "web_MyextensionList"::
  *
  *    <be:link.newRecord table="a_table" returnUrl="{f:be.uri(route: 'web_MyextensionList')}" pid="17">
+ *
+ * Output::
+ *
+ *    <a href="/typo3/index.php?route=/record/edit&edit[a_table][17]=new&returnUrl=/typo3/index.php?route=/module/web/MyextensionList">
+ *        Edit record
+ *    </a>
+ *
+ * Link to create a new record of a_table on page 17 with a default value::
+ *
+ *    <be:link.newRecord table="a_table" returnUrl="foo/bar" pid="17" defaultValues="{a_table: {a_field: 'value'}}">
+ *
+ * Output::
+ *
+ *    <a href="/typo3/index.php?route=/record/edit&edit[a_table][17]=new&returnUrl=foo/bar&defVals[a_table][a_field]=value">
+ *        Edit record
+ *    </a>
  */
 class NewRecordViewHelper extends AbstractTagBasedViewHelper
 {
@@ -92,6 +108,7 @@ class NewRecordViewHelper extends AbstractTagBasedViewHelper
         $this->registerArgument('pid', 'int', 'the page id where the record will be created', false);
         $this->registerArgument('table', 'string', 'target database table', true);
         $this->registerArgument('returnUrl', 'string', 'return to this URL after closing the edit dialog', false, '');
+        $this->registerArgument('defaultValues', 'array', 'default values for fields of the new record', false, []);
     }
 
     /**
@@ -115,6 +132,11 @@ class NewRecordViewHelper extends AbstractTagBasedViewHelper
             'edit' => [$this->arguments['table'] => [$this->arguments['uid'] ?? $this->arguments['pid'] ?? 0 => 'new']],
             'returnUrl' => $this->arguments['returnUrl']
         ];
+
+        if (is_array($this->arguments['defaultValues']) && $this->arguments['defaultValues'] !== []) {
+            $params['defVals'] = $this->arguments['defaultValues'];
+        }
+
         $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
         $uri = (string)$uriBuilder->buildUriFromRoute('record_edit', $params);
         $this->tag->addAttribute('href', $uri);
diff --git a/typo3/sysext/backend/Classes/ViewHelpers/Uri/NewRecordViewHelper.php b/typo3/sysext/backend/Classes/ViewHelpers/Uri/NewRecordViewHelper.php
index ca9ff15d256d..514b6e022d4a 100644
--- a/typo3/sysext/backend/Classes/ViewHelpers/Uri/NewRecordViewHelper.php
+++ b/typo3/sysext/backend/Classes/ViewHelpers/Uri/NewRecordViewHelper.php
@@ -61,7 +61,13 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
  *
  *    <be:uri.newRecord table="a_table" returnUrl="foo/bar" pid="17"/>
  *
- * ``/typo3/index.php?route=/record/edit&edit[a_table][-17]=new&returnUrl=foo/bar``
+ * ``/typo3/index.php?route=/record/edit&edit[a_table][17]=new&returnUrl=foo/bar``
+ *
+ * Uri to create a new record of a_table on page 17 with a default value::
+ *
+ *    <be:uri.newRecord table="a_table" returnUrl="foo/bar" pid="17" defaultValues="{a_table: {a_field: 'value'}}"/>
+ *
+ * ``/typo3/index.php?route=/record/edit&edit[a_table][17]=new&returnUrl=foo/bar&defVals[a_table][a_field]=value``
  */
 class NewRecordViewHelper extends AbstractTagBasedViewHelper
 {
@@ -73,6 +79,7 @@ class NewRecordViewHelper extends AbstractTagBasedViewHelper
         $this->registerArgument('pid', 'int', 'the page id where the record will be created', false);
         $this->registerArgument('table', 'string', 'target database table', true);
         $this->registerArgument('returnUrl', 'string', '', false, '');
+        $this->registerArgument('defaultValues', 'array', 'default values for fields of the new record', false, []);
     }
 
     /**
@@ -100,6 +107,11 @@ class NewRecordViewHelper extends AbstractTagBasedViewHelper
             'edit' => [$arguments['table'] => [$arguments['uid'] ?? $arguments['pid'] ?? 0 => 'new']],
             'returnUrl' => $arguments['returnUrl']
         ];
+
+        if (is_array($arguments['defaultValues']) && $arguments['defaultValues'] !== []) {
+            $params['defVals'] = $arguments['defaultValues'];
+        }
+
         $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
         return (string)$uriBuilder->buildUriFromRoute('record_edit', $params);
     }
diff --git a/typo3/sysext/backend/Tests/Functional/ViewHelpers/Fixtures/Link/NewRecordViewHelper/WithPidTableAndDefaultValue.html b/typo3/sysext/backend/Tests/Functional/ViewHelpers/Fixtures/Link/NewRecordViewHelper/WithPidTableAndDefaultValue.html
new file mode 100644
index 000000000000..dd8960884bff
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Functional/ViewHelpers/Fixtures/Link/NewRecordViewHelper/WithPidTableAndDefaultValue.html
@@ -0,0 +1,3 @@
+<html xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers">
+    <be:link.newRecord table="c_table" defaultValues="{c_table: {c_field: 'c_value'}}" pid="17">new record at c_table</be:link.newRecord>
+</html>
diff --git a/typo3/sysext/backend/Tests/Functional/ViewHelpers/Fixtures/Link/NewRecordViewHelper/WithPidTableAndDefaultValues.html b/typo3/sysext/backend/Tests/Functional/ViewHelpers/Fixtures/Link/NewRecordViewHelper/WithPidTableAndDefaultValues.html
new file mode 100644
index 000000000000..a8bac9532db6
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Functional/ViewHelpers/Fixtures/Link/NewRecordViewHelper/WithPidTableAndDefaultValues.html
@@ -0,0 +1,3 @@
+<html xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers">
+    <be:link.newRecord table="c_table" defaultValues="{c_table: {c_field: 'c_value', c_field2: 'c_value2'}}" pid="17">new record at c_table</be:link.newRecord>
+</html>
diff --git a/typo3/sysext/backend/Tests/Functional/ViewHelpers/Fixtures/Uri/NewRecordViewHelper/WithPidTableAndDefaultValue.html b/typo3/sysext/backend/Tests/Functional/ViewHelpers/Fixtures/Uri/NewRecordViewHelper/WithPidTableAndDefaultValue.html
new file mode 100644
index 000000000000..62f0298ebcc5
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Functional/ViewHelpers/Fixtures/Uri/NewRecordViewHelper/WithPidTableAndDefaultValue.html
@@ -0,0 +1,3 @@
+<html xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers">
+    <be:uri.newRecord table="c_table" defaultValues="{c_table: {c_field: 'c_value'}}" pid="17">new record at c_table</be:uri.newRecord>
+</html>
diff --git a/typo3/sysext/backend/Tests/Functional/ViewHelpers/Fixtures/Uri/NewRecordViewHelper/WithPidTableAndDefaultValues.html b/typo3/sysext/backend/Tests/Functional/ViewHelpers/Fixtures/Uri/NewRecordViewHelper/WithPidTableAndDefaultValues.html
new file mode 100644
index 000000000000..d9e9fa2658ff
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Functional/ViewHelpers/Fixtures/Uri/NewRecordViewHelper/WithPidTableAndDefaultValues.html
@@ -0,0 +1,3 @@
+<html xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers">
+    <be:uri.newRecord table="c_table" defaultValues="{c_table: {c_field: 'c_value', c_field2: 'c_value2'}}" pid="17">new record at c_table</be:uri.newRecord>
+</html>
diff --git a/typo3/sysext/backend/Tests/Functional/ViewHelpers/Link/NewRecordViewHelperTest.php b/typo3/sysext/backend/Tests/Functional/ViewHelpers/Link/NewRecordViewHelperTest.php
index 6c33047d463c..9cc5fb839a7d 100644
--- a/typo3/sysext/backend/Tests/Functional/ViewHelpers/Link/NewRecordViewHelperTest.php
+++ b/typo3/sysext/backend/Tests/Functional/ViewHelpers/Link/NewRecordViewHelperTest.php
@@ -95,14 +95,29 @@ class NewRecordViewHelperTest extends FunctionalTestCase
     /**
      * @test
      */
-    public function renderThrowsExceptionForUidAndPid()
+    public function renderReturnsValidLinkWithDefaultValue()
     {
-        $this->expectException(\InvalidArgumentException::class);
-        $this->expectExceptionCode(1526129969);
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $view->setTemplatePathAndFilename('EXT:backend/Tests/Functional/ViewHelpers/Fixtures/Link/NewRecordViewHelper/WithPidTableAndDefaultValue.html');
+        $result = urldecode($view->render());
+
+        self::assertStringContainsString('route=/record/edit', $result);
+        self::assertStringContainsString('edit[c_table][17]=new', $result);
+        self::assertStringContainsString('defVals[c_table][c_field]=c_value', $result);
+    }
 
+    /**
+     * @test
+     */
+    public function renderReturnsValidLinkWithDefaultValues()
+    {
         $view = GeneralUtility::makeInstance(StandaloneView::class);
-        $view->setTemplatePathAndFilename('EXT:backend/Tests/Functional/ViewHelpers/Fixtures/Link/NewRecordViewHelper/WithUidAndPid.html');
-        $view->render();
+        $view->setTemplatePathAndFilename('EXT:backend/Tests/Functional/ViewHelpers/Fixtures/Link/NewRecordViewHelper/WithPidTableAndDefaultValues.html');
+        $result = urldecode($view->render());
+
+        self::assertStringContainsString('route=/record/edit', $result);
+        self::assertStringContainsString('edit[c_table][17]=new', $result);
+        self::assertStringContainsString('defVals[c_table][c_field]=c_value&amp;defVals[c_table][c_field2]=c_value2', $result);
     }
 
     /**
diff --git a/typo3/sysext/backend/Tests/Functional/ViewHelpers/Uri/NewRecordViewHelperTest.php b/typo3/sysext/backend/Tests/Functional/ViewHelpers/Uri/NewRecordViewHelperTest.php
index dc1eeaecc462..164d6b5946db 100644
--- a/typo3/sysext/backend/Tests/Functional/ViewHelpers/Uri/NewRecordViewHelperTest.php
+++ b/typo3/sysext/backend/Tests/Functional/ViewHelpers/Uri/NewRecordViewHelperTest.php
@@ -92,6 +92,34 @@ class NewRecordViewHelperTest extends FunctionalTestCase
         self::assertStringContainsString('edit[c_table][-11]=new', $result);
     }
 
+    /**
+     * @test
+     */
+    public function renderReturnsValidLinkWithDefaultValue()
+    {
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $view->setTemplatePathAndFilename('EXT:backend/Tests/Functional/ViewHelpers/Fixtures/Uri/NewRecordViewHelper/WithPidTableAndDefaultValue.html');
+        $result = urldecode($view->render());
+
+        self::assertStringContainsString('route=/record/edit', $result);
+        self::assertStringContainsString('edit[c_table][17]=new', $result);
+        self::assertStringContainsString('defVals[c_table][c_field]=c_value', $result);
+    }
+
+    /**
+     * @test
+     */
+    public function renderReturnsValidLinkWithDefaultValues()
+    {
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $view->setTemplatePathAndFilename('EXT:backend/Tests/Functional/ViewHelpers/Fixtures/Uri/NewRecordViewHelper/WithPidTableAndDefaultValues.html');
+        $result = urldecode($view->render());
+
+        self::assertStringContainsString('route=/record/edit', $result);
+        self::assertStringContainsString('edit[c_table][17]=new', $result);
+        self::assertStringContainsString('defVals[c_table][c_field]=c_value&defVals[c_table][c_field2]=c_value2', $result);
+    }
+
     /**
      * @test
      */
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-92462-AddOptionalDefaultValuesArgumentToNewRecordViewHelpers.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-92462-AddOptionalDefaultValuesArgumentToNewRecordViewHelpers.rst
new file mode 100644
index 000000000000..6833cd1c350a
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-92462-AddOptionalDefaultValuesArgumentToNewRecordViewHelpers.rst
@@ -0,0 +1,49 @@
+.. include:: ../../Includes.txt
+
+================================================================================
+Feature: #92462 - Add optional "defaultValues" argument to newRecord ViewHelpers
+================================================================================
+
+See :issue:`92462`
+
+Description
+===========
+
+A new optional argument `defaultValues` is added to the `be:uri.newRecord` and
+`be:link.newRecord` ViewHelpers. The new argument can contain default values for
+fields of the new record. FormEngine automatically fills the given default values
+into the corresponding fields.
+
+The syntax is: :xml:`{tableName: {fieldName: 'value'}}`.
+
+Please note that the given default values are added to the url as `GET` parameters
+and therefore override default values defined in FormDataProviders or TSconfig.
+
+
+Impact
+======
+
+It is now possible to assign default values to fields of new records using the
+`defaultValues` argument in the `be:uri.newRecord` and `be:link.newRecord` ViewHelpers.
+
+
+Example
+=======
+
+Link to create a new `tt_content` record on page 17 with a default value for field `header`:
+
+.. code-block:: xml
+
+   <be:link.newRecord table="tt_content" pid="17" defaultValues="{tt_content: {header: 'value'}}" returnUrl="foo/bar">
+        New record
+   </be:link.newRecord>
+
+Output:
+
+.. code-block:: html
+
+   <a href="/typo3/index.php?route=/record/edit&edit[tt_content][17]=new&returnUrl=foo/bar&defVals[tt_content][header]=value">
+       New record
+   </a>
+
+.. index:: Backend, Fluid, ext:backend
-- 
GitLab