mirror of
https://github.com/werkraum-media/events.git
synced 2024-12-22 12:46:10 +01:00
Provide location update wizard
This commit is contained in:
parent
ff8519e827
commit
8bd15ac380
4 changed files with 308 additions and 0 deletions
259
Classes/Updates/MigrateOldLocations.php
Normal file
259
Classes/Updates/MigrateOldLocations.php
Normal file
|
@ -0,0 +1,259 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Wrm\Events\Updates;
|
||||
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
||||
use TYPO3\CMS\Core\DataHandling\DataHandler;
|
||||
use TYPO3\CMS\Core\Log\Logger;
|
||||
use TYPO3\CMS\Core\Log\LogManager;
|
||||
use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
|
||||
use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
|
||||
|
||||
class MigrateOldLocations implements UpgradeWizardInterface
|
||||
{
|
||||
/**
|
||||
* @var ConnectionPool
|
||||
*/
|
||||
private $connectionPool;
|
||||
|
||||
/**
|
||||
* @var DataHandler
|
||||
*/
|
||||
private $dataHandler;
|
||||
|
||||
/**
|
||||
* @var Logger
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $uidsForTranslation = [];
|
||||
|
||||
public function __construct(
|
||||
ConnectionPool $connectionPool,
|
||||
DataHandler $dataHandler,
|
||||
LogManager $logManager
|
||||
) {
|
||||
$this->connectionPool = $connectionPool;
|
||||
$this->dataHandler = $dataHandler;
|
||||
$this->logger = $logManager->getLogger(self::class);
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Migrate EXT:event location data.';
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Checks for legacy location data stored within events and will create dedicated location records and relations.';
|
||||
}
|
||||
|
||||
public function updateNecessary(): bool
|
||||
{
|
||||
return $this->getQueryBuilder()
|
||||
->count('*')
|
||||
->execute()
|
||||
->fetchOne() > 0
|
||||
;
|
||||
}
|
||||
|
||||
public function executeUpdate(): bool
|
||||
{
|
||||
$result = $this->getQueryBuilder()->execute();
|
||||
foreach ($result as $eventRecord) {
|
||||
$this->logger->info('Updating event record.', ['record' => $eventRecord]);
|
||||
$eventRecord['location'] = $this->getLocationUid($eventRecord);
|
||||
$this->uidsForTranslation[$eventRecord['uid'] . '-' . $eventRecord['sys_language_uid']] = $eventRecord['location'];
|
||||
$this->updateEvent($eventRecord);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getLocationUid(array $event): int
|
||||
{
|
||||
$existingUid = $this->getExitingLocationUid($event);
|
||||
if ($existingUid > 0) {
|
||||
$this->logger->info('Location already exists', ['uid' => $existingUid, 'event' => $event]);
|
||||
return $existingUid;
|
||||
}
|
||||
|
||||
return $this->createLocation($event);
|
||||
}
|
||||
|
||||
private function getExitingLocationUid(array $event): int
|
||||
{
|
||||
$oldColumns = [
|
||||
'sys_language_uid' => 'sys_language_uid',
|
||||
'zzz_deleted_name' => 'name',
|
||||
'zzz_deleted_street' => 'street',
|
||||
'zzz_deleted_district' => 'district',
|
||||
'zzz_deleted_city' => 'city',
|
||||
'zzz_deleted_zip' => 'zip',
|
||||
'zzz_deleted_country' => 'country',
|
||||
'zzz_deleted_phone' => 'phone',
|
||||
'zzz_deleted_latitude' => 'latitude',
|
||||
'zzz_deleted_longitude' => 'longitude',
|
||||
];
|
||||
$qb = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_location');
|
||||
$qb->select('uid', 'l10n_parent');
|
||||
$qb->from('tx_events_domain_model_location');
|
||||
foreach ($oldColumns as $oldName => $newName) {
|
||||
$qb->andWhere($qb->expr()->eq($newName, $qb->createNamedParameter($event[$oldName])));
|
||||
}
|
||||
|
||||
$uids = $qb->execute()->fetchAssociative();
|
||||
if (is_bool($uids)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $uids['l10n_parent'] ?: $uids['uid'];
|
||||
}
|
||||
|
||||
private function createLocation(array $event): int
|
||||
{
|
||||
$this->logger->info('Location will be created.', ['event' => $event]);
|
||||
|
||||
$record = [
|
||||
'pid' => $event['pid'],
|
||||
'sys_language_uid' => $event['sys_language_uid'],
|
||||
'name' => $event['zzz_deleted_name'],
|
||||
'street' => $event['zzz_deleted_street'],
|
||||
'district' => $event['zzz_deleted_district'],
|
||||
'city' => $event['zzz_deleted_city'],
|
||||
'zip' => $event['zzz_deleted_zip'],
|
||||
'country' => $event['zzz_deleted_country'],
|
||||
'phone' => $event['zzz_deleted_phone'],
|
||||
'latitude' => $event['zzz_deleted_latitude'],
|
||||
'longitude' => $event['zzz_deleted_longitude'],
|
||||
];
|
||||
$recordUid = 'NEW12121';
|
||||
$l10nParentUid = $this->uidsForTranslation[$event['l10n_parent'] . '-0'] ?? 0;
|
||||
$dataHandler = clone $this->dataHandler;
|
||||
|
||||
if ($event['sys_language_uid'] > 0 && $l10nParentUid > 0) {
|
||||
$this->logger->info('Foreign language, create translation.', [
|
||||
'l10nParentUid' => $l10nParentUid,
|
||||
'event' => $event,
|
||||
]);
|
||||
|
||||
$dataHandler->start([], [
|
||||
'tx_events_domain_model_location' => [
|
||||
$l10nParentUid => [
|
||||
'localize' => $event['sys_language_uid'],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$dataHandler->process_cmdmap();
|
||||
$recordUid = $dataHandler->copyMappingArray_merged['tx_events_domain_model_location'][$l10nParentUid] ?? 0;
|
||||
}
|
||||
|
||||
$this->logger->info('Create or update loation.', [
|
||||
'recordUid' => $recordUid,
|
||||
'l10nParentUid' => $l10nParentUid,
|
||||
'event' => $event,
|
||||
'record' => $record,
|
||||
]);
|
||||
|
||||
$dataHandler->start([
|
||||
'tx_events_domain_model_location' => [
|
||||
$recordUid => $record,
|
||||
],
|
||||
], []);
|
||||
$dataHandler->process_datamap();
|
||||
|
||||
$uid = $dataHandler->substNEWwithIDs[$recordUid] ?? 0;
|
||||
$this->logger->info('Created or updated location.', [
|
||||
'uid' => $uid,
|
||||
]);
|
||||
if ($uid > 0) {
|
||||
return $uid;
|
||||
}
|
||||
if ($l10nParentUid > 0) {
|
||||
return $l10nParentUid;
|
||||
}
|
||||
|
||||
throw new \Exception('Could not create location: ' . implode(', ', $dataHandler->errorLog), 1672916613);
|
||||
}
|
||||
|
||||
private function updateEvent(array $event): void
|
||||
{
|
||||
$this->connectionPool
|
||||
->getConnectionForTable('tx_events_domain_model_event')
|
||||
->update(
|
||||
'tx_events_domain_model_event',
|
||||
['location' => $event['location']],
|
||||
['uid' => $event['uid']]
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
private function getQueryBuilder(): QueryBuilder
|
||||
{
|
||||
$oldColumns = [
|
||||
'zzz_deleted_name',
|
||||
'zzz_deleted_street',
|
||||
'zzz_deleted_district',
|
||||
'zzz_deleted_city',
|
||||
'zzz_deleted_zip',
|
||||
'zzz_deleted_country',
|
||||
'zzz_deleted_phone',
|
||||
'zzz_deleted_latitude',
|
||||
'zzz_deleted_longitude',
|
||||
];
|
||||
$qb = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_event');
|
||||
$qb->getRestrictions()->removeAll();
|
||||
$qb->select(...$oldColumns);
|
||||
$qb->addSelect('uid', 'pid', 'sys_language_uid', 'l10n_parent');
|
||||
$qb->from('tx_events_domain_model_event');
|
||||
foreach ($oldColumns as $columnName) {
|
||||
$qb->orWhere($qb->expr()->neq($columnName, $qb->createNamedParameter('')));
|
||||
}
|
||||
$qb->orderBy('sys_language_uid', 'ASC');
|
||||
$qb->addOrderBy('l10n_parent', 'ASC');
|
||||
$qb->addOrderBy('uid', 'ASC');
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function getIdentifier(): string
|
||||
{
|
||||
return self::class;
|
||||
}
|
||||
|
||||
public function getPrerequisites(): array
|
||||
{
|
||||
return [
|
||||
DatabaseUpdatedPrerequisite::class,
|
||||
];
|
||||
}
|
||||
|
||||
public static function register(): void
|
||||
{
|
||||
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][self::class] = self::class;
|
||||
}
|
||||
}
|
|
@ -16,6 +16,16 @@ Features
|
|||
* Pages can now define they store event records.
|
||||
A new entry was added to select and the icon within page tree will be replaced.
|
||||
|
||||
* Provided update wizard to migrate old location data to new one.
|
||||
It is important to execute the database compare once, so old columns are prefixed but not removed.
|
||||
Execute wizard and you are done.
|
||||
Locations will be extracted from old events and placed on same pid.
|
||||
You might wanna move all locations to a dedicated new pid in the end, e.g. with an sql query (Replace 2 by your page uid):
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
UPDATE tx_events_domain_model_location SET pid = 2
|
||||
|
||||
Fixes
|
||||
-----
|
||||
|
||||
|
|
|
@ -50,4 +50,6 @@ call_user_func(function () {
|
|||
\TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
|
||||
['source' => 'EXT:events/Resources/Public/Icons/Folder.svg']
|
||||
);
|
||||
|
||||
\Wrm\Events\Updates\MigrateOldLocations::register();
|
||||
});
|
||||
|
|
|
@ -4,10 +4,12 @@ parameters:
|
|||
message: "#^Cannot call method typoLink_URL\\(\\) on TYPO3\\\\CMS\\\\Frontend\\\\ContentObject\\\\ContentObjectRenderer\\|null\\.$#"
|
||||
count: 1
|
||||
path: Classes/Controller/DateController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$categories of method Wrm\\\\Events\\\\Domain\\\\Model\\\\Event\\:\\:setCategories\\(\\) expects TYPO3\\\\CMS\\\\Extbase\\\\Persistence\\\\ObjectStorage\\<Wrm\\\\Events\\\\Domain\\\\Model\\\\Category\\>, TYPO3\\\\CMS\\\\Extbase\\\\Persistence\\\\ObjectStorage\\<mixed\\> given\\.$#"
|
||||
count: 1
|
||||
path: Classes/Service/DestinationDataImportService.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$array of function array_map expects array, mixed given\\.$#"
|
||||
count: 1
|
||||
|
@ -38,3 +40,38 @@ parameters:
|
|||
count: 2
|
||||
path: Classes/Service/DestinationDataImportService/CategoriesAssignment.php
|
||||
|
||||
-
|
||||
message: "#^Argument of an invalid type Doctrine\\\\DBAL\\\\Driver\\\\ResultStatement\\|int supplied for foreach, only iterables are supported\\.$#"
|
||||
count: 1
|
||||
path: Classes/Updates/MigrateOldLocations.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method fetchAssociative\\(\\) on Doctrine\\\\DBAL\\\\Driver\\\\ResultStatement\\|int\\.$#"
|
||||
count: 1
|
||||
path: Classes/Updates/MigrateOldLocations.php
|
||||
|
||||
-
|
||||
message: "#^Argument of an invalid type Doctrine\\\\DBAL\\\\Result\\|int supplied for foreach, only iterables are supported\\.$#"
|
||||
count: 1
|
||||
path: Classes/Updates/MigrateOldLocations.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method fetchAssociative\\(\\) on Doctrine\\\\DBAL\\\\Result\\|int\\.$#"
|
||||
count: 1
|
||||
path: Classes/Updates/MigrateOldLocations.php
|
||||
|
||||
-
|
||||
message: "#^Method Wrm\\\\Events\\\\Updates\\\\MigrateOldLocations\\:\\:getExitingLocationUid\\(\\) should return int but returns mixed\\.$#"
|
||||
count: 1
|
||||
path: Classes/Updates/MigrateOldLocations.php
|
||||
|
||||
-
|
||||
message: "#^Offset 'sys_language_uid' does not exist on array\\{location\\: int\\}\\.$#"
|
||||
count: 1
|
||||
path: Classes/Updates/MigrateOldLocations.php
|
||||
|
||||
-
|
||||
message: "#^Offset 'uid' does not exist on array\\{location\\: int\\}\\.$#"
|
||||
count: 1
|
||||
path: Classes/Updates/MigrateOldLocations.php
|
||||
|
||||
|
|
Loading…
Reference in a new issue