initial commit

This commit is contained in:
origin
2023-12-04 16:36:56 +01:00
commit e5dd88a27c
64 changed files with 4545 additions and 0 deletions

View File

@ -0,0 +1,281 @@
<?php
declare(strict_types=1);
namespace A2G\A2gMaps\Controller;
use A2G\A2gMaps\Domain\Traits\{
InjectMapEntryRepositoryTrait,
InjectMarkerRepositoryTrait,
InjectImageServiceTrait,
InjectSysFileReferenceRepositoryTrait,
InjectObjectManagerTrait
};
use A2G\A2gMaps\Utility\MapConfigUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
use TYPO3\CMS\Fluid\View\TemplateView;
use TYPO3\CMS\Fluid\View\StandaloneView;
use TYPO3\CMS\Core\Resource\ResourceFactory;
/**
* This file is part of the "Products" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* (c) 2021 Raphael Martin <raphy.martin@gmail.com>, none
*/
/**
* MapController
*/
class MapController extends ActionController {
use InjectMapEntryRepositoryTrait;
use InjectMarkerRepositoryTrait;
use InjectImageServiceTrait;
use InjectSysFileReferenceRepositoryTrait;
private static $mapIcons = null;
/**
*
* @param UriBuilder $uriBuilder
* @param TemplateView $sourceView
* @param type $arguments
* @param type $actionName
* @param type $controllerName
* @return StandaloneView
*/
static private function generateContent(UriBuilder $uriBuilder, TemplateView &$sourceView, $arguments = [], $actionName = 'popup', $controllerName = 'Map'): StandaloneView {
$templatePath = $controllerName . '/' . ucfirst($actionName);
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$templateRootPaths = $sourceView->getTemplateRootPaths();
$context = $objectManager->get(ControllerContext::class);
$request =$objectManager->get(\TYPO3\CMS\Extbase\Mvc\Request::class);
$context->setRequest($request);
$context->setUriBuilder($uriBuilder);
/**
* @var StandaloneView $view
*/
$view = GeneralUtility::makeInstance(StandaloneView::class);
$view->setControllerContext($context);
$view->setLayoutRootPaths($sourceView->getLayoutRootPaths());
$view->setTemplateRootPaths($templateRootPaths);
$view->setPartialRootPaths($sourceView->getPartialRootPaths());
$view->setTemplate($templatePath);
$arguments['today'] = (new \DateTime())->format('d.m.Y');
$view->assignMultiple($arguments);
// \TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($arguments);
// die();
return $view;
}
private function setMapMarkerIcons(){
if (self::$mapIcons === null) {
self::$mapIcons = [];
$markers = $this->markerRepository->findAll();
foreach ($markers as $marker) {
if ($marker->getMapIcon() !== null) {
self::$mapIcons[] = [
'uid' => 'i-' . $marker->getUid(),
'icon' => $this->imageService->getImageUri($this->imageService->applyProcessingInstructions($this->imageService->getImage('', $marker->getMapIcon(), false), []), true)
];
}
}
}
}
/**
* action map
*
* @return string|object|null|void
*/
public function mapAction() {
if ((int) $this->settings['gpxData'] > 0) {
$tmp = $this->sysFileReferenceRepository->findByTablename('tt_content', (int) $this->configurationManager->getContentObject()->data['uid']);
$resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
$file = $resourceFactory->getFileReferenceObject($tmp[0]->getUid());
$showGpxData=true;
} else {
$showGpxData=false;
}
$this->setMapMarkerIcons();
if(array_key_exists('markers',$this->settings) && $this->settings['markers'] !== null){
$markers = explode(',', $this->settings['markers']);
if(count($markers)>0){
$showMarkers = true;
$this->uriBuilder->setTargetPageType(1652369510);
$markerUri = $this->uriBuilder->uriFor('mapMarkers', ['ttContentUid'=>(int) $this->configurationManager->getContentObject()->data['uid']]);
if((bool)$this->settings['showMarkerList'] === true && !empty($markers)){
if(array_key_exists('markerListOrderBy', $markers)){
$mapEntries=$this->mapEntryRepository->getFromUids($markers, $this->settings['markerListOrderBy']);
} else {
$mapEntries=$this->mapEntryRepository->getFromUids($markers);
}
$mapEntriesSort = [];
foreach($mapEntries as $mapEntrie){
if(array_key_exists($mapEntrie->getRegion(),$mapEntriesSort)){
$mapEntriesSort[$mapEntrie->getRegion()][]=$mapEntrie;
} else {
$mapEntriesSort[$mapEntrie->getRegion()]=[];
$mapEntriesSort[$mapEntrie->getRegion()][]=$mapEntrie;
}
}
$this->view->assign('mapEntries', $mapEntriesSort);
}
} else {
$showMarkers = false;
}
}else {
$showMarkers = false;
}
if(array_key_exists('layers',$this->settings) && $this->settings['layers'] !== null){
$layerIds = explode(',', $this->settings['layers']);
} else {
$layerIds = [];
}
$this->view->assignMultiple([
'mapId' => 'a2g-map-' . uniqid(),
'countMapLayers' => count($layerIds),
'mapIcons' => \GuzzleHttp\json_encode(self::$mapIcons),
'mapConfig' => \GuzzleHttp\json_encode(MapConfigUtility::getMapConfig(
$layerIds,
$showGpxData === true ? $file->getOriginalFile()->getPublicUrl() : null,
$showMarkers === true ? $markerUri : null,
$this->settings['defaultMapMarker'],
(int)$this->settings['zoom'],
(int)$this->settings['maxZoom'], (float)$this->settings['centerLon'], (float)$this->settings['centerLat'],
(bool)$this->settings['useZoomSlider'], (bool)$this->settings['useFullscreenButton'], (bool)$this->settings['useLayerSwitcher']))
]);
}
/**
* action mapMarkers
*
* @return string|object|null|void
*/
public function mapMarkersAction() {
if($this->mapEntryRepository->findAll()->count() > 0){
$markersUids = $this->mapEntryRepository->getEntriesFromMap((int)GeneralUtility::_GET('tx_a2gmaps_map')['ttContentUid']);
$markers = $this->mapEntryRepository->getFromUids($markersUids);
if($markers===null){
$markers = [];
}
} else {
$markers=[];
}
$out = [
"type" => "FeatureCollection",
"totalFeatures" => count($markers),
"csr" => MapConfigUtility::getMarkerCsr(),
"features" => []
];
foreach ($markers as $marker) {
if ($marker->getRelMarker() !== null) {
$tmpIcon = "i-" . $marker->getRelMarker()->getUid();
} else {
$tmpIcon = null;
}
$out["features"][] = MapConfigUtility::getMarker($marker, $tmpIcon, self::generateContent( $this->uriBuilder, $this->view, ['mapEntry' => $marker ])->render());
}
return \GuzzleHttp\json_encode($out);
}
/**
* action popup
*
* @return string|object|null|void
*/
public function MapEntry() {
}
/**
* action list
*
* @return string|object|null|void
*/
public function listAction() {
}
/**
* action ajaxListAction
*
* @return string|object|null|void
*/
public function ajaxListAction() {
}
// /**
// * action show
// *
// * @param Ingredients $ingredient
// * @return string|object|null|void
// */
// public function showAction(Ingredients $ingredient) {
// $titleProvider = GeneralUtility::makeInstance(A2gPageTitleProvider::class);
//
// if($this->settings['pageTitleSuffix'] !== null && $this->settings['pageTitleSuffix'] !== '' && (strlen($ingredient->getTitle()) + strlen($this->settings['pageTitleSuffix'])) < 66 ){
// $pageTitle = $ingredient->getTitle(). ' ' . $this->settings['pageTitleSuffix'];
// } else {
// $pageTitle = $ingredient->getTitle();
// }
// $titleProvider->setTitle($pageTitle);
// $contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
// $description = $contentObject->crop($ingredient->getDescription(), 125 . '|...|' . true);
//
// $uri = $this->uriBuilder->reset()->setCreateAbsoluteUri(true)->setTargetPageUid(
// $GLOBALS['TSFE']->id)->uriFor('show', ['ingredient' => $ingredient], 'Ingredients', 'a2gProducts', 'ingredientsdetail');
//
// $metaTagManager = GeneralUtility::makeInstance(MetaTagManagerRegistry::class);
//
// $metaTagManager->getManagerForProperty('robots')->addProperty('robots', 'index, folow');
// $metaTagManager->getManagerForProperty('og:type')->addProperty('og:type', 'website');
// $metaTagManager->getManagerForProperty('twitter:card')->addProperty('twitter:card', 'summary_large_image');
//
// if ($ingredient->getTitle() !== '') {
// $metaTagManager->getManagerForProperty('title')->addProperty('title', $pageTitle);
// $metaTagManager->getManagerForProperty('og:title')->addProperty('og:title', $pageTitle);
// $metaTagManager->getManagerForProperty('twitter:title')->addProperty('twitter:title', $pageTitle);
// }
// if ($ingredient->getDescription() !== '') {
// $metaTagManager->getManagerForProperty('description')->addProperty('description', $description);
// $metaTagManager->getManagerForProperty('og:description')->addProperty('og:description', $description);
// $metaTagManager->getManagerForProperty('twitter:description')->addProperty('twitter:description', $description);
// }
// $metaTagManager->getManagerForProperty('og:url')->addProperty('og:url', $uri);
// $metaTagManager->getManagerForProperty('twitter:url')->addProperty('twitter:url', $uri);
//
// if ($ingredient->getImage() !== null) {
// $processedImage = $this->imageService->applyProcessingInstructions(
// $this->imageService->getImage('', $ingredient->getImage(), false),
// ['width' => '
// 1200', 'height' => '630c']
// );
// $metaTagManager->getManagerForProperty('twitter:image')->addProperty('twitter:image', $this->imageService->getImageUri($processedImage, true));
// $metaTagManager->getManagerForProperty('og:image')->addProperty('og:image', $this->imageService->getImageUri($processedImage, true));
// }
// $this->view->assign('ingredient', $ingredient);
// }
}

