mirror of
https://github.com/werkraum-media/events.git
synced 2024-11-24 03:16:10 +01:00
Properly handle latitude and longitude during Destination One import (#32)
They sometimes use a different separator. The code is adjusted to always use same separator and precision. That will prevent the same location from showing up multiple times due to different latitude and longitude values.
This commit is contained in:
parent
6348b1079d
commit
00946af6ad
23 changed files with 1276 additions and 15 deletions
|
@ -75,8 +75,8 @@ class Location extends AbstractEntity
|
|||
$this->district = $district;
|
||||
$this->country = $country;
|
||||
$this->phone = $phone;
|
||||
$this->latitude = $latitude;
|
||||
$this->longitude = $longitude;
|
||||
$this->latitude = $this->normalizeGeocoordinate($latitude);
|
||||
$this->longitude = $this->normalizeGeocoordinate($longitude);
|
||||
$this->_languageUid = $languageUid;
|
||||
|
||||
$this->globalId = $this->generateGlobalId();
|
||||
|
@ -132,6 +132,14 @@ class Location extends AbstractEntity
|
|||
return $this->globalId;
|
||||
}
|
||||
|
||||
public function updateFromLocation(self $location): void
|
||||
{
|
||||
// Only updates values not being part of global id.
|
||||
$this->phone = $location->getPhone();
|
||||
$this->longitude = $location->getLongitude();
|
||||
$this->latitude = $location->getLatitude();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the location.
|
||||
*
|
||||
|
@ -158,8 +166,21 @@ class Location extends AbstractEntity
|
|||
$this->city,
|
||||
$this->district,
|
||||
$this->country,
|
||||
$this->latitude,
|
||||
$this->longitude,
|
||||
]));
|
||||
}
|
||||
|
||||
private function normalizeGeocoordinate(string $coordinate): string
|
||||
{
|
||||
$numberOfCommas = substr_count($coordinate, ',');
|
||||
$numberOfPoints = substr_count($coordinate, '.');
|
||||
|
||||
if (
|
||||
$numberOfCommas === 1
|
||||
&& $numberOfPoints === 0
|
||||
) {
|
||||
$coordinate = str_replace(',', '.', $coordinate);
|
||||
}
|
||||
|
||||
return number_format((float)$coordinate, 6, '.', '');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,19 @@
|
|||
namespace Wrm\Events\Domain\Repository;
|
||||
|
||||
use TYPO3\CMS\Extbase\Persistence\Repository;
|
||||
use Wrm\Events\Domain\Model\Location;
|
||||
|
||||
class LocationRepository extends Repository
|
||||
{
|
||||
public function findOneByGlobalId(string $globalId): ?Location
|
||||
{
|
||||
$query = $this->createQuery();
|
||||
|
||||
return $query
|
||||
->matching($query->equals('globalId', $globalId))
|
||||
->setLimit(1)
|
||||
->execute()
|
||||
->getFirst()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,12 @@ class LocationAssignment
|
|||
|
||||
$existingLocation = $this->repository->findOneByGlobalId($newLocation->getGlobalId());
|
||||
|
||||
return $existingLocation ?? $newLocation;
|
||||
if ($existingLocation === null) {
|
||||
return $newLocation;
|
||||
}
|
||||
|
||||
$existingLocation->updateFromLocation($newLocation);
|
||||
|
||||
return $existingLocation;
|
||||
}
|
||||
}
|
||||
|
|
204
Classes/Updates/MigrateDuplicateLocations.php
Normal file
204
Classes/Updates/MigrateDuplicateLocations.php
Normal file
|
@ -0,0 +1,204 @@
|
|||
<?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 Generator;
|
||||
use TYPO3\CMS\Core\Database\Connection;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
|
||||
use Wrm\Events\Domain\Model\Location;
|
||||
|
||||
final class MigrateDuplicateLocations implements UpgradeWizardInterface
|
||||
{
|
||||
/**
|
||||
* @var ConnectionPool
|
||||
*/
|
||||
private $connectionPool;
|
||||
|
||||
public function __construct(
|
||||
ConnectionPool $connectionPool
|
||||
) {
|
||||
$this->connectionPool = $connectionPool;
|
||||
}
|
||||
|
||||
public function getIdentifier(): string
|
||||
{
|
||||
return self::class;
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Remove duplicate locations of EXT:event';
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Checks for duplicates and reduces them to one entry, fixing relations to events.';
|
||||
}
|
||||
|
||||
public function updateNecessary(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function executeUpdate(): bool
|
||||
{
|
||||
$duplicates = [];
|
||||
|
||||
foreach ($this->getLocations() as $location) {
|
||||
$locationObject = $this->buildObject($location);
|
||||
if ($locationObject->getGlobalId() === $location['global_id']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$uid = (int)$location['uid'];
|
||||
$matchingLocation = $this->getMatchingLocation(
|
||||
$locationObject->getGlobalId(),
|
||||
$uid
|
||||
);
|
||||
|
||||
// Already have entries for the new id, this one is duplicate
|
||||
if ($matchingLocation > 0) {
|
||||
$duplicates[$uid] = $matchingLocation;
|
||||
continue;
|
||||
}
|
||||
|
||||
// No duplicates, update this one
|
||||
$this->updateLocation($locationObject, $uid);
|
||||
}
|
||||
|
||||
$this->removeDuplicates(array_keys($duplicates));
|
||||
$this->updateRelations($duplicates);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getPrerequisites(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public static function register(): void
|
||||
{
|
||||
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][self::class] = self::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Generator<array>
|
||||
*/
|
||||
private function getLocations(): Generator
|
||||
{
|
||||
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_location');
|
||||
$queryBuilder->select(
|
||||
'name',
|
||||
'street',
|
||||
'zip',
|
||||
'city',
|
||||
'district',
|
||||
'country',
|
||||
'phone',
|
||||
'latitude',
|
||||
'longitude',
|
||||
'global_id',
|
||||
'uid',
|
||||
'sys_language_uid'
|
||||
);
|
||||
$queryBuilder->from('tx_events_domain_model_location');
|
||||
$queryBuilder->orderBy('uid', 'asc');
|
||||
$result = $queryBuilder->execute();
|
||||
|
||||
foreach ($result->fetchAllAssociative() as $location) {
|
||||
yield $location;
|
||||
}
|
||||
}
|
||||
|
||||
private function getMatchingLocation(
|
||||
string $globalId,
|
||||
int $uid
|
||||
): int {
|
||||
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_location');
|
||||
$queryBuilder->select('uid');
|
||||
$queryBuilder->from('tx_events_domain_model_location');
|
||||
$queryBuilder->where($queryBuilder->expr()->eq('global_id', $queryBuilder->createNamedParameter($globalId)));
|
||||
$queryBuilder->andWhere($queryBuilder->expr()->neq('uid', $queryBuilder->createNamedParameter($uid)));
|
||||
$queryBuilder->setMaxResults(1);
|
||||
|
||||
$uid = $queryBuilder->execute()->fetchOne();
|
||||
if (is_numeric($uid) === false) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) $uid;
|
||||
}
|
||||
|
||||
private function buildObject(array $location): Location
|
||||
{
|
||||
return new Location(
|
||||
$location['name'],
|
||||
$location['street'],
|
||||
$location['zip'],
|
||||
$location['city'],
|
||||
$location['district'],
|
||||
$location['country'],
|
||||
$location['phone'],
|
||||
$location['latitude'],
|
||||
$location['longitude'],
|
||||
(int)$location['sys_language_uid']
|
||||
);
|
||||
}
|
||||
|
||||
private function updateLocation(Location $location, int $uid): void
|
||||
{
|
||||
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_location');
|
||||
$queryBuilder->update('tx_events_domain_model_location');
|
||||
$queryBuilder->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid)));
|
||||
$queryBuilder->set('global_id', $location->getGlobalId());
|
||||
$queryBuilder->set('latitude', $location->getLatitude());
|
||||
$queryBuilder->set('longitude', $location->getLongitude());
|
||||
$queryBuilder->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $uids
|
||||
*/
|
||||
private function removeDuplicates(array $uids): void
|
||||
{
|
||||
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_location');
|
||||
$queryBuilder->delete('tx_events_domain_model_location');
|
||||
$queryBuilder->where($queryBuilder->expr()->in('uid', $queryBuilder->createNamedParameter($uids, Connection::PARAM_INT_ARRAY)));
|
||||
$queryBuilder->execute();
|
||||
}
|
||||
|
||||
private function updateRelations(array $migration): void
|
||||
{
|
||||
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_event');
|
||||
$queryBuilder->update('tx_events_domain_model_event');
|
||||
|
||||
foreach ($migration as $legacyLocationUid => $newLocationUid) {
|
||||
$finalBuilder = clone $queryBuilder;
|
||||
$finalBuilder->where($finalBuilder->expr()->eq('location', $finalBuilder->createNamedParameter($legacyLocationUid)));
|
||||
$finalBuilder->set('location', $newLocationUid);
|
||||
$finalBuilder->execute();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,6 +37,9 @@ services:
|
|||
identifier: 'WrmEventsAddSpecialPropertiesToDate'
|
||||
event: TYPO3\CMS\Extbase\Event\Persistence\AfterObjectThawedEvent
|
||||
|
||||
Wrm\Events\Updates\MigrateDuplicateLocations:
|
||||
public: true
|
||||
|
||||
Wrm\Events\Updates\MigrateOldLocations:
|
||||
public: true
|
||||
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
3.4.0
|
||||
=====
|
||||
|
||||
Manual steps
|
||||
------------
|
||||
|
||||
* Determining global_id of locations has changed.
|
||||
An Update Wizard is provided in order to migrate existing data.
|
||||
This is only necessary when using the import of locations from Destination One.
|
||||
|
||||
Breaking
|
||||
--------
|
||||
|
||||
|
@ -74,6 +81,10 @@ Fixes
|
|||
Those might not exist in newer systems where migration is not necessary.
|
||||
The wizard now properly checks for existence before querying the data.
|
||||
|
||||
* Prevent duplicate location entries from Destination One import.
|
||||
They seem to differ in writing of latitude and longitude.
|
||||
An update wizard is provided to clean up existing duplicates.
|
||||
|
||||
Tasks
|
||||
-----
|
||||
|
||||
|
|
|
@ -31,9 +31,9 @@ Es gilt die 2G-PLUS-Regel.",,,,,,,"1","2",,"8","3",,"1",,3,"adventliche-orgelmus
|
|||
,"13","2","0","0","0","0",-1,0,"0","0","0","3","1671732000","1671735600","no","0",,"adventliche-orgelmusik-orgel-kmd-frank-bettenhausen-2022-12-22t18-00-00",,,,,,,,,,,,,,,,,,
|
||||
"tx_events_domain_model_location",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,"uid","pid","cruser_id","hidden","starttime","endtime","sys_language_uid","l10n_parent","t3ver_oid","t3ver_wsid","t3ver_state","name","street","district","city","zip","country","latitude","longitude","phone",,,,,,,,,,,,,,,,
|
||||
,"1","2","0","0","0","0",-1,0,"0","0","0","Schillerhaus Rudolstadt","Schillerstraße 25",,"Rudolstadt","07407","Deutschland","50.720971023259","11.335229873657","+ 49 3672 / 486470",,,,,,,,,,,,,,,,
|
||||
,"2","2","0","0","0","0",-1,0,"0","0","0","Stadtbibliothek Rudolstadt","Schulplatz 13",,"Rudolstadt","07407","Deutschland","50.720835175056","11.342568397522","0 36 72 - 48 64 20",,,,,,,,,,,,,,,,
|
||||
,"3","2","0","0","0","0",-1,0,"0","0","0","Lutherkirche","Caspar-Schulte-Straße",,"Rudolstadt","07407","Deutschland","50.718688721183","11.327333450317","03672 - 48 96 13",,,,,,,,,,,,,,,,
|
||||
,"1","2","0","0","0","0",-1,0,"0","0","0","Schillerhaus Rudolstadt","Schillerstraße 25",,"Rudolstadt","07407","Deutschland","50.720971","11.335230","+ 49 3672 / 486470",,,,,,,,,,,,,,,,
|
||||
,"2","2","0","0","0","0",-1,0,"0","0","0","Stadtbibliothek Rudolstadt","Schulplatz 13",,"Rudolstadt","07407","Deutschland","50.720835","11.342568","0 36 72 - 48 64 20",,,,,,,,,,,,,,,,
|
||||
,"3","2","0","0","0","0",-1,0,"0","0","0","Lutherkirche","Caspar-Schulte-Straße",,"Rudolstadt","07407","Deutschland","50.718689","11.327333","03672 - 48 96 13",,,,,,,,,,,,,,,,
|
||||
"sys_category",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,"uid","pid","cruser_id","hidden","starttime","endtime","sys_language_uid","l10n_parent","title","items","parent",,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,1,2,0,0,0,0,0,0,"Top Category",0,0,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
|
|
|
|
@ -1,4 +0,0 @@
|
|||
"tx_events_domain_model_location",,,,,,,,,,,,,,,,,,,,
|
||||
,"uid","pid","cruser_id","hidden","starttime","endtime","sys_language_uid","l10n_parent","t3ver_oid","t3ver_wsid","t3ver_state","name","street","district","city","zip","country","latitude","longitude","phone"
|
||||
,"1","2","0","0","0","0",-1,0,"0","0","0","Schillerhaus Rudolstadt","Schillerstraße 25",,"Rudolstadt","07407","Deutschland","50.720971023259","11.335229873657","+ 49 3672 / 486470"
|
||||
,"2","2","0","0","0","0",-1,0,"0","0","0","Schillerhaus Rudolstadt","Other address",,"Rudolstadt","07407","Deutschland","50.720971023259","11.335229873657","+ 49 3672 / 486470"
|
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'tx_events_domain_model_location' => [
|
||||
[
|
||||
'uid' => 1,
|
||||
'pid' => 2,
|
||||
'cruser_id' => 0,
|
||||
'hidden' => 0,
|
||||
'starttime' => 0,
|
||||
'endtime' => 0,
|
||||
'sys_language_uid' => -1,
|
||||
'l10n_parent' => 0,
|
||||
't3ver_oid' => 0,
|
||||
't3ver_wsid' => 0,
|
||||
't3ver_state' => 0,
|
||||
'name' => 'Schillerhaus Rudolstadt',
|
||||
'street' => 'Schillerstraße 25',
|
||||
'district' => '',
|
||||
'city' => 'Rudolstadt',
|
||||
'zip' => '07407',
|
||||
'country' => 'Deutschland',
|
||||
'latitude' => '50.720971',
|
||||
'longitude' => '11.335230',
|
||||
'phone' => '+ 49 3672 / 486470',
|
||||
'global_id' => '2c898a5e8f751906124a6eb6384a3b111754db37d3330b169ec022b98a0ddcbe',
|
||||
],
|
||||
[
|
||||
'uid' => 2,
|
||||
'pid' => 2,
|
||||
'cruser_id' => 0,
|
||||
'hidden' => 0,
|
||||
'starttime' => 0,
|
||||
'endtime' => 0,
|
||||
'sys_language_uid' => -1,
|
||||
'l10n_parent' => 0,
|
||||
't3ver_oid' => 0,
|
||||
't3ver_wsid' => 0,
|
||||
't3ver_state' => 0,
|
||||
'name' => 'Schillerhaus Rudolstadt',
|
||||
'street' => 'Other address',
|
||||
'district' => '',
|
||||
'city' => 'Rudolstadt',
|
||||
'zip' => '07407',
|
||||
'country' => 'Deutschland',
|
||||
'latitude' => '50.720971',
|
||||
'longitude' => '11.335230',
|
||||
'phone' => '+ 49 3672 / 486470',
|
||||
'global_id' => 'c0df4e7901836412bf6e45289cf749f60b86cf8405aa23767b5e18890fa4cf30',
|
||||
],
|
||||
],
|
||||
];
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'tx_events_domain_model_location' => [
|
||||
[
|
||||
'uid' => 1,
|
||||
'pid' => 2,
|
||||
'name' => 'Schillerhaus Rudolstadt',
|
||||
'street' => 'Schillerstraße 25',
|
||||
'district' => '',
|
||||
'city' => 'Rudolstadt',
|
||||
'zip' => '07407',
|
||||
'country' => 'Deutschland',
|
||||
'latitude' => '50.720971',
|
||||
'longitude' => '11.335230',
|
||||
'phone' => '+ 49 3672 / 486470',
|
||||
'global_id' => '2c898a5e8f751906124a6eb6384a3b111754db37d3330b169ec022b98a0ddcbe',
|
||||
],
|
||||
],
|
||||
];
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'tx_events_domain_model_location' => [
|
||||
[
|
||||
'uid' => 1,
|
||||
'pid' => 2,
|
||||
'sys_language_uid' => -1,
|
||||
'name' => 'Schillerhaus Rudolstadt',
|
||||
'street' => 'Schillerstraße 25',
|
||||
'district' => '',
|
||||
'city' => 'Rudolstadt',
|
||||
'zip' => '07407',
|
||||
'country' => 'Deutschland',
|
||||
'latitude' => '50.720971',
|
||||
'longitude' => '11.335230',
|
||||
'phone' => '+ 49 3672 / 486470',
|
||||
'global_id' => '2c898a5e8f751906124a6eb6384a3b111754db37d3330b169ec022b98a0ddcbe',
|
||||
],
|
||||
],
|
||||
];
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'tx_events_domain_model_location' => [
|
||||
[
|
||||
'uid' => 1,
|
||||
'pid' => 2,
|
||||
'sys_language_uid' => -1,
|
||||
'name' => 'Schillerhaus Rudolstadt',
|
||||
'street' => 'Schillerstraße 25',
|
||||
'district' => '',
|
||||
'city' => 'Rudolstadt',
|
||||
'zip' => '07407',
|
||||
'country' => 'Deutschland',
|
||||
'latitude' => '49.720971',
|
||||
'longitude' => '10.335230',
|
||||
'phone' => '+ 49 / 486470',
|
||||
'global_id' => '2c898a5e8f751906124a6eb6384a3b111754db37d3330b169ec022b98a0ddcbe',
|
||||
],
|
||||
],
|
||||
];
|
|
@ -0,0 +1,341 @@
|
|||
{
|
||||
"status": "OK",
|
||||
"count": 2,
|
||||
"overallcount": 50,
|
||||
"channels": [],
|
||||
"facetGroups": [],
|
||||
"items": [
|
||||
{
|
||||
"global_id": "e_100347853",
|
||||
"id": "100347853",
|
||||
"title": "Allerlei Weihnachtliches (Heute mit Johannes Geißer)",
|
||||
"type": "Event",
|
||||
"categories": [
|
||||
"Weihnachten"
|
||||
],
|
||||
"texts": [
|
||||
{
|
||||
"rel": "details",
|
||||
"type": "text/html",
|
||||
"value": "Die Lichter sind entzündet, die Plätzchen duften, man rückt endlich wieder näher zusammen und lauscht den Geschichten. Vier Schauspieler*innen unseres Theaters überraschen mit ihren weihnachtlichen Texten, die sie für uns ausgewählt haben. Dazu plaudern sie über persönliche Anekdoten und erinnern sich an ihre schönsten und verrücktesten Weihnachtsfeste. Und da der Genuss in der Vorweihnachtszeit nicht fehlen darf, wird an jedem Adventssonntag eine andere weihnachtliche Spezialität serviert.<br>Eintritt: 10 € (inkl. Gedeck mit weihnachtlicher Schillerlocke)<br>Um Voranmeldung unter 03672-486470 oder <a data-cke-saved-href=\"mailto:schillerhaus@rudolstadt.de\" href=\"mailto:schillerhaus@rudolstadt.de\">schillerhaus@rudolstadt.de</a> wird gebeten. <br><strong>Es gilt die 2G-PLUS-Regel.</strong> <br>"
|
||||
},
|
||||
{
|
||||
"rel": "details",
|
||||
"type": "text/plain",
|
||||
"value": "Die Lichter sind entzündet, die Plätzchen duften, man rückt endlich wieder näher zusammen und lauscht den Geschichten. Vier Schauspieler*innen unseres Theaters überraschen mit ihren weihnachtlichen Texten, die sie für uns ausgewählt haben. Dazu plaudern sie über persönliche Anekdoten und erinnern sich an ihre schönsten und verrücktesten Weihnachtsfeste. Und da der Genuss in der Vorweihnachtszeit nicht fehlen darf, wird an jedem Adventssonntag eine andere weihnachtliche Spezialität serviert.\nEintritt: 10 € (inkl. Gedeck mit weihnachtlicher Schillerlocke)\nUm Voranmeldung unter 03672-486470 oder schillerhaus@rudolstadt.de wird gebeten.\nEs gilt die 2G-PLUS-Regel."
|
||||
},
|
||||
{
|
||||
"rel": "teaser",
|
||||
"type": "text/html"
|
||||
},
|
||||
{
|
||||
"rel": "teaser",
|
||||
"type": "text/plain"
|
||||
}
|
||||
],
|
||||
"areas": [
|
||||
"Rudolstadt und Umgebung"
|
||||
],
|
||||
|
||||
"name": "Schillerhaus Rudolstadt",
|
||||
"street": "Schillerstraße 25",
|
||||
"zip": "07407",
|
||||
"city": "Rudolstadt",
|
||||
"district": "",
|
||||
"country": "Deutschland",
|
||||
"phone": "+ 49 3672 / 486470",
|
||||
"geo": {
|
||||
"main": {
|
||||
"latitude": 50.720971023258805,
|
||||
"longitude": 11.335229873657227
|
||||
},
|
||||
"entry": [],
|
||||
"attributes": []
|
||||
},
|
||||
|
||||
"fax": "+ 49 3672 / 486475",
|
||||
"web": "http://www.schillerhaus.rudolstadt.de/",
|
||||
"email": "schillerhaus@rudolstadt.de",
|
||||
"author": "support@hubermedia.de",
|
||||
"ratings": [
|
||||
{
|
||||
"type": "eT4",
|
||||
"value": 40.0
|
||||
},
|
||||
{
|
||||
"type": "order",
|
||||
"value": 99.0001
|
||||
}
|
||||
],
|
||||
"cuisine_types": [],
|
||||
"payment": [],
|
||||
"media_objects": [
|
||||
{
|
||||
"rel": "venuewebsite",
|
||||
"url": "http://schillerhaus.rudolstadt.de/",
|
||||
"latitude": null,
|
||||
"longitude": null,
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"keywords": [],
|
||||
"timeIntervals": [
|
||||
{
|
||||
"weekdays": [],
|
||||
"start": "2099-12-19T15:00:00+01:00",
|
||||
"end": "2099-12-19T16:30:00+01:00",
|
||||
"tz": "Europe/Berlin",
|
||||
"interval": 1
|
||||
}
|
||||
],
|
||||
"kitchenTimeIntervals": [],
|
||||
"deliveryTimeIntervals": [],
|
||||
"numbers": [],
|
||||
"attributes": [
|
||||
{
|
||||
"key": "VO_Id",
|
||||
"value": "100050775"
|
||||
},
|
||||
{
|
||||
"key": "VO_CategoryName",
|
||||
"value": "POI"
|
||||
},
|
||||
{
|
||||
"key": "VA_Id",
|
||||
"value": "100050775"
|
||||
},
|
||||
{
|
||||
"key": "VA_CategoryName",
|
||||
"value": "POI"
|
||||
},
|
||||
{
|
||||
"key": "interval_first_match_start",
|
||||
"value": "2099-12-19T15:00:00+01"
|
||||
},
|
||||
{
|
||||
"key": "interval_first_match_end",
|
||||
"value": "2099-12-19T16:30:00+01"
|
||||
},
|
||||
{
|
||||
"key": "interval_match_count",
|
||||
"value": "1"
|
||||
}
|
||||
],
|
||||
"features": [
|
||||
"vorhandenes Feature",
|
||||
"Barrierefrei",
|
||||
"Zielgruppe Jugendliche",
|
||||
"Karten an der Abendkasse",
|
||||
"Ausreichende Lüftung",
|
||||
"Beachtung der Hygienehinweise"
|
||||
],
|
||||
"addresses": [
|
||||
{
|
||||
"name": "Städtetourismus in Thüringen e.V.",
|
||||
"city": "Weimar",
|
||||
"zip": "99423",
|
||||
"street": "UNESCO-Platz 1",
|
||||
"phone": "+49 (3643) 745 314",
|
||||
"web": "http://www.thueringer-staedte.de",
|
||||
"email": "verein@thueringer-staedte.de",
|
||||
"rel": "author"
|
||||
},
|
||||
{
|
||||
"name": "Städtetourismus in Thüringen\" e.V.",
|
||||
"web": "http://www.thueringer-staedte.de",
|
||||
"email": "verein@thueringer-staedte.de",
|
||||
"rel": "organisation"
|
||||
},
|
||||
{
|
||||
"name": "Schillerhaus Rudolstadt",
|
||||
"city": "Rudolstadt",
|
||||
"zip": "07407",
|
||||
"street": "Schillerstraße 25",
|
||||
"phone": "+ 49 3672 / 486470",
|
||||
"fax": "+ 49 3672 / 486475",
|
||||
"web": "http://schillerhaus.rudolstadt.de",
|
||||
"email": "schillerhaus@rudolstadt.de",
|
||||
"rel": "organizer"
|
||||
}
|
||||
],
|
||||
"created": "2099-10-31T12:29:00+00:00",
|
||||
"changed": "2099-12-14T08:29:00+00:00",
|
||||
"source": {
|
||||
"url": "http://destination.one/",
|
||||
"value": "destination.one"
|
||||
},
|
||||
"company": "",
|
||||
"postoffice": "",
|
||||
"phone2": "",
|
||||
"seasons": [],
|
||||
"subitems": [],
|
||||
"hyperObjects": []
|
||||
},
|
||||
{
|
||||
"global_id": "e_100347853",
|
||||
"id": "100347853",
|
||||
"title": "Allerlei Weihnachtliches (Heute mit Johannes Geißer)",
|
||||
"type": "Event",
|
||||
"categories": [
|
||||
"Weihnachten"
|
||||
],
|
||||
"texts": [
|
||||
{
|
||||
"rel": "details",
|
||||
"type": "text/html",
|
||||
"value": "Die Lichter sind entzündet, die Plätzchen duften, man rückt endlich wieder näher zusammen und lauscht den Geschichten. Vier Schauspieler*innen unseres Theaters überraschen mit ihren weihnachtlichen Texten, die sie für uns ausgewählt haben. Dazu plaudern sie über persönliche Anekdoten und erinnern sich an ihre schönsten und verrücktesten Weihnachtsfeste. Und da der Genuss in der Vorweihnachtszeit nicht fehlen darf, wird an jedem Adventssonntag eine andere weihnachtliche Spezialität serviert.<br>Eintritt: 10 € (inkl. Gedeck mit weihnachtlicher Schillerlocke)<br>Um Voranmeldung unter 03672-486470 oder <a data-cke-saved-href=\"mailto:schillerhaus@rudolstadt.de\" href=\"mailto:schillerhaus@rudolstadt.de\">schillerhaus@rudolstadt.de</a> wird gebeten. <br><strong>Es gilt die 2G-PLUS-Regel.</strong> <br>"
|
||||
},
|
||||
{
|
||||
"rel": "details",
|
||||
"type": "text/plain",
|
||||
"value": "Die Lichter sind entzündet, die Plätzchen duften, man rückt endlich wieder näher zusammen und lauscht den Geschichten. Vier Schauspieler*innen unseres Theaters überraschen mit ihren weihnachtlichen Texten, die sie für uns ausgewählt haben. Dazu plaudern sie über persönliche Anekdoten und erinnern sich an ihre schönsten und verrücktesten Weihnachtsfeste. Und da der Genuss in der Vorweihnachtszeit nicht fehlen darf, wird an jedem Adventssonntag eine andere weihnachtliche Spezialität serviert.\nEintritt: 10 € (inkl. Gedeck mit weihnachtlicher Schillerlocke)\nUm Voranmeldung unter 03672-486470 oder schillerhaus@rudolstadt.de wird gebeten.\nEs gilt die 2G-PLUS-Regel."
|
||||
},
|
||||
{
|
||||
"rel": "teaser",
|
||||
"type": "text/html"
|
||||
},
|
||||
{
|
||||
"rel": "teaser",
|
||||
"type": "text/plain"
|
||||
}
|
||||
],
|
||||
"areas": [
|
||||
"Rudolstadt und Umgebung"
|
||||
],
|
||||
|
||||
"name": "Schillerhaus Rudolstadt",
|
||||
"street": "Schillerstraße 25",
|
||||
"zip": "07407",
|
||||
"city": "Rudolstadt",
|
||||
"district": "",
|
||||
"country": "Deutschland",
|
||||
"phone": "+ 49 3672 / 486470",
|
||||
"geo": {
|
||||
"main": {
|
||||
"latitude": "50,720971023258805",
|
||||
"longitude": "11,335229873657227"
|
||||
},
|
||||
"entry": [],
|
||||
"attributes": []
|
||||
},
|
||||
|
||||
"fax": "+ 49 3672 / 486475",
|
||||
"web": "http://www.schillerhaus.rudolstadt.de/",
|
||||
"email": "schillerhaus@rudolstadt.de",
|
||||
"author": "support@hubermedia.de",
|
||||
"ratings": [
|
||||
{
|
||||
"type": "eT4",
|
||||
"value": 40.0
|
||||
},
|
||||
{
|
||||
"type": "order",
|
||||
"value": 99.0001
|
||||
}
|
||||
],
|
||||
"cuisine_types": [],
|
||||
"payment": [],
|
||||
"media_objects": [
|
||||
{
|
||||
"rel": "venuewebsite",
|
||||
"url": "http://schillerhaus.rudolstadt.de/",
|
||||
"latitude": null,
|
||||
"longitude": null,
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"keywords": [],
|
||||
"timeIntervals": [
|
||||
{
|
||||
"weekdays": [],
|
||||
"start": "2099-12-19T15:00:00+01:00",
|
||||
"end": "2099-12-19T16:30:00+01:00",
|
||||
"tz": "Europe/Berlin",
|
||||
"interval": 1
|
||||
}
|
||||
],
|
||||
"kitchenTimeIntervals": [],
|
||||
"deliveryTimeIntervals": [],
|
||||
"numbers": [],
|
||||
"attributes": [
|
||||
{
|
||||
"key": "VO_Id",
|
||||
"value": "100050775"
|
||||
},
|
||||
{
|
||||
"key": "VO_CategoryName",
|
||||
"value": "POI"
|
||||
},
|
||||
{
|
||||
"key": "VA_Id",
|
||||
"value": "100050775"
|
||||
},
|
||||
{
|
||||
"key": "VA_CategoryName",
|
||||
"value": "POI"
|
||||
},
|
||||
{
|
||||
"key": "interval_first_match_start",
|
||||
"value": "2099-12-19T15:00:00+01"
|
||||
},
|
||||
{
|
||||
"key": "interval_first_match_end",
|
||||
"value": "2099-12-19T16:30:00+01"
|
||||
},
|
||||
{
|
||||
"key": "interval_match_count",
|
||||
"value": "1"
|
||||
}
|
||||
],
|
||||
"features": [
|
||||
"vorhandenes Feature",
|
||||
"Barrierefrei",
|
||||
"Zielgruppe Jugendliche",
|
||||
"Karten an der Abendkasse",
|
||||
"Ausreichende Lüftung",
|
||||
"Beachtung der Hygienehinweise"
|
||||
],
|
||||
"addresses": [
|
||||
{
|
||||
"name": "Städtetourismus in Thüringen e.V.",
|
||||
"city": "Weimar",
|
||||
"zip": "99423",
|
||||
"street": "UNESCO-Platz 1",
|
||||
"phone": "+49 (3643) 745 314",
|
||||
"web": "http://www.thueringer-staedte.de",
|
||||
"email": "verein@thueringer-staedte.de",
|
||||
"rel": "author"
|
||||
},
|
||||
{
|
||||
"name": "Städtetourismus in Thüringen\" e.V.",
|
||||
"web": "http://www.thueringer-staedte.de",
|
||||
"email": "verein@thueringer-staedte.de",
|
||||
"rel": "organisation"
|
||||
},
|
||||
{
|
||||
"name": "Schillerhaus Rudolstadt",
|
||||
"city": "Rudolstadt",
|
||||
"zip": "07407",
|
||||
"street": "Schillerstraße 25",
|
||||
"phone": "+ 49 3672 / 486470",
|
||||
"fax": "+ 49 3672 / 486475",
|
||||
"web": "http://schillerhaus.rudolstadt.de",
|
||||
"email": "schillerhaus@rudolstadt.de",
|
||||
"rel": "organizer"
|
||||
}
|
||||
],
|
||||
"created": "2099-10-31T12:29:00+00:00",
|
||||
"changed": "2099-12-14T08:29:00+00:00",
|
||||
"source": {
|
||||
"url": "http://destination.one/",
|
||||
"value": "destination.one"
|
||||
},
|
||||
"company": "",
|
||||
"postoffice": "",
|
||||
"phone2": "",
|
||||
"seasons": [],
|
||||
"subitems": [],
|
||||
"hyperObjects": []
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
{
|
||||
"status": "OK",
|
||||
"count": 1,
|
||||
"overallcount": 50,
|
||||
"channels": [],
|
||||
"facetGroups": [],
|
||||
"items": [
|
||||
{
|
||||
"global_id": "e_100347853",
|
||||
"id": "100347853",
|
||||
"title": "Allerlei Weihnachtliches (Heute mit Johannes Geißer)",
|
||||
"type": "Event",
|
||||
"categories": [ ],
|
||||
"name": "Schillerhaus Rudolstadt",
|
||||
"street": "Schillerstraße 25",
|
||||
"zip": "07407",
|
||||
"city": "Rudolstadt",
|
||||
"district": "",
|
||||
"country": "Deutschland",
|
||||
"phone": "+ 49 3672 / 486470",
|
||||
"geo": {
|
||||
"main": {
|
||||
"latitude": 50.720971023258805,
|
||||
"longitude": 11.335229873657227
|
||||
}
|
||||
},
|
||||
"fax": "+ 49 3672 / 486475",
|
||||
"web": "http://www.schillerhaus.rudolstadt.de/",
|
||||
"email": "schillerhaus@rudolstadt.de",
|
||||
"author": "support@hubermedia.de",
|
||||
"cuisine_types": [],
|
||||
"payment": [],
|
||||
"media_objects": [ ],
|
||||
"keywords": [],
|
||||
"timeIntervals": [ ],
|
||||
"kitchenTimeIntervals": [],
|
||||
"deliveryTimeIntervals": [],
|
||||
"numbers": [],
|
||||
"attributes": [ ],
|
||||
"features": [ ],
|
||||
"addresses": [ ],
|
||||
"created": "2099-10-31T12:29:00+00:00",
|
||||
"changed": "2099-12-14T08:29:00+00:00",
|
||||
"source": {
|
||||
"url": "http://destination.one/",
|
||||
"value": "destination.one"
|
||||
},
|
||||
"company": "",
|
||||
"postoffice": "",
|
||||
"phone2": "",
|
||||
"seasons": [],
|
||||
"subitems": [],
|
||||
"hyperObjects": []
|
||||
}
|
||||
]
|
||||
}
|
|
@ -7,7 +7,7 @@ use GuzzleHttp\Psr7\Response;
|
|||
/**
|
||||
* @testdox DestinationData import
|
||||
*/
|
||||
class ImportsWithLocationsTest extends AbstractTest
|
||||
final class ImportsWithLocationsTest extends AbstractTest
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
|
@ -29,13 +29,48 @@ class ImportsWithLocationsTest extends AbstractTest
|
|||
*/
|
||||
public function importsWithLocations(): void
|
||||
{
|
||||
$requests = &$this->setUpResponses([
|
||||
$this->setUpResponses([
|
||||
new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ResponseWithLocations.json') ?: ''),
|
||||
]);
|
||||
$tester = $this->executeCommand();
|
||||
|
||||
self::assertSame(0, $tester->getStatusCode());
|
||||
$this->assertCSVDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Assertions/ImportsWithLocations.csv');
|
||||
$this->assertPHPDataSet(__DIR__ . '/Assertions/ImportsWithLocations.php');
|
||||
$this->assertEmptyLog();
|
||||
}
|
||||
|
||||
/**
|
||||
* A single location might be available with different ways to write latitude an longitude ("," and ".").
|
||||
* This test ensures this situation is properly handled by streamlining the values.
|
||||
*
|
||||
* @test
|
||||
*/
|
||||
public function importsWithSingleLocationOnDuplicates(): void
|
||||
{
|
||||
$this->setUpResponses([
|
||||
new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ResponseWithLocationUsingDifferentLatitudeAndLongitude.json') ?: ''),
|
||||
]);
|
||||
$tester = $this->executeCommand();
|
||||
|
||||
self::assertSame(0, $tester->getStatusCode());
|
||||
$this->assertPHPDataSet(__DIR__ . '/Assertions/ImportsWithSingleLocationOnDuplicates.php');
|
||||
$this->assertEmptyLog();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function updatesExistingLocation(): void
|
||||
{
|
||||
$this->importPHPDataSet(__DIR__ . '/Fixtures/Database/ExistingLocation.php');
|
||||
|
||||
$this->setUpResponses([
|
||||
new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ResponseWithLocationWithDifferentValues.json') ?: ''),
|
||||
]);
|
||||
$tester = $this->executeCommand();
|
||||
|
||||
self::assertSame(0, $tester->getStatusCode());
|
||||
$this->assertPHPDataSet(__DIR__ . '/Assertions/UpdatesExistingLocation.php');
|
||||
$this->assertEmptyLog();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'tx_events_domain_model_location' => [
|
||||
[
|
||||
'uid' => 1,
|
||||
'pid' => 0,
|
||||
'sys_language_uid' => -1,
|
||||
'global_id' => 'a91656ec76732f2b7b72987d11d81d926fa67ea3b2eb4cc6fd75bb2b748da21d',
|
||||
'name' => 'Domplatz',
|
||||
'street' => '',
|
||||
'city' => 'Erfurt',
|
||||
'zip' => '99084',
|
||||
'district' => 'Altstadt',
|
||||
'country' => 'Deutschland',
|
||||
'phone' => '',
|
||||
'latitude' => '50.977089',
|
||||
'longitude' => '11.024878',
|
||||
],
|
||||
[
|
||||
'uid' => 3,
|
||||
'pid' => 0,
|
||||
'sys_language_uid' => -1,
|
||||
'global_id' => '95ca076b77e478cc8eb831f48aacaa608a640034e31da2e11b42da9758c84aaf',
|
||||
'name' => 'Wenigemarkt',
|
||||
'street' => '',
|
||||
'city' => 'Erfurt',
|
||||
'zip' => '99084',
|
||||
'district' => 'Altstadt',
|
||||
'country' => 'Deutschland',
|
||||
'phone' => '',
|
||||
'latitude' => '50.978500',
|
||||
'longitude' => '11.031589',
|
||||
],
|
||||
],
|
||||
'tx_events_domain_model_event' => [
|
||||
[
|
||||
'uid' => 1,
|
||||
'pid' => 0,
|
||||
'title' => 'Abendmahlsgottesdienst',
|
||||
'global_id' => 'e_100171396',
|
||||
'location' => 1,
|
||||
],
|
||||
[
|
||||
'uid' => 2,
|
||||
'pid' => 0,
|
||||
'title' => 'Travestie-Revue "Pretty Wo(man)"',
|
||||
'global_id' => 'e_100172162',
|
||||
'location' => 1,
|
||||
],
|
||||
[
|
||||
'uid' => 3,
|
||||
'pid' => 0,
|
||||
'title' => 'Abendgebet in englischer Sprache',
|
||||
'global_id' => 'e_100172275',
|
||||
'location' => 3,
|
||||
],
|
||||
],
|
||||
];
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'tx_events_domain_model_location' => [
|
||||
[
|
||||
'uid' => 1,
|
||||
'pid' => 0,
|
||||
'sys_language_uid' => -1,
|
||||
'global_id' => '21e0561cb967c2b3c7977c367615b97b4176e26302dd77fadb33296cd37fb4b0',
|
||||
'name' => 'Domplatz',
|
||||
'street' => '',
|
||||
'city' => 'Erfurt',
|
||||
'zip' => '99084',
|
||||
'district' => 'Altstadt',
|
||||
'country' => 'Deutschland',
|
||||
'phone' => '',
|
||||
'latitude' => '50,977089',
|
||||
'longitude' => '11,024878',
|
||||
],
|
||||
[
|
||||
'uid' => 2,
|
||||
'pid' => 0,
|
||||
'sys_language_uid' => -1,
|
||||
'global_id' => '1cc57820faf4a3bf6bf8326f2821068f0619f9fc8bcbebd8c6e4c496e38471c7',
|
||||
'name' => 'Domplatz',
|
||||
'street' => '',
|
||||
'city' => 'Erfurt',
|
||||
'zip' => '99084',
|
||||
'district' => 'Altstadt',
|
||||
'country' => 'Deutschland',
|
||||
'phone' => '',
|
||||
'latitude' => '50.977089',
|
||||
'longitude' => '11.024878',
|
||||
],
|
||||
[
|
||||
'uid' => 3,
|
||||
'pid' => 0,
|
||||
'sys_language_uid' => -1,
|
||||
'global_id' => '64d0def98fe304c32c79e6926cac40c8501797158e0e43990c36f7b1fb50c17e',
|
||||
'name' => 'Wenigemarkt',
|
||||
'street' => '',
|
||||
'city' => 'Erfurt',
|
||||
'zip' => '99084',
|
||||
'district' => 'Altstadt',
|
||||
'country' => 'Deutschland',
|
||||
'phone' => '',
|
||||
'latitude' => '50.9785',
|
||||
'longitude' => '11.031589',
|
||||
],
|
||||
],
|
||||
'tx_events_domain_model_event' => [
|
||||
[
|
||||
'uid' => 1,
|
||||
'pid' => 0,
|
||||
'title' => 'Abendmahlsgottesdienst',
|
||||
'global_id' => 'e_100171396',
|
||||
'location' => 1,
|
||||
],
|
||||
[
|
||||
'uid' => 2,
|
||||
'pid' => 0,
|
||||
'title' => 'Travestie-Revue "Pretty Wo(man)"',
|
||||
'global_id' => 'e_100172162',
|
||||
'location' => 2,
|
||||
],
|
||||
[
|
||||
'uid' => 3,
|
||||
'pid' => 0,
|
||||
'title' => 'Abendgebet in englischer Sprache',
|
||||
'global_id' => 'e_100172275',
|
||||
'location' => 3,
|
||||
],
|
||||
],
|
||||
];
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'tx_events_domain_model_location' => [
|
||||
[
|
||||
'uid' => 1,
|
||||
'pid' => 0,
|
||||
'sys_language_uid' => -1,
|
||||
'global_id' => '1cc57820faf4a3bf6bf8326f2821068f0619f9fc8bcbebd8c6e4c496e38471c7',
|
||||
'name' => 'Domplatz',
|
||||
'street' => '',
|
||||
'city' => 'Erfurt',
|
||||
'zip' => '99084',
|
||||
'district' => 'Altstadt',
|
||||
'country' => 'Deutschland',
|
||||
'phone' => '',
|
||||
'latitude' => '50.977089',
|
||||
'longitude' => '11.024878',
|
||||
],
|
||||
[
|
||||
'uid' => 2,
|
||||
'pid' => 0,
|
||||
'sys_language_uid' => -1,
|
||||
'global_id' => '64d0def98fe304c32c79e6926cac40c8501797158e0e43990c36f7b1fb50c17e',
|
||||
'name' => 'Wenigemarkt',
|
||||
'street' => '',
|
||||
'city' => 'Erfurt',
|
||||
'zip' => '99084',
|
||||
'district' => 'Altstadt',
|
||||
'country' => 'Deutschland',
|
||||
'phone' => '',
|
||||
'latitude' => '50.9785',
|
||||
'longitude' => '11.031589',
|
||||
],
|
||||
],
|
||||
];
|
85
Tests/Functional/Updates/MigrateDuplicateLocationsTest.php
Normal file
85
Tests/Functional/Updates/MigrateDuplicateLocationsTest.php
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?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\Tests\Functional\Updates;
|
||||
|
||||
use Wrm\Events\Tests\Functional\AbstractFunctionalTestCase;
|
||||
use Wrm\Events\Updates\MigrateDuplicateLocations;
|
||||
|
||||
/**
|
||||
* @testdox The update wizard to migrate duplicate locations
|
||||
*/
|
||||
final class MigrateDuplicateLocationsTest extends AbstractFunctionalTestCase
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function canBeCreated(): void
|
||||
{
|
||||
$subject = $this->get(MigrateDuplicateLocations::class);
|
||||
|
||||
self::assertInstanceOf(MigrateDuplicateLocations::class, $subject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function isRegistered(): void
|
||||
{
|
||||
self::assertArrayHasKey(
|
||||
MigrateDuplicateLocations::class,
|
||||
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function keepsDataIfNothingToDo(): void
|
||||
{
|
||||
$this->importPHPDataSet(__DIR__ . '/Fixtures/MigrateDuplicateLocationsNoDuplicates.php');
|
||||
|
||||
$subject = $this->get(MigrateDuplicateLocations::class);
|
||||
|
||||
self::assertInstanceOf(MigrateDuplicateLocations::class, $subject);
|
||||
self::assertTrue($subject->updateNecessary());
|
||||
|
||||
$this->assertPHPDataSet(__DIR__ . '/Fixtures/MigrateDuplicateLocationsNoDuplicates.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function migratesDuplicateEntries(): void
|
||||
{
|
||||
$this->importPHPDataSet(__DIR__ . '/Fixtures/MigrateDuplicateLocations.php');
|
||||
|
||||
$subject = $this->get(MigrateDuplicateLocations::class);
|
||||
|
||||
self::assertInstanceOf(MigrateDuplicateLocations::class, $subject);
|
||||
self::assertTrue($subject->updateNecessary());
|
||||
$subject->executeUpdate();
|
||||
|
||||
$this->assertPHPDataSet(__DIR__ . '/Assertions/MigrateDuplicateLocations.php');
|
||||
}
|
||||
}
|
83
Tests/Unit/Domain/Model/LocationTest.php
Normal file
83
Tests/Unit/Domain/Model/LocationTest.php
Normal file
|
@ -0,0 +1,83 @@
|
|||
<?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\Tests\Unit\Domain\Model;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Wrm\Events\Domain\Model\Location;
|
||||
|
||||
/**
|
||||
* @covers \Wrm\Events\Domain\Model\Location
|
||||
*/
|
||||
final class LocationTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @dataProvider possibleLatitudeAndLongitude
|
||||
*/
|
||||
public function normalizesLatitudeAndLongitude(
|
||||
string $latitude,
|
||||
string $longitude
|
||||
): void {
|
||||
$subject = new Location(
|
||||
'Name',
|
||||
'Street',
|
||||
'Zip',
|
||||
'City',
|
||||
'District',
|
||||
'Country',
|
||||
'Phone',
|
||||
$latitude,
|
||||
$longitude,
|
||||
1
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
'50.720971',
|
||||
$subject->getLatitude()
|
||||
);
|
||||
self::assertSame(
|
||||
'11.335230',
|
||||
$subject->getLongitude()
|
||||
);
|
||||
}
|
||||
|
||||
public static function possibleLatitudeAndLongitude(): array
|
||||
{
|
||||
return [
|
||||
'Using float numbers' => [
|
||||
'latitude' => (string)50.720971023258805,
|
||||
'longitude' => (string)11.335229873657227,
|
||||
],
|
||||
'Using ","' => [
|
||||
'latitude' => '50,720971023258805',
|
||||
'longitude' => '11,335229873657227',
|
||||
],
|
||||
'Using "."' => [
|
||||
'latitude' => '50.720971023258805',
|
||||
'longitude' => '11.335229873657227',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
<?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\Tests\Unit\Service\DestinationDataImportService;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Wrm\Events\Domain\Model\Location;
|
||||
use Wrm\Events\Domain\Repository\LocationRepository;
|
||||
use Wrm\Events\Service\DestinationDataImportService\LocationAssignment;
|
||||
|
||||
/**
|
||||
* @covers \Wrm\Events\Service\DestinationDataImportService\LocationAssignment
|
||||
*/
|
||||
final class LocationAssignmentTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function canBeCreated(): void
|
||||
{
|
||||
$repository = $this->createStub(LocationRepository::class);
|
||||
$subject = new LocationAssignment(
|
||||
$repository
|
||||
);
|
||||
|
||||
self::assertInstanceOf(
|
||||
LocationAssignment::class,
|
||||
$subject
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @dataProvider possibleLatitudeAndLongitude
|
||||
*
|
||||
* @param string|float $latitude
|
||||
* @param string|float $longitude
|
||||
*/
|
||||
public function normalizesLatitudeAndLongitude(
|
||||
$latitude,
|
||||
$longitude
|
||||
): void {
|
||||
$repository = $this->createStub(LocationRepository::class);
|
||||
$repository->method('findOneByGlobalId')->willReturn(null);
|
||||
|
||||
$subject = new LocationAssignment(
|
||||
$repository
|
||||
);
|
||||
|
||||
$result = $subject->getLocation([
|
||||
'name' => 'Name',
|
||||
'street' => 'Street',
|
||||
'zip' => 'Zip',
|
||||
'city' => 'City',
|
||||
'district' => 'District',
|
||||
'country' => 'Country',
|
||||
'phone' => 'Phone',
|
||||
'geo' => [
|
||||
'main' => [
|
||||
'latitude' => $latitude,
|
||||
'longitude' => $longitude,
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
self::assertInstanceOf(
|
||||
Location::class,
|
||||
$result
|
||||
);
|
||||
self::assertSame(
|
||||
'50.720971',
|
||||
$result->getLatitude(),
|
||||
'Latitude returns unexpected value.'
|
||||
);
|
||||
self::assertSame(
|
||||
'11.335230',
|
||||
$result->getLongitude(),
|
||||
'Longitude returns unexpected value.'
|
||||
);
|
||||
}
|
||||
|
||||
public static function possibleLatitudeAndLongitude(): array
|
||||
{
|
||||
return [
|
||||
'Using float numbers' => [
|
||||
'latitude' => 50.720971023258805,
|
||||
'longitude' => 11.335229873657227,
|
||||
],
|
||||
'Using ","' => [
|
||||
'latitude' => '50,720971023258805',
|
||||
'longitude' => '11,335229873657227',
|
||||
],
|
||||
'Using "."' => [
|
||||
'latitude' => '50.720971023258805',
|
||||
'longitude' => '11.335229873657227',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
|
@ -53,4 +53,5 @@ call_user_func(function () {
|
|||
|
||||
\Wrm\Events\Caching\PageCacheTimeout::register();
|
||||
\Wrm\Events\Updates\MigrateOldLocations::register();
|
||||
\Wrm\Events\Updates\MigrateDuplicateLocations::register();
|
||||
});
|
||||
|
|
|
@ -12,8 +12,12 @@ parameters:
|
|||
- "#^Call to an undefined method Doctrine\\\\DBAL\\\\Result\\:\\:fetch\\(\\)\\.$#"
|
||||
- "#^Cannot call method fetchAll\\(\\) on Doctrine\\\\DBAL\\\\Driver\\\\ResultStatement\\|int\\.$#"
|
||||
- "#^Cannot call method fetchAll\\(\\) on Doctrine\\\\DBAL\\\\Result\\|int\\.$#"
|
||||
- "#^Cannot call method fetchAllAssociative\\(\\) on Doctrine\\\\DBAL\\\\Driver\\\\ResultStatement\\|int\\.$#"
|
||||
- "#^Cannot call method fetchAllAssociative\\(\\) on Doctrine\\\\DBAL\\\\Result\\|int\\.$#"
|
||||
- "#^Cannot call method fetchColumn\\(\\) on Doctrine\\\\DBAL\\\\Driver\\\\ResultStatement\\|int\\.$#"
|
||||
- "#^Cannot call method fetchColumn\\(\\) on Doctrine\\\\DBAL\\\\Result\\|int\\.$#"
|
||||
- "#^Cannot call method fetchFirstColumn\\(\\) on Doctrine\\\\DBAL\\\\Driver\\\\ResultStatement\\|int\\.$#"
|
||||
- "#^Cannot call method fetchFirstColumn\\(\\) on Doctrine\\\\DBAL\\\\Result\\|int\\.$#"
|
||||
- "#^Cannot call method fetch\\(\\) on Doctrine\\\\DBAL\\\\Driver\\\\ResultStatement\\|int\\.$#"
|
||||
- "#^Cannot call method fetch\\(\\) on Doctrine\\\\DBAL\\\\Result\\|int\\.$#"
|
||||
- "#^Cannot call method fetchOne\\(\\) on Doctrine\\\\DBAL\\\\Driver\\\\ResultStatement\\|int\\.$#"
|
||||
|
|
Loading…
Reference in a new issue