Files
contao-leaflet-maps/src/MapProvider.php

374 lines
10 KiB
PHP
Raw Normal View History

2014-12-29 12:17:40 +01:00
<?php
/**
2017-10-05 15:45:43 +02:00
* Leaflet maps for Contao CMS.
*
2016-10-11 10:40:15 +02:00
* @package contao-leaflet-maps
2014-12-29 12:17:40 +01:00
* @author David Molineus <david.molineus@netzmacht.de>
2017-10-05 15:45:43 +02:00
* @copyright 2016-2017 netzmacht David Molineus. All rights reserved.
* @license LGPL-3.0 https://github.com/netzmacht/contao-leaflet-maps/blob/master/LICENSE
2014-12-29 12:17:40 +01:00
* @filesource
*/
namespace Netzmacht\Contao\Leaflet;
use Doctrine\Common\Cache\Cache;
2014-12-29 12:17:40 +01:00
use Netzmacht\Contao\Leaflet\Event\GetJavascriptEvent;
2015-01-27 00:02:17 +01:00
use Netzmacht\Contao\Leaflet\Filter\Filter;
2015-01-28 16:40:48 +01:00
use Netzmacht\Contao\Leaflet\Frontend\DataController;
use Netzmacht\Contao\Leaflet\Frontend\RequestUrl;
2014-12-29 12:17:40 +01:00
use Netzmacht\Contao\Leaflet\Mapper\DefinitionMapper;
2015-01-06 14:55:53 +01:00
use Netzmacht\Contao\Leaflet\Model\LayerModel;
2014-12-29 12:17:40 +01:00
use Netzmacht\Contao\Leaflet\Model\MapModel;
use Netzmacht\LeafletPHP\Value\GeoJson\FeatureCollection;
2014-12-29 12:17:40 +01:00
use Netzmacht\LeafletPHP\Definition\Map;
use Netzmacht\LeafletPHP\Leaflet;
use Symfony\Component\EventDispatcher\EventDispatcherInterface as EventDispatcher;
/**
2016-10-05 14:18:15 +02:00
* Class MapProvider.
2014-12-29 12:17:40 +01:00
*
* @package Netzmacht\Contao\Leaflet
*/
2016-10-05 14:18:15 +02:00
class MapProvider
2014-12-29 12:17:40 +01:00
{
/**
* The definition mapper.
*
* @var DefinitionMapper
*/
private $mapper;
/**
* The leaflet service.
*
* @var Leaflet
*/
private $leaflet;
2015-01-08 23:03:01 +01:00
2014-12-29 12:17:40 +01:00
/**
2015-01-12 19:03:29 +01:00
* The event dispatcher.
*
2014-12-29 12:17:40 +01:00
* @var EventDispatcher
*/
private $eventDispatcher;
2015-01-28 16:40:48 +01:00
/**
* The request input.
*
* @var \Input
*/
private $input;
2015-02-02 08:21:47 +01:00
/**
* Map assets collector.
*
* @var ContaoAssets
2015-02-02 08:21:47 +01:00
*/
private $assets;
/**
* Request filters configuration.
*
* @var array
*/
private $filters;
/**
* Display errors setting.
*
* @var bool
*/
private $displayErrors;
/**
* Cache.
*
* @var Cache
*/
private $cache;
2014-12-29 12:17:40 +01:00
/**
* Construct.
*
* @param DefinitionMapper $mapper The definition mapper.
* @param Leaflet $leaflet The Leaflet instance.
* @param EventDispatcher $eventDispatcher The Contao event dispatcher.
2015-01-28 16:40:48 +01:00
* @param \Input $input Thw request input.
* @param ContaoAssets $assets Assets handler.
* @param Cache $cache Cache.
* @param array $filters Request filters configuration.
* @param bool $displayErrors Display errors setting.
2014-12-29 12:17:40 +01:00
*/
2015-01-28 16:40:48 +01:00
public function __construct(
DefinitionMapper $mapper,
Leaflet $leaflet,
EventDispatcher $eventDispatcher,
2015-02-02 08:21:47 +01:00
\Input $input,
ContaoAssets $assets,
Cache $cache,
array $filters,
$displayErrors
2015-01-28 16:40:48 +01:00
) {
2014-12-29 12:17:40 +01:00
$this->mapper = $mapper;
$this->leaflet = $leaflet;
$this->eventDispatcher = $eventDispatcher;
2015-01-28 16:40:48 +01:00
$this->input = $input;
2015-02-02 08:21:47 +01:00
$this->assets = $assets;
$this->filters = $filters;
$this->displayErrors = $displayErrors;
$this->cache = $cache;
2014-12-29 12:17:40 +01:00
}
/**
* Get map definition.
*
2015-01-30 19:59:51 +01:00
* @param MapModel|int $mapId The map database id. MapModel accepted as well.
* @param Filter $filter Optional request filter.
* @param string $elementId Optional element id. If none given the mapId or alias is used.
2014-12-29 12:17:40 +01:00
*
* @return Map
*/
2015-01-27 00:02:17 +01:00
public function getDefinition($mapId, Filter $filter = null, $elementId = null)
2014-12-29 12:17:40 +01:00
{
2015-01-08 23:03:01 +01:00
if ($mapId instanceof MapModel) {
$model = $mapId;
2015-01-28 16:40:48 +01:00
$mapId = $model->id;
2015-01-08 23:03:01 +01:00
} else {
$model = $this->getModel($mapId);
}
2014-12-29 12:17:40 +01:00
2015-01-28 16:40:48 +01:00
RequestUrl::setFor($elementId ?: $mapId);
$definition = $this->mapper->reset()->handle($model, $filter, $elementId);
RequestUrl::setFor(null);
return $definition;
2014-12-29 12:17:40 +01:00
}
/**
* Get map model.
*
2015-01-14 18:51:52 +01:00
* @param int|string $mapId Model id or alias.
2014-12-29 12:17:40 +01:00
*
* @return MapModel
*
* @throws \InvalidArgumentException If no model is found.
*/
public function getModel($mapId)
{
2015-01-14 18:51:52 +01:00
$model = MapModel::findByIdOrAlias($mapId);
2014-12-29 12:17:40 +01:00
if ($model === null) {
throw new \InvalidArgumentException(sprintf('Model "%s" not found', $mapId));
}
return $model;
}
/**
* Get map javascript.
*
2015-01-08 23:03:01 +01:00
* @param MapModel|int $mapId The map database id. MapModel accepted as well.
2015-01-28 16:40:48 +01:00
* @param Filter $filter Optional request filter.
2015-01-06 14:55:53 +01:00
* @param string $elementId Optional element id. If none given the mapId or alias is used.
2015-01-14 18:51:52 +01:00
* @param string $template The template being used for generating.
* @param string $style Optional style attributes.
2014-12-29 12:17:40 +01:00
*
* @return string
2015-01-15 15:30:16 +01:00
* @throws \Exception If generating went wrong.
2014-12-29 12:17:40 +01:00
*/
2015-01-14 18:51:52 +01:00
public function generate(
$mapId,
2015-01-28 16:40:48 +01:00
Filter $filter = null,
2015-01-14 18:51:52 +01:00
$elementId = null,
$template = 'leaflet_map_js',
$style = ''
) {
if ($mapId instanceof MapModel) {
$model = $mapId;
$mapId = $mapId->id;
} else {
$model = $this->getModel($mapId);
}
2015-01-14 18:51:52 +01:00
if ($model->cache) {
$cacheKey = $this->getCacheKey($mapId, $filter, $elementId, $template, $style);
if ($this->cache->contains($cacheKey)) {
$cached = $this->cache->fetch($cacheKey);
$this->assets->fromArray($cached['assets']);
2014-12-29 12:17:40 +01:00
return $cached['javascript'];
}
}
2014-12-29 12:17:40 +01:00
$buffer = $this->doGenerate($mapId, $filter, $elementId, $template, $model, $style);
if ($model->cache) {
$this->cache->save(
$cacheKey,
[
'assets' => $this->assets->toArray(),
'javascript' => $buffer
],
(int) $model->cacheLifeTime
);
}
return $buffer;
2014-12-29 12:17:40 +01:00
}
2015-01-06 14:55:53 +01:00
/**
* Get feature collection of a layer.
*
2015-01-08 23:03:01 +01:00
* @param LayerModel|int $layerId The layer database id or layer model.
2015-01-27 00:02:17 +01:00
* @param Filter|null $filter Filter data.
2015-01-06 14:55:53 +01:00
*
* @return FeatureCollection
2015-01-12 19:03:29 +01:00
*
* @throws \InvalidArgumentException If a layer could not be found.
2015-01-06 14:55:53 +01:00
*/
2015-01-27 00:02:17 +01:00
public function getFeatureCollection($layerId, Filter $filter = null)
2015-01-06 14:55:53 +01:00
{
2015-01-08 23:03:01 +01:00
if ($layerId instanceof LayerModel) {
$model = $layerId;
} else {
$model = LayerModel::findByPK($layerId);
}
2015-01-06 14:55:53 +01:00
if (!$model || !$model->active) {
throw new \InvalidArgumentException(sprintf('Could not find layer "%s"', $layerId));
}
if (!$model->cache) {
return $this->mapper->handleGeoJson($model, $filter);
}
$cacheKey = 'feature_layer_' . $model->id;
if ($filter) {
$cacheKey .= '.filter_' . md5($filter->toRequest());
}
if ($this->cache->contains($cacheKey)) {
return $this->cache->fetch($cacheKey);
}
$collection = $this->mapper->handleGeoJson($model, $filter);
$this->cache->save($cacheKey, $collection, $model->cacheLifeTime);
return $collection;
2015-01-06 14:55:53 +01:00
}
2015-01-28 16:40:48 +01:00
/**
* Handle ajax request.
*
* @param string $identifier The request identifier.
* @param bool $exit Exit if ajax request is detected.
*
2015-01-30 19:59:51 +01:00
* @return void
* @throws \RuntimeException IF the input data does not match.
*
* @SuppressWarnings(PHPMD.ExitExpression)
2015-01-28 16:40:48 +01:00
*/
public function handleAjaxRequest($identifier, $exit = true)
{
$input = $this->input->get('leaflet', true);
// Handle ajax request.
if ($input) {
$data = explode(',', base64_decode($input));
$data[] = $this->input->get('f');
$data[] = $this->input->get('v');
if (count($data) != 6) {
throw new \RuntimeException('Bad request. Could not resolve query params');
}
$data = array_combine(array('for', 'type', 'id', 'format', 'filter', 'values'), $data);
$data = array_filter($data);
if (empty($data['for']) || $data['for'] != $identifier) {
return;
}
$controller = new DataController($this, $this->filters, $this->displayErrors);
$controller->execute($data);
2015-01-28 16:40:48 +01:00
if ($exit) {
exit;
}
}
}
/**
* Get the cache key.
*
* @param int $mapId The map database id.
* @param Filter|null $filter Optional request filter.
* @param string $elementId Optional element id. If none given the mapId or alias is used.
* @param string $template The template being used for generating.
* @param string $style Optional style attributes.
*
* @return string
*/
protected function getCacheKey($mapId, $filter, $elementId, $template, $style)
{
$cacheKey = 'map_' . $mapId;
if ($filter) {
$cacheKey .= '.filter_' . md5($filter->toRequest());
}
if ($elementId) {
$cacheKey .= '.element_' . $elementId;
}
$cacheKey .= '.template_' . $template;
if ($style) {
$cacheKey .= '.style_' . md5($style);
return $cacheKey;
}
return $cacheKey;
}
/**
* Do the generating of the map.
*
* @param MapModel $model Map model.
* @param Filter|null $filter Optional request filter.
* @param string $elementId Optional element id. If none given the mapId or alias is used.
* @param string $template The template being used for generating.
* @param string $style Optional style attributes.
*
* @return string
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
*/
protected function doGenerate($model, $filter, $elementId, $template, $style)
{
$definition = $this->getDefinition($model, $filter, $elementId);
$template = \Controller::getTemplate($template);
// @codingStandardsIgnoreStart - Set for the template.
$javascript = $this->leaflet->build($definition, $this->assets);
$mapId = $definition->getId();
// @codingStandardsIgnoreEnd
ob_start();
include $template;
$content = ob_get_contents();
ob_end_clean();
$event = new GetJavascriptEvent($definition, $content);
$this->eventDispatcher->dispatch($event::NAME, $event);
$buffer = $event->getJavascript();
return $buffer;
}
2014-12-29 12:17:40 +01:00
}