Skip to content

Commit 9c96918

Browse files
committed
Version 6.0.1
1 parent c8ccb3c commit 9c96918

File tree

4 files changed

+255
-3
lines changed

4 files changed

+255
-3
lines changed
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Extension "plain_faq" for TYPO3 CMS.
7+
*
8+
* For the full copyright and license information, please read the
9+
* LICENSE.txt file that was distributed with this source code.
10+
*/
11+
12+
namespace Fixpunkt\FpMasterquiz\Updates;
13+
14+
use TYPO3\CMS\Core\Database\Connection;
15+
use TYPO3\CMS\Core\Database\ConnectionPool;
16+
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
17+
use TYPO3\CMS\Core\Service\FlexFormService;
18+
use TYPO3\CMS\Core\Utility\GeneralUtility;
19+
use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
20+
use TYPO3\CMS\Install\Attribute\UpgradeWizard;
21+
use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
22+
23+
#[UpgradeWizard('switchableControllerActionsPluginUpdaterFpQuiz')]
24+
final class SwitchableControllerActionsPluginUpdater implements UpgradeWizardInterface
25+
{
26+
private const MIGRATION_SETTINGS = [
27+
[
28+
'sourceListType' => 'fpmasterquiz_pi1',
29+
'switchableControllerActions' => 'Quiz->list;Quiz->show;Quiz->showAjax',
30+
'targetListType' => 'fpmasterquiz_list',
31+
],
32+
[
33+
'sourceListType' => 'fpmasterquiz_pi1',
34+
'switchableControllerActions' => 'Quiz->default;Quiz->show;Quiz->showAjax',
35+
'targetListType' => 'fpmasterquiz_show',
36+
],
37+
[
38+
'sourceListType' => 'fpmasterquiz_pi1',
39+
'switchableControllerActions' => 'Quiz->showByTag',
40+
'targetListType' => 'fpmasterquiz_showbytag',
41+
],
42+
[
43+
'sourceListType' => 'fpmasterquiz_pi1',
44+
'switchableControllerActions' => 'Quiz->intro;Quiz->show;Quiz->showAjax;Quiz->showByTag',
45+
'targetListType' => 'fpmasterquiz_intro',
46+
],
47+
[
48+
'sourceListType' => 'fpmasterquiz_pi1',
49+
'switchableControllerActions' => 'Quiz->closure',
50+
'targetListType' => 'fpmasterquiz_closure',
51+
],
52+
[
53+
'sourceListType' => 'fpmasterquiz_pi1',
54+
'switchableControllerActions' => 'Quiz->defaultres;Quiz->result',
55+
'targetListType' => 'fpmasterquiz_result',
56+
],
57+
[
58+
'sourceListType' => 'fpmasterquiz_pi1',
59+
'switchableControllerActions' => 'Quiz->highscore',
60+
'targetListType' => 'fpmasterquiz_highscore',
61+
],
62+
];
63+
64+
protected FlexFormService $flexFormService;
65+
66+
public function __construct()
67+
{
68+
$this->flexFormService = GeneralUtility::makeInstance(FlexFormService::class);
69+
}
70+
71+
public function getIdentifier(): string
72+
{
73+
return 'switchableControllerActionsPluginUpdaterFpQuiz';
74+
}
75+
76+
public function getTitle(): string
77+
{
78+
return 'EXT:fp_masterquiz: Migrates plugin and settings of existing MasterQuiz plugins using switchableControllerActions';
79+
}
80+
81+
public function getDescription(): string
82+
{
83+
$description = 'The old fp_masterquiz plugin using switchableControllerActions has been split into separate plugins. ';
84+
$description .= 'This update wizard migrates all existing plugin settings and changes the Plugin (list_type) ';
85+
$description .= 'to use the new plugins available.';
86+
return $description;
87+
}
88+
89+
public function getPrerequisites(): array
90+
{
91+
return [
92+
DatabaseUpdatedPrerequisite::class,
93+
];
94+
}
95+
96+
public function updateNecessary(): bool
97+
{
98+
return $this->checkIfWizardIsRequired();
99+
}
100+
101+
public function executeUpdate(): bool
102+
{
103+
return $this->performMigration();
104+
}
105+
106+
public function checkIfWizardIsRequired(): bool
107+
{
108+
return count($this->getMigrationRecords()) > 0;
109+
}
110+
111+
public function performMigration(): bool
112+
{
113+
$records = $this->getMigrationRecords();
114+
115+
foreach ($records as $record) {
116+
$flexFormData = GeneralUtility::xml2array($record['pi_flexform']);
117+
$flexForm = $this->flexFormService->convertFlexFormContentToArray($record['pi_flexform']);
118+
if (!is_array($flexForm)) {
119+
$flexForm = [];
120+
}
121+
if (!isset($flexForm['switchableControllerActions'])) {
122+
$flexForm['switchableControllerActions'] = '';
123+
}
124+
$targetListType = $this->getTargetListType(
125+
$record['list_type'],
126+
$flexForm['switchableControllerActions']
127+
);
128+
$allowedSettings = $this->getAllowedSettingsFromFlexForm($targetListType);
129+
130+
// Remove flexform data which do not exist in flexform of new plugin
131+
foreach ($flexFormData['data'] as $sheetKey => $sheetData) {
132+
foreach ($sheetData['lDEF'] as $settingName => $setting) {
133+
if (!in_array($settingName, $allowedSettings, true)) {
134+
unset($flexFormData['data'][$sheetKey]['lDEF'][$settingName]);
135+
}
136+
}
137+
138+
// Remove empty sheets
139+
if (!count($flexFormData['data'][$sheetKey]['lDEF']) > 0) {
140+
unset($flexFormData['data'][$sheetKey]);
141+
}
142+
}
143+
144+
if (count($flexFormData['data']) > 0) {
145+
$newFlexform = $this->array2xml($flexFormData);
146+
} else {
147+
$newFlexform = '';
148+
}
149+
150+
$this->updateContentElement($record['uid'], $targetListType, $newFlexform);
151+
}
152+
153+
return true;
154+
}
155+
156+
protected function getMigrationRecords(): array
157+
{
158+
$checkListTypes = array_unique(array_column(self::MIGRATION_SETTINGS, 'sourceListType'));
159+
160+
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
161+
$queryBuilder = $connectionPool->getQueryBuilderForTable('tt_content');
162+
$queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
163+
164+
return $queryBuilder
165+
->select('uid', 'list_type', 'pi_flexform')
166+
->from('tt_content')->where($queryBuilder->expr()->in(
167+
'list_type',
168+
$queryBuilder->createNamedParameter($checkListTypes, Connection::PARAM_STR_ARRAY)
169+
))->executeQuery()
170+
->fetchAllAssociative();
171+
}
172+
173+
protected function getTargetListType(string $sourceListType, string $switchableControllerActions): string
174+
{
175+
foreach (self::MIGRATION_SETTINGS as $setting) {
176+
if ($setting['sourceListType'] === $sourceListType &&
177+
$setting['switchableControllerActions'] === $switchableControllerActions
178+
) {
179+
return $setting['targetListType'];
180+
}
181+
}
182+
183+
return '';
184+
}
185+
186+
protected function getAllowedSettingsFromFlexForm(string $listType): array
187+
{
188+
$settings = [];
189+
if ($listType) {
190+
$flexFormFile = $GLOBALS['TCA']['tt_content']['columns']['pi_flexform']['config']['ds'][$listType . ',list'];
191+
if ($flexFormFile) {
192+
$flexFormContent = file_get_contents(GeneralUtility::getFileAbsFileName(substr(trim((string)$flexFormFile), 5)));
193+
$flexFormData = GeneralUtility::xml2array($flexFormContent);
194+
195+
// Iterate each sheet and extract all settings
196+
foreach ($flexFormData['sheets'] as $sheet) {
197+
foreach ($sheet['ROOT']['el'] as $setting => $tceForms) {
198+
$settings[] = $setting;
199+
}
200+
}
201+
}
202+
}
203+
return $settings;
204+
}
205+
206+
/**
207+
* Updates list_type and pi_flexform of the given content element UID
208+
*/
209+
protected function updateContentElement(int $uid, string $newListType, string $flexform): void
210+
{
211+
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content');
212+
$queryBuilder->update('tt_content')
213+
->set('list_type', $newListType)
214+
->set('pi_flexform', $flexform)->where($queryBuilder->expr()->in(
215+
'uid',
216+
$queryBuilder->createNamedParameter($uid, Connection::PARAM_INT)
217+
))->executeStatement();
218+
}
219+
220+
/**
221+
* Transforms the given array to FlexForm XML
222+
*
223+
* @return string
224+
*/
225+
protected function array2xml(array $input = []): string
226+
{
227+
$options = [
228+
'parentTagMap' => [
229+
'data' => 'sheet',
230+
'sheet' => 'language',
231+
'language' => 'field',
232+
'el' => 'field',
233+
'field' => 'value',
234+
'field:el' => 'el',
235+
'el:_IS_NUM' => 'section',
236+
'section' => 'itemType',
237+
],
238+
'disableTypeAttrib' => 2,
239+
];
240+
$spaceInd = 4;
241+
$output = GeneralUtility::array2xml($input, '', 0, 'T3FlexForms', $spaceInd, $options);
242+
$output = '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>' . LF . $output;
243+
return $output;
244+
}
245+
}

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# fp_masterquiz
22

