forked from Snck3rs/contao-leaflet-maps
Implement boundsMode fit.
This commit is contained in:
@@ -302,6 +302,30 @@ class Layer
|
||||
->execute($dataContainer->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bounds modes supported by the layer.
|
||||
*
|
||||
* @param \DataContainer $dataContainer The data container.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getBoundsModes($dataContainer)
|
||||
{
|
||||
$options = array();
|
||||
|
||||
if ($dataContainer->activeRecord && !empty($this->layers[$dataContainer->activeRecord->type]['boundsMode'])) {
|
||||
foreach ($this->layers[$dataContainer->activeRecord->type]['boundsMode'] as $mode => $enabled) {
|
||||
if ($enabled === true) {
|
||||
$options[] = $mode;
|
||||
} elseif ($enabled === 'deferred' && $dataContainer->activeRecord->deferred) {
|
||||
$options[] = $mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a button.
|
||||
*
|
||||
|
||||
@@ -51,4 +51,37 @@ class Marker
|
||||
|
||||
return $builder->getOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the coordinates.
|
||||
*
|
||||
* @param string $value The raw data.
|
||||
* @param \DataContainer $dataContainer The data container driver.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function saveCoordinates($value, $dataContainer)
|
||||
{
|
||||
$combined = array(
|
||||
'latitude' => null,
|
||||
'longitude' => null,
|
||||
'altitude' => null
|
||||
);
|
||||
|
||||
$values = trimsplit(',', $value);
|
||||
$keys = array_keys($combined);
|
||||
|
||||
if (count($values) >= 2 && count($values) <= 3) {
|
||||
for ($i = 0; $i < count($values); $i++) {
|
||||
$combined[$keys[$i]] = $values[$i];
|
||||
}
|
||||
}
|
||||
|
||||
\Database::getInstance()
|
||||
->prepare('UPDATE tl_leaflet_marker %s WHERE id=?')
|
||||
->set($combined)
|
||||
->execute($dataContainer->id);
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
namespace Netzmacht\Contao\Leaflet\Frontend;
|
||||
|
||||
use Netzmacht\Contao\Leaflet\Filter\Filter;
|
||||
use Netzmacht\Contao\Leaflet\MapService;
|
||||
use Netzmacht\Contao\Leaflet\Model\LayerModel;
|
||||
|
||||
/**
|
||||
* The data controller handles ajax request for sub data.
|
||||
@@ -36,7 +36,9 @@ class DataController
|
||||
private $input = array(
|
||||
'format' => 'geojson',
|
||||
'type' => 'layer',
|
||||
'id' => null
|
||||
'id' => null,
|
||||
'filter' => null,
|
||||
'values' => null
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -61,7 +63,13 @@ class DataController
|
||||
public function execute()
|
||||
{
|
||||
try {
|
||||
list($data, $error) = $this->loadData($this->input['type'], $this->input['id']);
|
||||
if ($this->input['filter']) {
|
||||
$filter = $this->createFilter();
|
||||
} else {
|
||||
$filter = null;
|
||||
}
|
||||
|
||||
list($data, $error) = $this->loadData($this->input['type'], $this->input['id'], $filter);
|
||||
$this->encodeData($this->input['format'], $data);
|
||||
} catch (\Exception $e) {
|
||||
if (\Config::get('debugMode') || \Config::get('displayErrors')) {
|
||||
@@ -101,17 +109,18 @@ class DataController
|
||||
*
|
||||
* @param string $type The data type.
|
||||
* @param mixed $dataId The data id.
|
||||
* @param Filter $filter Optional request filter.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function loadData($type, $dataId)
|
||||
public function loadData($type, $dataId, Filter $filter = null)
|
||||
{
|
||||
$error = false;
|
||||
$data = null;
|
||||
|
||||
switch ($type) {
|
||||
case 'layer':
|
||||
$data = $this->mapService->getFeatureCollection($dataId);
|
||||
$data = $this->mapService->getFeatureCollection($dataId, $filter);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -122,4 +131,24 @@ class DataController
|
||||
|
||||
return array($data, $error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a filter.
|
||||
*
|
||||
* @return Filter
|
||||
* @throws \RuntimeException If the filter is not defined.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.Superglobals)
|
||||
*/
|
||||
private function createFilter()
|
||||
{
|
||||
if (!isset($GLOBALS['LEAFLET_FILTERS'][$this->input['filter']])) {
|
||||
throw new \RuntimeException(sprintf('Undefined filter "%s".', $this->input['filter']));
|
||||
}
|
||||
|
||||
/** @var Filter $filter */
|
||||
$filter = $GLOBALS['LEAFLET_FILTERS'][$this->input['filter']];
|
||||
|
||||
return $filter::fromRequest($this->input['values']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ trait HybridTrait
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \HttpRequestException If a bad leaflet param hash is given.
|
||||
* @throws \RuntimeException If a bad leaflet param hash is given.
|
||||
* @SuppressWarnings(ExitExpression)
|
||||
*/
|
||||
private function handleAjaxRequest()
|
||||
@@ -142,13 +142,15 @@ trait HybridTrait
|
||||
|
||||
// Handle ajax request.
|
||||
if ($input) {
|
||||
$data = explode(',', base64_decode($input));
|
||||
$data = explode(',', base64_decode($input));
|
||||
$data[] = $this->input->get('f');
|
||||
$data[] = $this->input->get('v');
|
||||
|
||||
if (count($data) != 4) {
|
||||
throw new \HttpRequestException('Bad request. Could not resolve query params');
|
||||
if (count($data) != 6) {
|
||||
throw new \RuntimeException('Bad request. Could not resolve query params');
|
||||
}
|
||||
|
||||
$data = array_combine(array('for', 'type', 'id', 'format'), $data);
|
||||
$data = array_combine(array('for', 'type', 'id', 'format', 'filter', 'values'), $data);
|
||||
$data = array_filter($data);
|
||||
|
||||
if (empty($data['for']) || $data['for'] != $this->getIdentifier()) {
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
namespace Netzmacht\Contao\Leaflet\Frontend;
|
||||
|
||||
use Netzmacht\Contao\Leaflet\Filter\Filter;
|
||||
|
||||
/**
|
||||
* Class RequestUrl creates the request url.
|
||||
*
|
||||
@@ -39,6 +41,13 @@ class RequestUrl implements \JsonSerializable
|
||||
*/
|
||||
private $url;
|
||||
|
||||
/**
|
||||
* Request filter.
|
||||
*
|
||||
* @var Filter|null
|
||||
*/
|
||||
private $filter;
|
||||
|
||||
/**
|
||||
* Create the request url.
|
||||
*
|
||||
@@ -47,10 +56,11 @@ class RequestUrl implements \JsonSerializable
|
||||
* @param int $dataId The data object id.
|
||||
* @param string|null $type Object type. If empty it assumes a layer.
|
||||
* @param string|null $format Data format. If empty it assumes geojson.
|
||||
* @param Filter $filter Optional filter.
|
||||
*
|
||||
* @return RequestUrl
|
||||
*/
|
||||
public static function create($dataId, $type = null, $format = null)
|
||||
public static function create($dataId, $type = null, $format = null, Filter $filter = null)
|
||||
{
|
||||
$params = array(
|
||||
'for' => static::$for,
|
||||
@@ -59,10 +69,16 @@ class RequestUrl implements \JsonSerializable
|
||||
'format' => $format != 'geojson' ? $format : null
|
||||
);
|
||||
|
||||
$hash = base64_encode(implode(',', $params));
|
||||
$url = \Config::get('websitePath') . '/' . \Frontend::addToUrl('leaflet=' . $hash, false);
|
||||
$hash = base64_encode(implode(',', $params));
|
||||
$query = 'leaflet=' . $hash;
|
||||
|
||||
return new static($url, $hash);
|
||||
if ($filter) {
|
||||
$query .= '&f=' . $filter->getName() . '&v=' . $filter->toRequest();
|
||||
}
|
||||
|
||||
$url = \Config::get('websitePath') . '/' . \Frontend::addToUrl($query, false);
|
||||
|
||||
return new static($url, $hash, $filter);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,6 +125,16 @@ class RequestUrl implements \JsonSerializable
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request filter.
|
||||
*
|
||||
* @return Filter|null
|
||||
*/
|
||||
public function getFilter()
|
||||
{
|
||||
return $this->filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to string will always return the whole url.
|
||||
*
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
namespace Netzmacht\Contao\Leaflet;
|
||||
|
||||
use Netzmacht\Contao\Leaflet\Event\GetJavascriptEvent;
|
||||
use Netzmacht\Contao\Leaflet\Filter\Filter;
|
||||
use Netzmacht\Contao\Leaflet\Mapper\DefinitionMapper;
|
||||
use Netzmacht\Contao\Leaflet\Model\LayerModel;
|
||||
use Netzmacht\Contao\Leaflet\Model\MapModel;
|
||||
@@ -68,12 +69,12 @@ class MapService
|
||||
* Get map definition.
|
||||
*
|
||||
* @param MapModel|int $mapId The map database id. MapModel accepted as well.
|
||||
* @param LatLngBounds $bounds Optional bounds where elements should be in.
|
||||
* @param Filter $filter Optional request filter.
|
||||
* @param string $elementId Optional element id. If none given the mapId or alias is used.
|
||||
*
|
||||
* @return Map
|
||||
*/
|
||||
public function getDefinition($mapId, LatLngBounds $bounds = null, $elementId = null)
|
||||
public function getDefinition($mapId, Filter $filter = null, $elementId = null)
|
||||
{
|
||||
if ($mapId instanceof MapModel) {
|
||||
$model = $mapId;
|
||||
@@ -81,7 +82,7 @@ class MapService
|
||||
$model = $this->getModel($mapId);
|
||||
}
|
||||
|
||||
return $this->mapper->handle($model, $bounds, $elementId);
|
||||
return $this->mapper->handle($model, $filter, $elementId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,13 +151,13 @@ class MapService
|
||||
* Get feature collection of a layer.
|
||||
*
|
||||
* @param LayerModel|int $layerId The layer database id or layer model.
|
||||
* @param LatLngBounds $bounds Filter features in the bounds.
|
||||
* @param Filter|null $filter Filter data.
|
||||
*
|
||||
* @return FeatureCollection
|
||||
*
|
||||
* @throws \InvalidArgumentException If a layer could not be found.
|
||||
*/
|
||||
public function getFeatureCollection($layerId, LatLngBounds $bounds = null)
|
||||
public function getFeatureCollection($layerId, Filter $filter = null)
|
||||
{
|
||||
if ($layerId instanceof LayerModel) {
|
||||
$model = $layerId;
|
||||
@@ -168,6 +169,6 @@ class MapService
|
||||
throw new \InvalidArgumentException(sprintf('Could not find layer "%s"', $layerId));
|
||||
}
|
||||
|
||||
return $this->mapper->handleGeoJson($model, $bounds);
|
||||
return $this->mapper->handleGeoJson($model, $filter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,21 +57,29 @@ class MarkersLayerMapper extends AbstractLayerMapper implements GeoJsonMapper
|
||||
$elementId = null
|
||||
) {
|
||||
if ($model->deferred) {
|
||||
if ($model->pointToLayer || $model->affectBounds) {
|
||||
if ($model->pointToLayer || $model->boundsMode) {
|
||||
$layer = new GeoJson($this->getElementId($model, $elementId));
|
||||
|
||||
if ($model->pointToLayer) {
|
||||
$layer->setPointToLayer(new Expression($model->pointToLayer));
|
||||
}
|
||||
|
||||
if ($model->affectBounds) {
|
||||
$layer->setOption('affectBounds', (bool) $model->affectBounds);
|
||||
if ($model->boundsMode) {
|
||||
$layer->setOption('boundsMode', $model->boundsMode);
|
||||
}
|
||||
|
||||
return array($this->getElementId($model, $elementId), RequestUrl::create($model->id), array(), $layer);
|
||||
return array(
|
||||
$this->getElementId($model, $elementId),
|
||||
RequestUrl::create($model->id, null, null, $filter),
|
||||
array(),
|
||||
$layer
|
||||
);
|
||||
}
|
||||
|
||||
return array($this->getElementId($model, $elementId), RequestUrl::create($model->id));
|
||||
return array(
|
||||
$this->getElementId($model, $elementId),
|
||||
RequestUrl::create($model->id, null, null, $filter)
|
||||
);
|
||||
}
|
||||
|
||||
return parent::buildConstructArguments($model, $mapper, $filter, $elementId);
|
||||
@@ -88,8 +96,8 @@ class MarkersLayerMapper extends AbstractLayerMapper implements GeoJsonMapper
|
||||
Definition $parent = null
|
||||
) {
|
||||
if ($definition instanceof GeoJson) {
|
||||
if ($model->affectBounds) {
|
||||
$definition->setOption('affectBounds', true);
|
||||
if ($model->boundsMode) {
|
||||
$definition->setOption('boundsMode', $model->boundsMode);
|
||||
}
|
||||
|
||||
$collection = $this->loadMarkerModels($model);
|
||||
@@ -117,7 +125,7 @@ class MarkersLayerMapper extends AbstractLayerMapper implements GeoJsonMapper
|
||||
public function handleGeoJson(\Model $model, DefinitionMapper $mapper, Filter $filter = null)
|
||||
{
|
||||
$feature = new FeatureCollection();
|
||||
$collection = $this->loadMarkerModels($model);
|
||||
$collection = $this->loadMarkerModels($model, $filter);
|
||||
|
||||
if ($collection) {
|
||||
foreach ($collection as $item) {
|
||||
@@ -136,12 +144,17 @@ class MarkersLayerMapper extends AbstractLayerMapper implements GeoJsonMapper
|
||||
/**
|
||||
* Load all layer markers.
|
||||
*
|
||||
* @param \Model $model The layer model.
|
||||
* @param \Model $model The layer model.
|
||||
* @param Filter $filter null The request filter.
|
||||
*
|
||||
* @return \Model\Collection|null
|
||||
*/
|
||||
protected function loadMarkerModels(\Model $model)
|
||||
protected function loadMarkerModels(\Model $model, Filter $filter = null)
|
||||
{
|
||||
return MarkerModel::findActiveBy('pid', $model->id, array('order' => 'sorting'));
|
||||
if ($model->boundsMode == 'fit') {
|
||||
return MarkerModel::findByFilter($model->id, $filter);
|
||||
}
|
||||
|
||||
return MarkerModel::findByFilter($model->id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,18 +68,26 @@ class VectorsLayerMapper extends AbstractLayerMapper implements GeoJsonMapper
|
||||
$options['onEachFeature'] = new Expression($model->onEachFeature);
|
||||
}
|
||||
|
||||
if ($model->affectBounds) {
|
||||
$options['affectBounds'] = (bool) $model->affectBounds;
|
||||
if ($model->boundsMode) {
|
||||
$options['boundsMode'] = $model->boundsMode;
|
||||
}
|
||||
|
||||
if (!empty($options)) {
|
||||
$layer = new GeoJson($this->getElementId($model, $elementId));
|
||||
$layer->setOptions($options);
|
||||
|
||||
return array($this->getElementId($model, $elementId), RequestUrl::create($model->id), array(), $layer);
|
||||
return array(
|
||||
$this->getElementId($model, $elementId),
|
||||
RequestUrl::create($model->id, null, null, $filter),
|
||||
array(),
|
||||
$layer
|
||||
);
|
||||
}
|
||||
|
||||
return array($this->getElementId($model, $elementId), RequestUrl::create($model->id));
|
||||
return array(
|
||||
$this->getElementId($model, $elementId),
|
||||
RequestUrl::create($model->id, null, null, $filter)
|
||||
);
|
||||
}
|
||||
|
||||
return parent::buildConstructArguments($model, $mapper, $filter, $elementId);
|
||||
@@ -98,8 +106,8 @@ class VectorsLayerMapper extends AbstractLayerMapper implements GeoJsonMapper
|
||||
if ($definition instanceof GeoJson) {
|
||||
$collection = $this->loadVectorModels($model);
|
||||
|
||||
if ($model->affectBounds) {
|
||||
$definition->setOption('affectBounds', true);
|
||||
if ($model->boundsMode) {
|
||||
$definition->setOption('boundsMode', $model->boundsMode);
|
||||
}
|
||||
|
||||
if ($collection) {
|
||||
|
||||
@@ -100,6 +100,8 @@ class MapMapper extends AbstractMapper
|
||||
if ($model->options) {
|
||||
$map->setOptions(json_decode($model->options, true));
|
||||
}
|
||||
|
||||
$map->setOption('dynamicLoad', (bool) $model->dynamicLoad);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -205,23 +205,38 @@ class OptionsBuilder
|
||||
public static function applyOptions($options, $definition, $model)
|
||||
{
|
||||
foreach ($options as $option => $mapping) {
|
||||
$setter = 'set' . ucfirst($option);
|
||||
$default = static::getDefaultOption($option, $definition);
|
||||
|
||||
if ($model->$mapping === '1' || $model->$mapping === '') {
|
||||
if (((bool) $model->$mapping) !== $default) {
|
||||
$definition->$setter($model->$mapping);
|
||||
static::applyOption($option, $model->$mapping, $definition);
|
||||
}
|
||||
} elseif (is_numeric($default)) {
|
||||
if ($model->$mapping != $default) {
|
||||
$definition->$setter($model->$mapping);
|
||||
static::applyOption($option, $model->$mapping, $definition);
|
||||
}
|
||||
} elseif ($model->$mapping !== $default) {
|
||||
$definition->$setter($model->$mapping);
|
||||
static::applyOption($option, $model->$mapping, $definition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $option
|
||||
* @param $value
|
||||
* @param Definition $definition
|
||||
*/
|
||||
private static function applyOption($option, $value, $definition)
|
||||
{
|
||||
$setter = 'set' . ucfirst($option);
|
||||
|
||||
if (method_exists($definition, $setter)) {
|
||||
$definition->$setter($value);
|
||||
} else {
|
||||
$definition->setOption($option, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default option value.
|
||||
*
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
|
||||
namespace Netzmacht\Contao\Leaflet\Model;
|
||||
|
||||
use Netzmacht\Contao\Leaflet\Filter\BboxFilter;
|
||||
use Netzmacht\Contao\Leaflet\Filter\Filter;
|
||||
use Netzmacht\LeafletPHP\Definition\Type\LatLngBounds;
|
||||
|
||||
/**
|
||||
* Class MarkerModel for the tl_leaflet_marker table.
|
||||
*
|
||||
@@ -24,4 +28,53 @@ class MarkerModel extends AbstractActiveModel
|
||||
* @var string
|
||||
*/
|
||||
protected static $strTable = 'tl_leaflet_marker';
|
||||
|
||||
/**
|
||||
* @param $pid
|
||||
* @param Filter $filter
|
||||
*
|
||||
* @return \Model\Collection|null
|
||||
*/
|
||||
public static function findByFilter($pid, Filter $filter = null)
|
||||
{
|
||||
if (!$filter) {
|
||||
return MarkerModel::findActiveBy('pid', $pid, array('order' => 'sorting'));
|
||||
}
|
||||
|
||||
switch ($filter->getName()) {
|
||||
case 'bbox':
|
||||
return static::findByBBoxFilter($pid, $filter);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $pid
|
||||
* @param BboxFilter $filter
|
||||
*
|
||||
* @return \Model\Collection|null
|
||||
*/
|
||||
public static function findByBBoxFilter($pid, BboxFilter $filter)
|
||||
{
|
||||
$columns = array(
|
||||
'active=1',
|
||||
'pid=?',
|
||||
'latitude > ? AND latitude < ?',
|
||||
'longitude > ? AND longitude < ?'
|
||||
);
|
||||
|
||||
/** @var LatLngBounds $bounds */
|
||||
$bounds = $filter->getValues()['bounds'];
|
||||
$values = array(
|
||||
$pid,
|
||||
$bounds->getSouthWest()->getLatitude(),
|
||||
$bounds->getNorthEast()->getLatitude(),
|
||||
$bounds->getSouthWest()->getLongitude(),
|
||||
$bounds->getNorthEast()->getLongitude()
|
||||
);
|
||||
|
||||
return static::findBy($columns, $values, array('order' => 'sorting'));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user