281
Classes/Domain/Model/MapEntry.php Executable file
View File

@ -0,0 +1,281 @@
<?php
declare(strict_types=1);
namespace A2G\A2gMaps\Domain\Model;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
use TYPO3\CMS\Extbase\Domain\Model\FileReference;
use TYPO3\CMS\Extbase\Annotation\ORM\{
Cascade,
Lazy
};
use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy;
/**
* This file is part of the "altogether Products" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* (c) 2021 Raphael Martin <raphy.martin@gmail.com>, none
*/
/**
* MapEntry
*/
class MapEntry extends AbstractEntity {
/**
*
* @var string
*/
protected $addressline = '';
/**
*
* @var string
*/
protected $zip = '';
/**
*
* @var string
*/
protected $city = '';
/**
*
* @var string
*/
protected $region = '';
/**
* latitude
*
* @var float
*/
protected $latitude = 0.0;
/**
* longitude
*
* @var float
*/
protected $longitude = 0.0;
/**
* title
*
* @var string
*/
protected $title = '';
/**
* pathSegment
*
* @var string
*/
protected $pathSegment = '';
/**
* popupContent
*
* @var string
*/
protected $popupContent = '';
/**
*
* @var string
*/
protected $navToUrl = '';
/**
* image
*
* @var FileReference
* @Cascade("remove")
* @Lazy
*/
protected $image = null;
/**
* relMarker
*
* @var Marker
* @Lazy
*/
protected $relMarker = null;
/**
*
* @return float
*/
public function getLatitude(): float {
return $this->latitude;
}
/**
*
* @return float
*/
public function getLongitude(): float {
return $this->longitude;
}
/**
*
* @return string
*/
public function getTitle(): string {
return $this->title;
}
/**
*
* @return string
*/
public function getPathSegment(): string {
return $this->pathSegment;
}
/**
*
* @return null|Marker
*/
public function getRelMarker(): ?Marker {
if ($this->relMarker instanceof LazyLoadingProxy) {
$this->relMarker = $this->relMarker->_loadRealInstance();
}
return $this->relMarker;
}
/**
*
* @param Marker $relMarker
* @return void
*/
public function setRelMarker(?Marker $relMarker): void {
$this->relMarker = $relMarker;
}
/**
*
* @return null|FileReference
*/
public function getImage(): ?FileReference {
if ($this->image instanceof LazyLoadingProxy) {
$this->image = $this->image->_loadRealInstance();
}
return $this->image;
}
/**
*
* @param float $latitude
* @return void
*/
public function setLatitude(float $latitude): void {
$this->latitude = $latitude;
}
/**
*
* @param float $longitude
* @return void
*/
public function setLongitude(float $longitude): void {
$this->longitude = $longitude;
}
/**
*
* @param string $title
* @return void
*/
public function setTitle(string $title): void {
$this->title = $title;
}
/**
*
* @param string $pathSegment
* @return void
*/
public function setPathSegment(string $pathSegment): void {
$this->pathSegment = $pathSegment;
}
/**
*
* @param null|FileReference $image
* @return void
*/
public function setImage(?FileReference $image): void {
$this->image = $image;
}
/**
*
* @return string
*/
public function getPopupContent(): string {
return $this->popupContent;
}
/**
*
* @param string $popupContent
* @return void
*/
public function setPopupContent(string $popupContent): void {
$this->popupContent = $popupContent;
}
public function getAddressline(): string {
return $this->addressline;
}
public function getZip(): string {
return $this->zip;
}
public function getCity(): string {
return $this->city;
}
public function getRegion(): string {
return $this->region;
}
public function setAddressline(string $addressline): void {
$this->addressline = $addressline;
}
public function setZip(string $zip): void {
$this->zip = $zip;
}
public function setCity(string $city): void {
$this->city = $city;
}
public function setRegion(string $region): void {
$this->region = $region;
}
public function getNavToUrl(): string {
return $this->navToUrl;
}
public function setNavToUrl(string $navToUrl): void {
$this->navToUrl = $navToUrl;
}
}

