events/Classes/Updates/MigrateOldLocations.php
Daniel Siepmann c6ad36b294 Use proper column names
Normal updates are executed:

    ./vendor/bin/typo3cms upgrade:prepare

    ./vendor/bin/typo3cms upgrade:run all --no-interaction

    ./vendor/bin/typo3cms database:updateschema '*'

    ./vendor/bin/typo3cms database:updateschema '*'

The first one will execute an database:updateschema which will run safe
which only adds and doesn't rename or remove columns.
Then our update wizard can use the existing columns and new columns and
tables.
The last step will actually rename and remove.
2023-01-24 13:08:46 +01:00

264 lines
7.7 KiB
PHP

<?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
{
$columns = [
'sys_language_uid',
'name',
'street',
'district',
'city',
'zip',
'country',
'phone',
'latitude',
'longitude',
];
$qb = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_location');
$qb->select('uid', 'l10n_parent');
$qb->from('tx_events_domain_model_location');
foreach ($columns as $column) {
$qb->andWhere($qb->expr()->eq($column, $qb->createNamedParameter($event[$column])));
}
$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]);
$columnsToMap = [
'pid',
'sys_language_uid',
'name',
'street',
'district',
'city',
'zip',
'country',
'phone',
'latitude',
'longitude',
];
$record = [];
foreach ($columnsToMap as $columnName) {
$record[$columnName] = $event[$columnName];
}
$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
{
$columns = [
'name',
'street',
'district',
'city',
'zip',
'country',
'phone',
'latitude',
'longitude',
];
$qb = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_event');
$qb->getRestrictions()->removeAll();
$qb->select(...$columns);
$qb->addSelect('uid', 'pid', 'sys_language_uid', 'l10n_parent');
$qb->from('tx_events_domain_model_event');
foreach ($columns 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;
}
}