3-
version 6.0.0
3+
version 6.0.1
44

55
TYPO3 extension to create a quiz, poll or test. The participant result will be saved in the DB too and can be deleted automatically via Scheduler.
66

@@ -59,4 +59,7 @@ Changes in 5.2.0:
5959

6060
Changes in 6.0.0:
6161
- First version for TYPO3 13, but emails are not working with TYPO3 13!
62-
- Upgrade Wizards for old file references and Switchable-Controller-Action-Plugins removed!
62+
- Upgrade Wizards for old file references and Switchable-Controller-Action-Plugins removed!
63+
64+
Changes in 6.0.1:
65+
- Upgrade Wizards for Switchable-Controller-Action-Plugins added again, so it can be used with TYPO3 13 too!

ext_emconf.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
'category' => 'plugin',
1717
'author' => 'Kurt Gusbeth',
1818
'state' => 'stable',
19-
'version' => '6.0.0',
19+
'version' => '6.0.1',
2020
'constraints' => [
2121
'depends' => [
2222
'typo3' => '12.4.0-13.4.99',

ext_localconf.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ function()
8585
if ((new Typo3Version())->getMajorVersion() < 13) {
8686
// @extensionScannerIgnoreLine
8787
ExtensionManagementUtility::addPageTSConfig('@import \'EXT:fp_masterquiz/Configuration/TSconfig/ContentElementWizard.tsconfig\'');
88+
89+
// Register switchableControllerActions plugin migrator
90+
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['switchableControllerActionsPluginUpdaterFpQuiz']
91+
= \Fixpunkt\FpMasterquiz\Updates\SwitchableControllerActionsPluginUpdater::class;
8892
}
8993

9094
// register statistics tables for garbage collection

0 commit comments

Comments
 (0)