56
Classes/Domain/Model/Marker.php Executable file
View File

@ -0,0 +1,56 @@
<?php
declare(strict_types=1);
namespace A2G\A2gMaps\Domain\Model;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
use TYPO3\CMS\Extbase\Domain\Model\FileReference;
use TYPO3\CMS\Extbase\Annotation\ORM\{
Cascade,
Lazy
};
use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy;
/**
* This file is part of the "altogether Products" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* (c) 2021 Raphael Martin <raphy.martin@gmail.com>, none
*/
/**
* Marker
*/
class Marker extends AbstractEntity {
/**
* mapIcon
*
* @var FileReference
* @Cascade("remove")
* @Lazy
*/
protected $mapIcon = null;
/**
*
* @return null|FileReference
*/
public function getMapIcon(): ?FileReference {
if ($this->mapIcon instanceof LazyLoadingProxy) {
$this->mapIcon = $this->mapIcon->_loadRealInstance();
}
return $this->mapIcon;
}
/**
*
* @return string
*/
public function getMapConfig(): string {
return $this->mapConfig;
}
}

View File

@ -0,0 +1,18 @@
<?php
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Scripting/PHPClass.php to edit this template
*/
namespace A2G\A2gMaps\Domain\Model;
use TYPO3\CMS\Extbase\Domain\Model\FileReference;
/**
* Description of SysFileReference
*
* @author raphael
*/
class SysFileReference extends FileReference {
//put your code here
}

