Implement boundsMode fit.

This commit is contained in:
David Molineus
2015-01-27 00:02:17 +01:00
parent 37b10c14fe
commit e2eceab60e
20 changed files with 388 additions and 72 deletions

View File

@@ -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.
*

View File

@@ -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;
}
}

View File

@@ -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']);
}
}

View File

@@ -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()) {

View File

@@ -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 .= '&amp;f=' . $filter->getName() . '&amp;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.
*

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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) {

View File

@@ -100,6 +100,8 @@ class MapMapper extends AbstractMapper
if ($model->options) {
$map->setOptions(json_decode($model->options, true));
}
$map->setOption('dynamicLoad', (bool) $model->dynamicLoad);
}
/**

View File

@@ -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.
*

View File

@@ -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'));
}
}