TYPO3 CMS  TYPO3_8-7
FormFileExtensionUpdateTest.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
30 
31 class FormFileExtensionUpdateTest extends FunctionalTestCase
32 {
36  protected $coreExtensionsToLoad = [
37  'form',
38  ];
39 
43  protected $testExtensionsToLoad = [
44  'typo3/sysext/form/Tests/Functional/Hooks/Fixtures/test_resources',
45  ];
46 
50  private $subject;
51 
55  private $slot;
56 
60  private $flexForm;
61 
65  private $referenceIndex;
66 
70  private $storageFolder;
71 
72  protected function setUp()
73  {
74  parent::setUp();
75 
76  $this->setUpBackendUserFromFixture(1);
77  Bootstrap::getInstance()->initializeLanguageObject();
78 
79  $folderIdentifier = 'user_upload';
80  $storage = ResourceFactory::getInstance()->getStorageObject(1);
81 
82  if ($storage->hasFolder($folderIdentifier)) {
83  $storage->getFolder($folderIdentifier)->delete(true);
84  }
85 
86  $this->subject = GeneralUtility::makeInstance(FormFileExtensionUpdate::class);
87  $this->slot = GeneralUtility::makeInstance(FilePersistenceSlot::class);
88  $this->flexForm = GeneralUtility::makeInstance(FlexFormTools::class);
89  $this->referenceIndex = GeneralUtility::makeInstance(ReferenceIndex::class);
90  $this->storageFolder = $storage->createFolder($folderIdentifier);
91  }
92 
93  protected function tearDown()
94  {
95  $this->storageFolder->delete(true);
96  parent::tearDown();
97  }
98 
99  /*
100  * --- CHECK FOR UPDATE ---
101  */
102 
106  private function invokeCheckForUpdate(): bool
107  {
108  $description = '';
109  return $this->subject->checkForUpdate($description);
110  }
111 
116  {
117  $this->createStorageFormDefinition('updated', false);
118  $this->assertFalse($this->invokeCheckForUpdate());
119  }
120 
125  {
126  $this->createStorageFormDefinition('legacy', true);
127  $this->assertTrue($this->invokeCheckForUpdate());
128  }
129 
134  {
135  $this->createStorageFormDefinition('updated', false);
136  $this->createReference(
137  $this->createStorageFileIdentifier('updated.form.yaml'),
138  'updated'
139  );
140  $this->assertFalse($this->invokeCheckForUpdate());
141  }
142 
147  ) {
148  $this->createStorageFormDefinition('updated', false);
149  $finisherOverrides = [
150  'FirstFinisher' => StringUtility::getUniqueId(),
151  'SecondFinisher' => StringUtility::getUniqueId(),
152  ];
153  $this->createReference(
154  $this->createStorageFileIdentifier('updated.form.yaml'),
155  'updated',
156  $finisherOverrides
157  );
158  $this->assertFalse($this->invokeCheckForUpdate());
159  }
160 
165  {
166  // form definition was renamed already
167  $this->createStorageFormDefinition('updated', false);
168  // but references not updated yet
169  $this->createReference(
170  $this->createStorageFileIdentifier('updated.yaml'),
171  'updated'
172  );
173  $this->assertTrue($this->invokeCheckForUpdate());
174  }
175 
180  ) {
181  // form definition was renamed already
182  $this->createStorageFormDefinition('updated', false);
183  // but references not updated yet
184  $finisherOverrides = [
185  'FirstFinisher' => StringUtility::getUniqueId(),
186  'SecondFinisher' => StringUtility::getUniqueId(),
187  ];
188  $this->createReference(
189  $this->createStorageFileIdentifier('updated.yaml'),
190  'updated',
191  $finisherOverrides
192  );
193  $this->assertTrue($this->invokeCheckForUpdate());
194  }
195 
200  {
202  $this->assertFalse($this->invokeCheckForUpdate());
203  }
204 
209  {
211  $this->createReference(
212  $this->createExtensionFileIdentifier('updated.form.yaml'),
213  'updated'
214  );
215  $this->assertFalse($this->invokeCheckForUpdate());
216  }
217 
222  {
224  $this->createReference(
225  $this->createExtensionFileIdentifier('updated.yaml'),
226  'updated'
227  );
228  $this->assertTrue($this->invokeCheckForUpdate());
229  }
230 
235  ) {
237  $finisherOverrides = [
238  'FirstFinisher' => StringUtility::getUniqueId(),
239  'SecondFinisher' => StringUtility::getUniqueId(),
240  ];
241  $this->createReference(
242  $this->createExtensionFileIdentifier('updated.yaml'),
243  'updated',
244  $finisherOverrides
245  );
246  $this->assertTrue($this->invokeCheckForUpdate());
247  }
248 
249  /*
250  * --- PERFORM UPDATE ---
251  */
252 
253  private function invokePerformUpdate(): bool
254  {
255  $queries = [];
256  $messages = '';
257  return $this->subject->performUpdate(
258  $queries,
259  $messages
260  );
261  }
262 
267  {
268  $this->createStorageFormDefinition('legacy', true);
269  $this->assertTrue(
270  $this->invokePerformUpdate()
271  );
272  $this->assertTrue(
273  $this->storageFolder->hasFile('legacy.form.yaml')
274  );
275  }
276 
281  {
282  // form definition was renamed already
283  $this->createStorageFormDefinition('updated', false);
284  // but references not updated yet
285  $this->createReference(
286  $this->createStorageFileIdentifier('updated.yaml'),
287  'updated'
288  );
289  // having an additional reference
290  $this->createReference(
291  $this->createStorageFileIdentifier('updated.yaml'),
292  'updated'
293  );
294  $this->assertTrue(
295  $this->invokePerformUpdate()
296  );
297  $expectedFileIdentifier = $this->createStorageFileIdentifier(
298  'updated.form.yaml'
299  );
300  foreach ($this->retrieveAllFlexForms() as $flexForm) {
301  $this->assertSame(
302  $expectedFileIdentifier,
303  $flexForm['data']['sDEF']['lDEF']['settings.persistenceIdentifier']['vDEF']
304  );
305  }
306  }
307 
312  ) {
313  // form definition was renamed already
314  $this->createStorageFormDefinition('updated', false);
315  // but references not updated yet
316  $finisherOverrides = [
317  'FirstFinisher' => StringUtility::getUniqueId(),
318  'SecondFinisher' => StringUtility::getUniqueId(),
319  ];
320  $this->createReference(
321  $this->createStorageFileIdentifier('updated.yaml'),
322  'updated',
323  $finisherOverrides
324  );
325  // having an additional reference
326  $this->createReference(
327  $this->createStorageFileIdentifier('updated.yaml'),
328  'updated',
329  $finisherOverrides
330  );
331  $this->assertTrue(
332  $this->invokePerformUpdate()
333  );
334  $expectedFileIdentifier = $this->createStorageFileIdentifier(
335  'updated.form.yaml'
336  );
337  $expectedSheetIdentifiers = $this->createFinisherOverridesSheetIdentifiers(
338  $expectedFileIdentifier,
339  'updated',
340  $finisherOverrides
341  );
342  foreach ($this->retrieveAllFlexForms() as $flexForm) {
343  $this->assertSame(
344  $expectedFileIdentifier,
345  $flexForm['data']['sDEF']['lDEF']['settings.persistenceIdentifier']['vDEF'] ?? null
346  );
347  foreach ($finisherOverrides as $finisherIdentifier => $finisherValue) {
348  $sheetIdentifier = $expectedSheetIdentifiers[$finisherIdentifier];
349  $propertyName = sprintf(
350  'settings.finishers.%s.value',
351  $finisherIdentifier
352  );
353  $this->assertSame(
354  $finisherValue,
355  $flexForm['data'][$sheetIdentifier]['lDEF'][$propertyName]['vDEF'] ?? null
356  );
357  }
358  }
359  }
360 
365  {
367  $this->createReference(
368  $this->createExtensionFileIdentifier('updated.yaml'),
369  'updated'
370  );
371  // having an additional reference
372  $this->createReference(
373  $this->createExtensionFileIdentifier('updated.yaml'),
374  'updated'
375  );
376  $this->assertTrue(
377  $this->invokePerformUpdate()
378  );
379  $expectedFileIdentifier = $this->createExtensionFileIdentifier(
380  'updated.form.yaml'
381  );
382  foreach ($this->retrieveAllFlexForms() as $flexForm) {
383  $this->assertSame(
384  $expectedFileIdentifier,
385  $flexForm['data']['sDEF']['lDEF']['settings.persistenceIdentifier']['vDEF'] ?? null
386  );
387  }
388  }
389 
394  ) {
396  $finisherOverrides = [
397  'FirstFinisher' => StringUtility::getUniqueId(),
398  'SecondFinisher' => StringUtility::getUniqueId(),
399  ];
400  $this->createReference(
401  $this->createExtensionFileIdentifier('updated.yaml'),
402  'updated',
403  $finisherOverrides
404  );
405  // having an additional reference
406  $this->createReference(
407  $this->createExtensionFileIdentifier('updated.yaml'),
408  'updated',
409  $finisherOverrides
410  );
411  $this->assertTrue(
412  $this->invokePerformUpdate()
413  );
414  }
415 
416  /*
417  * --- HELPER FUNCTIONS ---
418  */
419 
424  private function createStorageFormDefinition(
425  string $name,
426  bool $legacy = false
427  ) {
428  $content = implode(LF, [
429  'type: Form',
430  'identifier: ' . $name,
431  'prototypeName: standard'
432  ]);
433 
434  $fileName = $name . '.' . ($legacy ? 'yaml' : 'form.yaml');
435  $fileIdentifier = $this->createStorageFileIdentifier($fileName);
436 
437  if (!$legacy) {
438  $this->slot->allowInvocation(
440  $fileIdentifier
441  );
442  $this->slot->allowInvocation(
444  $fileIdentifier,
445  $this->slot->getContentSignature($content)
446  );
447  }
448 
449  $this->storageFolder->createFile($fileName)->setContents($content);
450  }
451 
457  private function createReference(
458  string $fileIdentifier,
459  string $formIdentifier,
460  array $finisherOverrides = []
461  ) {
462  $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
463  $connection = $connectionPool->getConnectionForTable('tt_content');
464 
465  $flexForm = [
466  'data' => [
467  'sDEF' => [
468  'lDEF' => [
469  'settings.persistenceIdentifier' => [
470  'vDEF' => $fileIdentifier,
471  ],
472  'settings.overrideFinishers' => [
473  'vDEF' => empty($finisherOverrides) ? '0' : '1',
474  ],
475  ]
476  ]
477  ]
478  ];
479 
480  $sheetIdentifiers = $this->createFinisherOverridesSheetIdentifiers(
481  $fileIdentifier,
482  $formIdentifier,
483  $finisherOverrides
484  );
485  foreach ($finisherOverrides as $finisherIdentifier => $finisherValue) {
486  $sheetIdentifier = $sheetIdentifiers[$finisherIdentifier];
487  $propertyName = sprintf(
488  'settings.finishers.%s.value',
489  $finisherIdentifier
490  );
491  $flexForm['data'][$sheetIdentifier]['lDEF'] = [
492  $propertyName => [
493  'vDEF' => $finisherValue
494  ],
495  ];
496  }
497 
498  $values = [
499  'pid' => 1,
500  'header' => sprintf(
501  'Form Content Element for "%s"',
502  $formIdentifier
503  ),
504  'CType' => 'form_formframework',
505  'pi_flexform' => $this->flexForm
506  ->flexArray2Xml($flexForm, true)
507  ];
508 
509  $connection->insert('tt_content', $values);
510  $id = $connection->lastInsertId('tt_content');
511  $this->referenceIndex->updateRefIndexTable('tt_content', $id);
512  }
513 
517  private function setUpAllowedExtensionPaths()
518  {
520  module.tx_form.settings.yamlConfigurations {
521  110 = EXT:test_resources/Configuration/Yaml/AllowedExtensionPaths.yaml
522  }
523  plugin.tx_form.settings.yamlConfigurations {
524  110 = EXT:test_resources/Configuration/Yaml/AllowedExtensionPaths.yaml
525  }
526  '));
527  }
528 
532  private function retrieveAllFlexForms(): array
533  {
534  $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
535  $connection = $connectionPool->getConnectionForTable('tt_content');
536 
537  return array_map(
538  function (array $record) {
539  return GeneralUtility::xml2array($record['pi_flexform']);
540  },
541  $connection->select(['pi_flexform'], 'tt_content')
542  ->fetchAll(\PDO::FETCH_ASSOC)
543  );
544  }
545 
553  string $fileIdentifier,
554  string $formIdentifier,
555  array $finisherOverrides
556  ): array {
557  $sheetIdentifiers = [];
558  foreach (array_keys($finisherOverrides) as $finisherIdentifier) {
559  $sheetIdentifiers[$finisherIdentifier] = md5(
560  $fileIdentifier
561  . 'standard'
562  . $formIdentifier
563  . $finisherIdentifier
564  );
565  }
566  return $sheetIdentifiers;
567  }
568 
573  private function createStorageFileIdentifier(string $fileName): string
574  {
575  return $this->storageFolder->getCombinedIdentifier() . $fileName;
576  }
577 
582  private function createExtensionFileIdentifier(string $fileName): string
583  {
584  return 'EXT:test_resources/Configuration/Form/' . $fileName;
585  }
586 }
createReference(string $fileIdentifier, string $formIdentifier, array $finisherOverrides=[])
static makeInstance($className,... $constructorArguments)
static xml2array($string, $NSprefix='', $reportDocTag=false)
createFinisherOverridesSheetIdentifiers(string $fileIdentifier, string $formIdentifier, array $finisherOverrides)