View File

@ -0,0 +1,79 @@
<?php
declare(strict_types=1);
namespace A2G\A2gMaps\Domain\Repository;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
/**
* This file is part of the "Products" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* (c) 2021 Raphael Martin <raphy.martin@gmail.com>, none
*/
/**
* The repository for MapEntry
*/
class MapEntryRepository extends \TYPO3\CMS\Extbase\Persistence\Repository {
/**
* @var array
*/
// protected $defaultOrderings = [
// 'sorting' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING
// ];
public function initializeObject() {
$querySettings = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings::class);
$querySettings->setRespectStoragePage(false);
$this->setDefaultQuerySettings($querySettings);
}
static private function mapInt($value){
if(MathUtility::canBeInterpretedAsInteger($value)){
return (int)$value;
} else {
return null;
}
}
public function getFromUids(array $uids, ?string $orderBy = null){
$arguments = [];
$uidsFiltered = array_filter(array_map('self::mapInt', $uids));
if(count($uidsFiltered) === 0){
return null;
}
$query = $this->createQuery();
$sql = 'SELECT meT.* FROM tx_a2gmaps_domain_model_mapentry AS meT ';
$sqlWhere = 'WHERE meT.hidden=0 AND meT.deleted=0 AND meT.uid IN ('.implode(',', $uidsFiltered).')';
$query->statement($sql . $sqlWhere, $arguments);
return $query->execute();
}
public function getEntriesFromMap(int $ttContentUid){
$query = $this->createQuery();
$sql = 'SELECT tcT.* FROM tt_content AS tcT ';
$sqlWhere = 'WHERE tcT.hidden=0 AND tcT.deleted=0 AND tcT.uid = :dcUid ';
$arguments = [
':dcUid' => $ttContentUid
];
$query->statement($sql . $sqlWhere, $arguments);
return explode(',',GeneralUtility::xml2array($query->execute(1)[0]['pi_flexform'])['data']['sDEF']['lDEF']['settings.markers']['vDEF']);
}
}

View File

@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace A2G\A2gMaps\Domain\Repository;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* This file is part of the "Products" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* (c) 2021 Raphael Martin <raphy.martin@gmail.com>, none
*/
/**
* The repository for Marker
*/
class MarkerRepository extends \TYPO3\CMS\Extbase\Persistence\Repository {
/**
* @var array
*/
// protected $defaultOrderings = [
// 'sorting' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING
// ];
public function initializeObject() {
$querySettings = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings::class);
$querySettings->setRespectStoragePage(false);
$this->setDefaultQuerySettings($querySettings);
}
}

View File

@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
namespace A2G\A2gMaps\Domain\Repository;
/**
* This file is part of the "Products" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* (c) 2021 Raphael Martin <raphy.martin@gmail.com>, none
*/
/**
* The repository for SysFileReference
*/
class SysFileReferenceRepository extends \TYPO3\CMS\Extbase\Persistence\Repository {
/**
* @var array
*/
// protected $defaultOrderings = [
// 'sorting' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING
// ];
public function initializeObject() {
$querySettings = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings::class);
$querySettings->setRespectStoragePage(false);
$this->setDefaultQuerySettings($querySettings);
}
public function findByTablename(string $tableName, int $uid){
$query = $this->createQuery();
$sql = 'SELECT sfrT.* FROM sys_file_reference AS sfrT ';
$sqlWhere = 'WHERE sfrT.hidden=0 AND sfrT.deleted=0 AND sfrT.tablenames = :dcTablename AND sfrT.uid_foreign = :dcUid ';
$arguments = [
':dcTablename' => $tableName,
':dcUid' => $uid
];
$query->statement($sql . $sqlWhere, $arguments);
return $query->execute();
}
}

View File

@ -0,0 +1,35 @@
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
declare(strict_types=1);
namespace A2G\A2gMaps\Domain\Traits;
use TYPO3\CMS\Extbase\Service\ImageService;
/**
* Description of InjectImageServiceTrait
*
* @author Raphael Martin
*/
trait InjectImageServiceTrait {
/**
* imageService
*
* @var ImageService
*/
protected $imageService = null;
/**
* @param ImageService $imageService
*/
public function injectImageService(ImageService $imageService) {
$this->imageService = $imageService;
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace A2G\A2gMaps\Domain\Traits;
use A2G\A2gMaps\Domain\Repository\MapEntryRepository;
/**y
* Description of InjectMapEntryRepositoryTrait
*
* @author Raphael Martin
*/
trait InjectMapEntryRepositoryTrait {
/**
*
* @var MapEntryRepository
*/
protected $mapEntryRepository = null;
/**
* @param MapEntryRepository $mapEntryRepository
*/
public function injectMapEntryRepository(MapEntryRepository $mapEntryRepository) {
$this->mapEntryRepository = $mapEntryRepository;
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace A2G\A2gMaps\Domain\Traits;
use A2G\A2gMaps\Domain\Repository\MarkerRepository;
/**y
* Description of InjectMarkerRepositoryTrait
*
* @author Raphael Martin
*/
trait InjectMarkerRepositoryTrait {
/**
*
* @var MarkerRepository
*/
protected $markerRepository = null;
/**
* @param MarkerRepository $markerRepository
*/
public function injectMarkerRepository(MarkerRepository $markerRepository) {
$this->markerRepository = $markerRepository;
}
}

View File

@ -0,0 +1,21 @@
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
* declare(strict_types=1);
namespace A2G\A2gMaps\Domain\Traits;
use TYPO3\CMS\Extbase\Object\ObjectManager;
/**
* Description of InjectObjectManagerTrait
*
* @author Raphael Martin
*/

View File

@ -0,0 +1,27 @@
<?php
namespace A2G\A2gMaps\Domain\Traits;
use A2G\A2gMaps\Domain\Repository\SysFileReferenceRepository;
/**y
* Description of InjectSysFileReferenceRepositoryTrait
*
* @author Raphael Martin
*/
trait InjectSysFileReferenceRepositoryTrait {
/**
*
* @var SysFileReferenceRepository
*/
protected $sysFileReferenceRepository = null;
/**
* @param SysFileReferenceRepository $sysFileReferenceRepository
*/
public function injectSysFileReferenceRepository(SysFileReferenceRepository $sysFileReferenceRepository) {
$this->sysFileReferenceRepository = $sysFileReferenceRepository;
}
}

View File

@ -0,0 +1,70 @@
<?php
declare(strict_types = 1);
namespace A2G\A2gMaps\FormEngine\FieldControl;
/**
* This file is part of the "tt_address" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*/
use TYPO3\CMS\Backend\Form\AbstractNode;
use TYPO3\CMS\Core\Localization\LanguageService;
/**
* Adds a wizard for location selection via map
*/
class LocationMapWizard extends AbstractNode
{
/**
* @return array
*/
public function render(): array
{
$row = $this->data['databaseRow'];
$paramArray = $this->data['parameterArray'];
$resultArray = $this->initializeResultArray();
$nameLongitude = $paramArray['itemFormElName'];
$nameLatitude = str_replace('longitude', 'latitude', $nameLongitude);
$nameLatitudeActive = str_replace('data', 'control[active]', $nameLatitude);
$geoCodeUrl = $geoCodeUrlShort = '';
$gLat = '55.6760968';
$gLon = '12.5683371';
$lat = $row['latitude'] != 0 ? (string)$row['latitude'] : '0.0';
$lon = $row['longitude'] != 0 ? (string)$row['longitude'] : '0.0';
$resultArray['iconIdentifier'] = 'location-map-wizard';
$resultArray['title'] = $this->getLanguageService()->sL('LLL:EXT:tt_address/Resources/Private/Language/locallang_db.xlf:tt_address.locationMapWizard');
$resultArray['linkAttributes']['class'] = 'locationMapWizard ';
$resultArray['linkAttributes']['data-label-title'] = $this->getLanguageService()->sL('LLL:EXT:tt_address/Resources/Private/Language/locallang_db.xlf:tt_address.locationMapWizard');
$resultArray['linkAttributes']['data-label-close'] = $this->getLanguageService()->sL('LLL:EXT:tt_address/Resources/Private/Language/locallang_db.xlf:tt_address.locationMapWizard.close');
$resultArray['linkAttributes']['data-label-import'] = $this->getLanguageService()->sL('LLL:EXT:tt_address/Resources/Private/Language/locallang_db.xlf:tt_address.locationMapWizard.import');
$resultArray['linkAttributes']['data-lat'] = $lat;
$resultArray['linkAttributes']['data-lon'] = $lon;
$resultArray['linkAttributes']['data-glat'] = $gLat;
$resultArray['linkAttributes']['data-glon'] = $gLon;
$resultArray['linkAttributes']['data-geocodeurl'] = $geoCodeUrl;
$resultArray['linkAttributes']['data-geocodeurlshort'] = $geoCodeUrlShort;
$resultArray['linkAttributes']['data-namelat'] = htmlspecialchars($nameLatitude);
$resultArray['linkAttributes']['data-namelon'] = htmlspecialchars($nameLongitude);
$resultArray['linkAttributes']['data-namelat-active'] = htmlspecialchars($nameLatitudeActive);
$resultArray['linkAttributes']['data-tiles'] = htmlspecialchars('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
$resultArray['linkAttributes']['data-copy'] = '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
$resultArray['stylesheetFiles'][] = 'EXT:tt_address/Resources/Public/Contrib/leaflet-core-1.4.0.css';
$resultArray['stylesheetFiles'][] = 'EXT:tt_address/Resources/Public/Backend/LocationMapWizard/leafletBackend.css';
$resultArray['requireJsModules'][] = 'TYPO3/CMS/TtAddress/leaflet-core-1.4.0';
$resultArray['requireJsModules'][] = 'TYPO3/CMS/TtAddress/LeafletBackend';
return $resultArray;
}
/**
* @return LanguageService
*/
protected function getLanguageService(): LanguageService
{
return $GLOBALS['LANG'];
}
}

View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace A2G\A2gMaps\Hooks;
use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use A2G\A2gMaps\Utility\MapConfigUtility;
class MapEntryDataHandlerHooks {
/**
* @param string|int $id
*/
public function processDatamap_postProcessFieldArray(
string $status, // Status of the current operation, 'new' or 'update'
string $table, // The table currently processing data for
$id, // The record uid currently processing data for,
// [integer] or [string] (like 'NEW...')
array &$fieldArray, // The field array of a record, cleaned to only
// 'to-be-changed' values. Needs to be &$fieldArray to be considered reference.
DataHandler $dataHandler
): void
{
if ($table === 'tx_a2gmaps_domain_model_mapentry') {
if( ( $fieldArray['latitude'] === 0.0 || $fieldArray['longitude'] === 0.0 ) || $fieldArray['nav_to_url'] === ''){
if($fieldArray['nav_to_url'] === '' && ($fieldArray['latitude'] != 0.0 || $fieldArray['longitude'] != 0.0 )){
} else if($fieldArray['city'] !== '' && $fieldArray['zip'] !== '' && $fieldArray['addressline'] !== ''){
$latLon = MapConfigUtility::getLatLonFrom($fieldArray['addressline'], $fieldArray['zip'] === '' ? $fieldArray['city'] : $fieldArray['zip'].' '.$fieldArray['city']);
$fieldArray['latitude'] = (float)$latLon['lat'];
$fieldArray['longitude'] = (float)$latLon['lon'];
$fieldArray['nav_to_url'] = MapConfigUtility::getNavToLink($fieldArray['addressline'], $fieldArray['zip'] === '' ? $fieldArray['city'] : $fieldArray['zip'].' '.$fieldArray['city']);
}
}
}
}
}

View File

@ -0,0 +1,95 @@
<?php
declare(strict_types=1);
namespace A2G\A2gMaps\Utility;
/**
* This file is part of the "tt_address" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*/
/**
* Class EvalcoordinatesUtility
*/
class EvalcoordinatesUtility
{
const LATITUDE_UPPER = '90.00000000';
const LONGITUDE_UPPER = '180.00000000';
/**
* @param float $coordinate
* @return float evaluated and well-formed coordinate
*/
public static function formatLongitude(float $coordinate)
{
return self::validate((string)$coordinate, self::LONGITUDE_UPPER);
}
/**
* @param float $coordinate
* @return float evaluated and well-formed coordinate
*/
public static function formatLatitude(float $coordinate)
{
return self::validate((string)$coordinate, self::LATITUDE_UPPER);
}
/**
* @param string $coordinate
* @param string $upperRange
* @return string
*/
protected static function validate($coordinate, string $upperRange): string
{
if ($coordinate === '') {
return '.00000000';
}
// test if value is negative
$negative = '';
if ($coordinate[0] === '-') {
$negative = '-';
}
// remove all chars not being digits and point
// therefore we will get a number
$coordinate = preg_replace("/[^\d\.]/", '', $coordinate);
// split up string at first occurrence decimal point without losing data
$integerPart = strstr($coordinate, '.', true);
$decimalPart = strstr($coordinate, '.');
// if coordinate is given as integer (no decimal point)
if ($integerPart === false) {
$integerPart = $coordinate;
}
if ($decimalPart === false) {
$decimalPart = '00';
}
// remove all points from decimal-part
$decimalPart = preg_replace("/[^\d]/", '', $decimalPart);
// fill up with zeros or shorten to match our goal of decimal(latitude: 10,8 and longitude: 11,8) in DB
if (\strlen($decimalPart) >= 8) {
$decimalPart = substr($decimalPart, 0, 8);
} else {
$decimalPart = str_pad($decimalPart, 8, '0', STR_PAD_RIGHT);
}
// concatenate the whole string to a well-formed longitude and return
$coordinate = $integerPart . '.' . $decimalPart;
// test if value is in the possible range. longitude can be -180 to +180.
// latitude can be -90 to +90
// At this point, our minus, if there, is stored to 'negative'
// therefore we just test if integerpart is bigger than 90
if ($coordinate > $upperRange) {
$coordinate = $upperRange;
}
// reapply signed/unsigned and return
return $negative . $coordinate;
}
}

View File

@ -0,0 +1,386 @@
<?php
declare(strict_types=1);
namespace A2G\A2gMaps\Utility;
use TYPO3\CMS\Extbase\Annotation as Extbase;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use A2G\A2gMaps\Domain\Model\MapEntry;
use GuzzleHttp\Client;
/**
* Description of Canonical
*
* @author Raphael Martin raphael@web-crossing.com
*/
class MapConfigUtility {
/**
* uidParamName
*
* @var string
*/
static private $mapLayerConfigs = [
1 => [
"layer" => "osm",
"config" => [
],
"label" => "osm_map_layer"
],
10 => [
"layer" => "stamen",
"config" => [
"layer" => "terrain"
],
"label" => "stamen_map_terrain"
],
11 => [
"layer" => "stamen",
"config" => [
"layer" => "watercolor"
],
"label" => "stamen_map_watercolor"
],
12 => [
"layer" => "stamen",
"config" => [
"layer" => "toner"
],
"label" => "stamen_map_toner"
],
100 => [
"layer" => "thunderforest",
"config" => [
"layer" => "cycle"
],
"label" => "thunderforest_map_cycle"
],
101 => [
"layer" => "thunderforest",
"config" => [
"layer" => "transport"
],
"label" => "thunderforest_map_transport"
],
102 => [
"layer" => "thunderforest",
"config" => [
"layer" => "landscape"
],
"label" => "thunderforest_map_landscape"
],
103 => [
"layer" => "thunderforest",
"config" => [
"layer" => "outdoors"
],
"label" => "thunderforest_map_outdoors"
],
104 => [
"layer" => "thunderforest",
"config" => [
"layer" => "atlas"
],
"label" => "thunderforest_map_atlas"
],
105 => [
"layer" => "thunderforest",
"config" => [
"layer" => "transport-dark"
],
"label" => "thunderforest_map_transport-dark"
],
106 => [
"layer" => "thunderforest",
"config" => [
"layer" => "spinal-map"
],
"label" => "thunderforest_map_spinal"
],
107 => [
"layer" => "thunderforest",
"config" => [
"layer" => "pioneer"
],
"label" => "thunderforest_map_pioneer"
],
108 => [
"layer" => "thunderforest",
"config" => [
"layer" => "neighbourhood"
],
"label" => "thunderforest_map_neighbourhood"
],
109 => [
"layer" => "thunderforest",
"config" => [
"layer" => "mobile-atlas"
],
"label" => "thunderforest_map_mobile-atlas"
],
200 => [
"layer" => "maptiler",
"config" => [
"layer" => "basic"
],
"label" => "maptiler_map_basic"
],
201 => [
"layer" => "maptiler",
"config" => [
"layer" => "basic-4326"
],
"label" => "maptiler_map_basic-4326"
],
202 => [
"layer" => "maptiler",
"config" => [
"layer" => "bright"
],
"label" => "maptiler_map_bright"
],
203 => [
"layer" => "maptiler",
"config" => [
"layer" => "openstreetmap"
],
"label" => "maptiler_map_openstreetmap"
],
204 => [
"layer" => "maptiler",
"config" => [
"layer" => "outdoor"
],
"label" => "maptiler_map_outdoor"
],
205 => [
"layer" => "maptiler",
"config" => [
"layer" => "pastel"
],
"label" => "maptiler_map_pastel"
],
206 => [
"layer" => "maptiler",
"config" => [
"layer" => "hybrid"
],
"label" => "maptiler_map_hybrid"
],
207 => [
"layer" => "maptiler",
"config" => [
"layer" => "streets"
],
"label" => "maptiler_map_streets"
],
208 => [
"layer" => "maptiler",
"config" => [
"layer" => "toner"
],
"label" => "maptiler_map_toner"
],
209 => [
"layer" => "maptiler",
"config" => [
"layer" => "topo"
],
"label" => "maptiler_map_topo"
],
210 => [
"layer" => "maptiler",
"config" => [
"layer" => "topographique"
],
"label" => "maptiler_map_topographique"
],
211 => [
"layer" => "maptiler",
"config" => [
"layer" => "voyager"
],
"label" => "maptiler_map_voyager"
],
212 => [
"layer" => "maptiler",
"config" => [
"layer" => "winter"
],
"label" => "maptiler_map_winter"
],
];
/**
* setCanonical
*
* @param type $href
*/
public static function getMapLayerConfig(array $mapLayerConfigIds) {
$out = [];
foreach ($mapLayerConfigIds as $id) {
$out[] = self::$mapLayerConfigs[$id];
}
return $out;
}
public static function getMapConfig(array $mapLayerConfigIds, ?string $gpxSource = null, ?string $markerSource = null,
?string $defaultMarkerIcon = null,
int $zoom = 1, int $maxZoom = 18, float $centerLon = 0.0, float $centerLat = 0.0,
bool $zoomSlider = false, bool $fullScreen = false, bool $useLayerSwitcher = false): array {
$out = [
'zoom' => $zoom,
'maxZoom' => $maxZoom,
'centerLon' => $centerLon,
'centerLat' => $centerLat
];
$out['mapLayers'] = self::getMapLayerConfig($mapLayerConfigIds);
if ($useLayerSwitcher) {
for ($i = 0; $i < count($out['mapLayers']); $i++) {
$out['mapLayers'][$i]['active'] = true;
}
}
if ($defaultMarkerIcon !== null) {
$out['defaultMarkerIcon'] = $defaultMarkerIcon;
}
if ($gpxSource !== null) {
$out['gpxSource'] = $gpxSource;
}
if ($markerSource !== null) {
$out['markerSource'] = $markerSource;
}
if ($zoomSlider) {
$out['zoomSlider'] = $zoomSlider;
}
if ($fullScreen) {
$out['fullScreen'] = $fullScreen;
}
return $out;
}
static public function getMarkerCsr() {
return [
"type" => "name",
"properties" => [
"name" => "urn:ogc:def:crs:EPSG::4326"
]
];
}
static public function getMarker(MapEntry $marker, ?string $icon, ?string $popupContent) {
$out = [
"type" => "Feature",
"id" => $marker->getUid(),
"geometry" => [
"type" => "Point",
"coordinates" => [
$marker->getLongitude(),
$marker->getLatitude()
]
],
"geometry_name" => "SHAPE",
"properties" => [
'icon' => $icon
]
];
if ($popupContent !== null) {
$out['properties']['popup'] = $popupContent;
}
return $out;
}
static private $countryCoordinates = null;
private static function getCountryGeoJson(string $twoIsoCode = ''): ?array {
if (self::$countryCoordinates === null) {
self::$countryCoordinates = \GuzzleHttp\json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/typo3conf/ext/a2g_travel_blog/Resources/Public/sampleData/countries.json'), true);
}
if (self::$countryCoordinates[strtoupper($twoIsoCode)]) {
return self::$countryCoordinates[strtoupper($twoIsoCode)][0];
} else {
return null;
}
}
static protected $nominationBaseUrl = 'https://nominatim.openstreetmap.org';
static protected $nominationSufixUrl = '&format=json&polygon=1&addressdetails=1';
static protected $client = null;
static protected function initClient(){
if(self::$client===null){
self::$client = new Client([
// Base URI is used with relative requests
'base_uri' => self::$nominationBaseUrl,
// You can set any number of default request options.
'timeout' => 2.0,
]);
}
}
static public function getLatLonFrom(string $addressline, string $countryline, string $state = ''): ?array {
self::initClient();
if ($state === '') {
$url = urlencode($addressline . ',' . $countryline);
} else {
$url = urlencode($addressline . ',' . $countryline . ',' . $state);
}
$response = self::$client->request('GET', self::$nominationBaseUrl.'/search?q='.$url.self::$nominationSufixUrl);
if($response->getStatusCode() === 200){
return \GuzzleHttp\json_decode($response->getBody()->getContents(), true)[0];
}
return null;
}
public static function getNavToLink(string $addressline, string $countryline, string $state = ''): string{
if ($state === '') {
$url = str_replace(' ', '+', $addressline . ',' . $countryline);
} else {
$url = str_replace(' ', '+', $addressline . ',' . $countryline . ',' . $state);
}
return 'https://www.google.com/maps/dir//'. urlencode($url);
}
public static function getCountryFeatureCollectionsFromIsoCodeList(array $isoCodes = ['DE' => 'popupcontent de', 'AT' => 'popupcontent at']) {
$out = [
'type' => 'FeatureCollection',
'crs' => [
'type' => 'name',
'properties' => [
'name' => 'urn:ogc:def:crs:OGC:1.3:CRS84'
]
],
'features' => []
];
foreach ($isoCodes as $twoIsoCode => $isoCodePopupcontent) {
if ($isoCodePopupcontent === null) {
$out['features'][] = [
'type' => 'Feature',
'properties' => [
],
'geometry' => self::getCountryGeoJson($twoIsoCode)
];
} else {
$out['features'][] = [
'type' => 'Feature',
'properties' => [
'popup' => $isoCodePopupcontent
],
'geometry' => self::getCountryGeoJson($twoIsoCode)
];
}
}
return $out;
}
}