diff --git a/composer.json b/composer.json
index 95221a5..79eef63 100644
--- a/composer.json
+++ b/composer.json
@@ -24,7 +24,9 @@
"contao-community-alliance/event-dispatcher":"~1.0",
"netzmacht/php-javascript-builder": "~1.0",
"netzmacht/php-leaflet": "dev-master",
- "bit3/contao-meta-palettes": "~1.5"
+ "bit3/contao-meta-palettes": "~1.5",
+ "menatwork/contao-multicolumnwizard": "~3.2",
+ "doctrine/cache": "~1.0"
},
"require-dev":{
"netzmacht/contao-build-tools": "1.0.x-dev"
diff --git a/module/assets/.htaccess b/module/assets/.htaccess
new file mode 100644
index 0000000..28cc359
--- /dev/null
+++ b/module/assets/.htaccess
@@ -0,0 +1,7 @@
+
+ Order allow,deny
+ Allow from all
+
+
+ Require all granted
+
\ No newline at end of file
diff --git a/module/assets/img/leaflet.png b/module/assets/img/leaflet.png
new file mode 100644
index 0000000..51c29cd
Binary files /dev/null and b/module/assets/img/leaflet.png differ
diff --git a/module/assets/js/contao-leaflet.js b/module/assets/js/contao-leaflet.js
new file mode 100644
index 0000000..5ee9d9b
--- /dev/null
+++ b/module/assets/js/contao-leaflet.js
@@ -0,0 +1,23 @@
+L.Contao = L.Class.extend( {
+ includes: L.Mixin.Events,
+
+ maps: {},
+
+ addMap: function (id, map) {
+ this.maps[id] = map;
+
+ this.fire('mapadded', { id: id, map: map});
+
+ return this;
+ },
+
+ getMap: function (id) {
+ if (typeof (this.map[id]) === 'undefined') {
+ return null;
+ }
+
+ return this.map[id]
+ }
+});
+
+window.ContaoLeaflet = new L.Contao();
diff --git a/module/config/autoload.php b/module/config/autoload.php
new file mode 100644
index 0000000..3cb9e96
--- /dev/null
+++ b/module/config/autoload.php
@@ -0,0 +1,8 @@
+ 'system/modules/leaflet/templates',
+ 'be_leaflet_geocode' => 'system/modules/leaflet/templates',
+ )
+);
diff --git a/module/config/config.php b/module/config/config.php
index fb0e613..5c25662 100644
--- a/module/config/config.php
+++ b/module/config/config.php
@@ -1,5 +1,76 @@
array('tl_leaflet_map')
+ 'tables' => array('tl_leaflet_map'),
+ 'icon' => 'system/modules/leaflet/assets/img/leaflet.png',
+);
+
+/*
+ * Content elements.
+ */
+$GLOBALS['TL_CTE']['includes']['leaflet'] = 'Netzmacht\Contao\Leaflet\LeafletMapElement';
+
+
+/*
+ * Models.
+ */
+$GLOBALS['TL_MODELS']['tl_leaflet_map'] = 'Netzmacht\Contao\Leaflet\Model\MapModel';
+
+
+/*
+ * Leaflet mappers.
+ *
+ * Mappers do the translations between the database models and the leaflet definition.
+ */
+$GLOBALS['LEAFLET_MAPPERS'] = array();
+$GLOBALS['LEAFLET_MAPPERS'][] = 'Netzmacht\Contao\Leaflet\Mapper\MapMapper';
+
+
+/*
+ * Leaflet encoders.
+ *
+ * The encoders transforms the definitions into javascript. The encoders has to be an implementation of the
+ * EventDispatcherInterface of the event dispatcher.
+ *
+ * You can define the encoders using the syntax of the cca event dispatcher implementation.
+ *
+ * @see https://github.com/contao-community-alliance/event-dispatcher#event-subscriber-per-configuration
+ */
+$GLOBALS['LEAFLET_ENCODERS'] = array();
+$GLOBALS['LEAFLET_ENCODERS'][] = 'Netzmacht\Javascript\Subscriber\EncoderSubscriber';
+$GLOBALS['LEAFLET_ENCODERS'][] = 'Netzmacht\LeafletPHP\Encoder\MapEncoder';
+$GLOBALS['LEAFLET_ENCODERS'][] = 'Netzmacht\LeafletPHP\Encoder\ControlEncoder';
+$GLOBALS['LEAFLET_ENCODERS'][] = 'Netzmacht\LeafletPHP\Encoder\GroupEncoder';
+$GLOBALS['LEAFLET_ENCODERS'][] = 'Netzmacht\LeafletPHP\Encoder\RasterEncoder';
+$GLOBALS['LEAFLET_ENCODERS'][] = 'Netzmacht\LeafletPHP\Encoder\VectorEncoder';
+$GLOBALS['LEAFLET_ENCODERS'][] = 'Netzmacht\Contao\Leaflet\Subscriber\EncoderSubscriber';
+
+
+/*
+ * Leaflet assets.
+ *
+ * The leaflet definition are aware of the required javascript libraries. Register the assets so that they are
+ * loaded automatically.
+ *
+ * Each entry is an array of 2 values. The first is the resource. The second is a type. Supported types are:
+ * - url: An valid url.
+ * - file: An file path relative to the Contao Root.
+ * - source: Inline css/javascript.
+ */
+$GLOBALS['LEAFLET_ASSETS']['contao'] = array(
+ 'javascript' => array(
+ array()
+ )
+);
+
+$GLOBALS['LEAFLET_ASSETS']['leaflet'] = array(
+ 'css' => array(
+ array('http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css', 'url')
+ ),
+ 'javascript' => array(
+ array('http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js?3', 'url')
+ )
);
diff --git a/module/config/event_subscribers.php b/module/config/event_subscribers.php
new file mode 100644
index 0000000..89e77f4
--- /dev/null
+++ b/module/config/event_subscribers.php
@@ -0,0 +1,5 @@
+share(function ($container) {
+ return new MapService(
+ $container['leaflet.definition.mapper'],
+ $container['leaflet.definition.builder'],
+ $container['event-dispatcher']
+ );
+});
+
+
+/*
+ * The leaflet boot.
+ */
+$container['leaflet.boot'] = $container->share(function ($container) {
+ return new Boot($container['event-dispatcher']);
+});
+
+
+/*
+ * The definition mapper.
+ */
+$container['leaflet.definition.mapper'] = $container->share(function ($container) {
+ /** @var Boot $boot */
+ $boot = $container['leaflet.boot'];
+ $mapper = new DefinitionMapper($container['event-dispatcher']);
+
+ return $boot->initializeDefinitionMapper($mapper);
+});
+
+
+/*
+ * The local event dispatcher is used for the leaflet javascript encoding system.
+ */
+$container['leaflet.definition.builder.event-dispatcher'] = $container->share(function ($container) {
+ /** @var Boot $boot */
+ $boot = $container['leaflet.boot'];
+ $dispatcher = new EventDispatcher();
+
+ return $boot->initializeEventDispatcher($dispatcher);
+});
+
+
+/*
+ * The leaflet builder transforms the definition to javascript.
+ */
+$container['leaflet.definition.builder'] = $container->share(function($container) {
+ /** @var Boot $boot */
+ $boot = $container['leaflet.boot'];
+ $dispatcher = $container['leaflet.definition.builder.event-dispatcher'];
+
+ $encoder = new Encoder($dispatcher);
+ $builder = new Builder($encoder, $dispatcher);
+ $leaflet = new Leaflet($builder);
+
+ return $boot->initializeLeafletBuilder($leaflet);
+});
diff --git a/module/dca/tl_content.php b/module/dca/tl_content.php
new file mode 100644
index 0000000..f790cb6
--- /dev/null
+++ b/module/dca/tl_content.php
@@ -0,0 +1,22 @@
+ array('type', 'headline'),
+ 'leaflet' => array('leaflet_map'),
+ 'templates' => array(':hide', 'customTpl'),
+ 'protected' => array(':hide', 'protected'),
+ 'expert' => array(':hide', 'guests', 'cssID', 'space'),
+ 'invisible' => array(':hide', 'invisible', 'start', 'start')
+);
+
+$GLOBALS['TL_DCA']['tl_content']['fields']['leaflet_map'] = array(
+ 'label' => &$GLOBALS['TL_LANG']['tl_content']['leaflet_map'],
+ 'inputType' => 'select',
+ 'exclude' => true,
+ 'options_callback' => array('Netzmacht\Contao\Leaflet\Dca\Content', 'getMaps'),
+ 'eval' => array(
+ 'tl_class' => 'w50',
+ 'chosen' => true,
+ ),
+ 'sql' => "int(10) unsigned NOT NULL default '0'"
+);
diff --git a/module/dca/tl_leaflet_map.php b/module/dca/tl_leaflet_map.php
index 20a4100..7c8525f 100644
--- a/module/dca/tl_leaflet_map.php
+++ b/module/dca/tl_leaflet_map.php
@@ -5,7 +5,7 @@ $GLOBALS['TL_DCA']['tl_leaflet_map'] = array
'config' => array(
'dataContainer' => 'Table',
'enableVersioning' => true,
- 'ctable' => array('tl_leaflet'),
+// 'ctable' => array('tl_leaflet'),
'sql' => array
(
'keys' => array
@@ -70,33 +70,34 @@ $GLOBALS['TL_DCA']['tl_leaflet_map'] = array
'metapalettes' => array(
'default' => array(
- 'name' => array('title', 'alias'),
- 'zoom' => array('center', 'zoom', 'adjustExtraZoom'),
- 'controls' => array('zoomControl', 'attributionControl', 'controls'),
- 'operation' => array(
+ 'title' => array('title', 'alias'),
+ 'zoom' => array('center', 'zoom', 'adjustZoomExtra'),
+ 'controls' => array('zoomControl', 'controls'),
+ 'interaction' => array(
'dragging',
'touchZoom',
'scrollWheelZoom',
'doubleClickZoom',
'boxZoom',
'tap',
- 'adjustKeyboard'
+ 'keyboard'
),
- 'behaviour' => array(
+ 'behaviour' => array(
'trackResize',
- 'popupOnClick',
+ 'closeOnClick',
'bounceAtZoomLimits'
),
- 'experts' => array(
- 'cache',
- 'options'
+ 'experts' => array(
+ 'options',
+ 'detachLibraries',
+ 'cache'
)
),
),
'metasubpalettes' => array(
- 'adjustKeyboard' => array('keyboard', 'keyboardPanOffset', 'keyboardZoomOffset'),
- 'adjustExtraZoom' => array('minZoom', 'maxZoom'),
+ 'keyboard' => array('keyboardPanOffset', 'keyboardZoomOffset'),
+ 'adjustZoomExtra' => array('minZoom', 'maxZoom'),
),
'fields' => array
@@ -114,7 +115,7 @@ $GLOBALS['TL_DCA']['tl_leaflet_map'] = array
'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['title'],
'exclude' => true,
'inputType' => 'text',
- 'eval' => array('mandatory' => true, 'maxlength' => 255),
+ 'eval' => array('mandatory' => true, 'maxlength' => 255, 'tl_class' => 'w50'),
'sql' => "varchar(255) NOT NULL default ''"
),
'alias' => array
@@ -122,9 +123,82 @@ $GLOBALS['TL_DCA']['tl_leaflet_map'] = array
'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['alias'],
'exclude' => true,
'inputType' => 'text',
- 'eval' => array('mandatory' => true, 'maxlength' => 255),
+ 'eval' => array('mandatory' => true, 'maxlength' => 255, 'tl_class' => 'w50'),
'sql' => "varchar(255) NOT NULL default ''"
),
+ 'center' => array
+ (
+ 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['center'],
+ 'exclude' => true,
+ 'inputType' => 'text',
+ 'save_callback' => array(
+ array('Netzmacht\Contao\Leaflet\Dca\Leaflet', 'validateCoordinate')
+ ),
+ 'wizard' => array(
+ array('Netzmacht\Contao\Leaflet\Dca\Leaflet', 'getGeocoder')
+ ),
+ 'eval' => array(
+ 'maxlength' => 255,
+ 'tl_class' => 'long clr',
+ 'nullIfEmpty' => true,
+ ),
+ 'sql' => "varchar(255) NULL"
+ ),
+ 'zoom' => array
+ (
+ 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['zoom'],
+ 'exclude' => true,
+ 'inputType' => 'select',
+ 'options_callback' => array('Netzmacht\Contao\Leaflet\Dca\Leaflet', 'getZoomLevels'),
+ 'default' => '',
+ 'eval' => array(
+ 'maxlength' => 4,
+ 'rgxp' => 'digit',
+ 'tl_class' => 'w50',
+ 'includeBlankOption' => true,
+ 'nullIfEmpty' => true
+ ),
+ 'sql' => "int(4) NULL"
+ ),
+ 'adjustZoomExtra' => array
+ (
+ 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['adjustZoomExtra'],
+ 'exclude' => true,
+ 'inputType' => 'checkbox',
+ 'default' => true,
+ 'eval' => array('tl_class' => 'w50 m12', 'submitOnChange' => true),
+ 'sql' => "char(1) NOT NULL default ''"
+ ),
+ 'minZoom' => array
+ (
+ 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['minZoom'],
+ 'exclude' => true,
+ 'inputType' => 'select',
+ 'options_callback' => array('Netzmacht\Contao\Leaflet\Dca\Leaflet', 'getZoomLevels'),
+ 'eval' => array(
+ 'maxlength' => 4,
+ 'rgxp' => 'digit',
+ 'tl_class' => 'w50',
+ 'includeBlankOption' => true,
+ 'nullIfEmpty' => true
+ ),
+ 'sql' => "int(4) NULL"
+ ),
+ 'maxZoom' => array
+ (
+ 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['maxZoom'],
+ 'exclude' => true,
+ 'inputType' => 'select',
+ 'options_callback' => array('Netzmacht\Contao\Leaflet\Dca\Leaflet', 'getZoomLevels'),
+ 'eval' => array(
+ 'maxlength' => 4,
+ 'rgxp' => 'digit',
+ 'tl_class' => 'w50',
+ 'includeBlankOption' => true,
+ 'nullIfEmpty' => true
+ ),
+ 'sql' => "int(4) NULL"
+ ),
'dragging' => array
(
'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['dragging'],
@@ -147,18 +221,22 @@ $GLOBALS['TL_DCA']['tl_leaflet_map'] = array
(
'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['scrollWheelZoom'],
'exclude' => true,
- 'inputType' => 'checkbox',
+ 'inputType' => 'select',
+ 'options' => array('1', '', 'center'),
+ 'reference' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['zoomValues'],
'default' => true,
- 'eval' => array('tl_class' => 'w50'),
+ 'eval' => array('tl_class' => 'w50', 'helpwizard' => true,),
'sql' => "char(1) NOT NULL default ''"
),
'doubleClickZoom' => array
(
'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['doubleClickZoom'],
'exclude' => true,
- 'inputType' => 'checkbox',
+ 'inputType' => 'select',
+ 'options' => array('1', '', 'center'),
+ 'reference' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['zoomValues'],
'default' => true,
- 'eval' => array('tl_class' => 'w50'),
+ 'eval' => array('tl_class' => 'w50', 'helpwizard' => true,),
'sql' => "char(1) NOT NULL default ''"
),
'boxZoom' => array
@@ -179,14 +257,95 @@ $GLOBALS['TL_DCA']['tl_leaflet_map'] = array
'eval' => array('tl_class' => 'w50'),
'sql' => "char(1) NOT NULL default ''"
),
- 'adjustKeyboard' => array
+ 'trackResize' => array
(
- 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['adjustKeyboard'],
+ 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['trackResize'],
'exclude' => true,
'inputType' => 'checkbox',
'default' => true,
'eval' => array('tl_class' => 'w50'),
+ 'sql' => "char(1) NOT NULL default '1'"
+ ),
+ 'bounceAtZoomLimits' => array
+ (
+ 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['bounceAtZoomLimits'],
+ 'exclude' => true,
+ 'inputType' => 'checkbox',
+ 'default' => true,
+ 'eval' => array('tl_class' => 'w50'),
+ 'sql' => "char(1) NOT NULL default '1'"
+ ),
+ 'closeOnClick' => array
+ (
+ 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['closeOnClick'],
+ 'exclude' => true,
+ 'inputType' => 'checkbox',
+ 'default' => true,
+ 'eval' => array('tl_class' => 'w50'),
+ 'sql' => "char(1) NOT NULL default '1'"
+ ),
+ 'keyboard' => array
+ (
+ 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['keyboard'],
+ 'exclude' => true,
+ 'inputType' => 'checkbox',
+ 'default' => true,
+ 'eval' => array('tl_class' => 'w50', 'submitOnChange' => true),
'sql' => "char(1) NOT NULL default ''"
),
+ 'keyboardPanOffset' => array
+ (
+ 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['keyboardPanOffset'],
+ 'exclude' => true,
+ 'inputType' => 'text',
+ 'default' => 80,
+ 'eval' => array('mandatory' => true, 'maxlength' => 4, 'rgxp' => 'digit', 'tl_class' => 'clr w50'),
+ 'sql' => "int(4) NOT NULL default '80'"
+ ),
+ 'keyboardZoomOffset' => array
+ (
+ 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['keyboardZoomOffset'],
+ 'exclude' => true,
+ 'inputType' => 'text',
+ 'default' => 1,
+ 'eval' => array('mandatory' => true, 'maxlength' => 4, 'rgxp' => 'digit', 'tl_class' => 'w50'),
+ 'sql' => "int(4) NOT NULL default '1'"
+ ),
+ 'zoomControl' => array
+ (
+ 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['zoomControl'],
+ 'exclude' => true,
+ 'inputType' => 'checkbox',
+ 'default' => true,
+ 'eval' => array('tl_class' => 'w50'),
+ 'sql' => "char(1) NOT NULL default '1'"
+ ),
+ 'options' => array
+ (
+ 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['options'],
+ 'exclude' => true,
+ 'inputType' => 'textarea',
+ 'default' => true,
+ 'eval' => array('tl_class' => 'clr lng', 'allowHtml'=>true, 'style' => 'min-height: 40px;'),
+ 'sql' => "char(1) NOT NULL default ''"
+ ),
+ 'detachLibraries' => array
+ (
+ 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['detachLibraries'],
+ 'exclude' => true,
+ 'inputType' => 'checkbox',
+ 'default' => false,
+ 'eval' => array('tl_class' => 'w50'),
+ 'sql' => "char(1) NOT NULL default ''"
+ ),
+ 'cache' => array
+ (
+ 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_map']['cache'],
+ 'exclude' => true,
+ 'inputType' => 'checkbox',
+ 'default' => false,
+ 'eval' => array('tl_class' => 'w50', 'submitOnChange' => true),
+ 'sql' => "char(1) NOT NULL default '0'"
+ ),
),
);
diff --git a/module/languages/en/modules.php b/module/languages/en/modules.php
new file mode 100644
index 0000000..18ceeb3
--- /dev/null
+++ b/module/languages/en/modules.php
@@ -0,0 +1,4 @@
+
+
+
+
+
+
+
+
diff --git a/module/templates/ce_leaflet_map.html5 b/module/templates/ce_leaflet_map.html5
new file mode 100644
index 0000000..9088421
--- /dev/null
+++ b/module/templates/ce_leaflet_map.html5
@@ -0,0 +1,6 @@
+
+
diff --git a/src/Netzmacht/Contao/Leaflet/Boot.php b/src/Netzmacht/Contao/Leaflet/Boot.php
new file mode 100644
index 0000000..0fd4e85
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/Boot.php
@@ -0,0 +1,89 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet;
+
+use Netzmacht\Contao\Leaflet\Event\InitializeDefinitionMapperEvent;
+use Netzmacht\Contao\Leaflet\Event\InitializeEventDispatcherEvent;
+use Netzmacht\Contao\Leaflet\Event\InitializeLeafletBuilderEvent;
+use Netzmacht\Contao\Leaflet\Mapper\DefinitionMapper;
+use Netzmacht\LeafletPHP\Leaflet;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface as EventDispatcher;
+
+/**
+ * Class Boot initialize the leaflet map extension.
+ *
+ * @package Netzmacht\Contao\Leaflet
+ */
+class Boot
+{
+ /**
+ * The event dispatcher.
+ *
+ * @var EventDispatcher
+ */
+ private $eventDispatcher;
+
+ /**
+ * Construct.
+ *
+ * @param EventDispatcher $eventDispatcher The event dispatcher.
+ */
+ public function __construct(EventDispatcher $eventDispatcher)
+ {
+ $this->eventDispatcher = $eventDispatcher;
+ }
+
+ /**
+ * Initialize definition mapper.
+ *
+ * @param DefinitionMapper $definitionMapper The definition mapper.
+ *
+ * @return DefinitionMapper
+ */
+ public function initializeDefinitionMapper(DefinitionMapper $definitionMapper)
+ {
+ $event = new InitializeDefinitionMapperEvent($definitionMapper);
+ $this->eventDispatcher->dispatch($event::NAME, $event);
+
+ return $definitionMapper;
+ }
+
+ /**
+ * Initialize the internal used event dispatcher of the leaflet encoding system.
+ *
+ * @param EventDispatcher $eventDispatcher The internal event dispatcher.
+ *
+ * @return EventDispatcher
+ */
+ public function initializeEventDispatcher(EventDispatcher $eventDispatcher)
+ {
+ $event = new InitializeEventDispatcherEvent($eventDispatcher);
+ $this->eventDispatcher->dispatch($event::NAME, $event);
+
+ return $eventDispatcher;
+ }
+
+ /**
+ * Initialize the leaflet builder.
+ *
+ * @param Leaflet $leaflet The leaflet builder.
+ *
+ * @return Leaflet
+ */
+ public function initializeLeafletBuilder(Leaflet $leaflet)
+ {
+ $event = new InitializeLeafletBuilderEvent($leaflet);
+ $this->eventDispatcher->dispatch($event::NAME, $event);
+
+ return $leaflet;
+ }
+}
diff --git a/src/Netzmacht/Contao/Leaflet/ContaoAssets.php b/src/Netzmacht/Contao/Leaflet/ContaoAssets.php
new file mode 100644
index 0000000..d836f26
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/ContaoAssets.php
@@ -0,0 +1,82 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet;
+
+use Netzmacht\LeafletPHP\Assets;
+
+/**
+ * Class ContaoAssets
+ * @package Netzmacht\Contao\Leaflet
+ */
+class ContaoAssets implements Assets
+{
+ /**
+ * @var
+ */
+ private $map;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addJavascript($script, $type = self::TYPE_SOURCE)
+ {
+ switch ($type) {
+ case static::TYPE_SOURCE:
+ $GLOBALS['TL_HEAD'][] = sprintf('', $script);
+ break;
+
+ case static::TYPE_FILE:
+ $script .= '|static';
+ // no break
+
+ default:
+ $GLOBALS['TL_JAVASCRIPT'][] = $script;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addStylesheet($stylesheet, $type = self::TYPE_FILE)
+ {
+ switch ($type) {
+ case static::TYPE_SOURCE:
+ $GLOBALS['TL_HEAD'][] = sprintf('', $stylesheet);
+ break;
+
+ case static::TYPE_FILE:
+ $stylesheet .= '||static';
+ // no break
+
+ default:
+ $GLOBALS['TL_CSS'][] = $stylesheet;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMap()
+ {
+ return $this->map;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setMap($map)
+ {
+ $this->map = $map;
+
+ return $this;
+ }
+}
diff --git a/src/Netzmacht/Contao/Leaflet/Dca/Content.php b/src/Netzmacht/Contao/Leaflet/Dca/Content.php
new file mode 100644
index 0000000..3c78c4c
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/Dca/Content.php
@@ -0,0 +1,40 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet\Dca;
+
+use Netzmacht\Contao\Leaflet\Model\MapModel;
+
+/**
+ * Class Content
+ * @package Netzmacht\Contao\Leaflet\Dca
+ */
+class Content
+{
+ /**
+ * Get all leaflet maps.
+ *
+ * @return array
+ */
+ public function getMaps()
+ {
+ $options = array();
+ $collection = MapModel::findAll();
+
+ if ($collection) {
+ foreach ($collection as $map) {
+ $options[$map->id] = $map->title;
+ }
+ }
+
+ return $options;
+ }
+}
diff --git a/src/Netzmacht/Contao/Leaflet/Dca/Leaflet.php b/src/Netzmacht/Contao/Leaflet/Dca/Leaflet.php
new file mode 100644
index 0000000..e1fb284
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/Dca/Leaflet.php
@@ -0,0 +1,63 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet\Dca;
+
+
+use Netzmacht\Contao\Leaflet\Mapper\DefinitionMapper;
+use Netzmacht\Contao\Leaflet\Mapper\MapMapper;
+use Netzmacht\Contao\Leaflet\Model\MapModel;
+use Netzmacht\LeafletPHP\Definition\Type\LatLng;
+
+class Leaflet
+{
+ /**
+ * Validate a coordinate.
+ *
+ * @param $value
+ *
+ * @return mixed
+ */
+ public function validateCoordinate($value)
+ {
+ if (!empty($value)) {
+ // Validate by creating latlng object. Throws an exception.
+
+ LatLng::fromString($value);
+ }
+
+ return $value;
+ }
+
+
+ public function getZoomLevels()
+ {
+ return range(1, 20);
+ }
+
+
+ public function getGeocoder($dataContainer)
+ {
+ $template = new \BackendTemplate('be_leaflet_geocode');
+ $template->field = 'ctrl_' . $dataContainer->field;
+
+ try {
+ $latLng = LatLng::fromString($dataContainer->value);
+ $template->marker = $latLng->toJson();
+ } catch(\Exception $e) {
+
+ }
+
+
+ return $template->parse();
+ }
+
+}
diff --git a/src/Netzmacht/Contao/Leaflet/Event/BuildDefinitionEvent.php b/src/Netzmacht/Contao/Leaflet/Event/BuildDefinitionEvent.php
new file mode 100644
index 0000000..7a91d5d
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/Event/BuildDefinitionEvent.php
@@ -0,0 +1,71 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet\Event;
+
+use Netzmacht\LeafletPHP\Definition;
+use Symfony\Component\EventDispatcher\Event;
+
+/**
+ * Class BuildDefinitionEvent is emitted when the mapper maps between the model and the definition.
+ *
+ * @package Netzmacht\Contao\Leaflet\Event
+ */
+class BuildDefinitionEvent extends Event
+{
+ const NAME = 'leaflet.mapper.definition';
+
+ /**
+ * The leaflet object definition.
+ *
+ * @var Definition
+ */
+ private $definition;
+
+ /**
+ * The model.
+ *
+ * @var \Model
+ */
+ private $model;
+
+ /**
+ * Construct.
+ *
+ * @param Definition $definition The leaflet definition.
+ * @param \Model $model The definition model.
+ */
+ public function __construct(Definition $definition, \Model $model)
+ {
+ $this->definition = $definition;
+ $this->model = $model;
+ }
+
+ /**
+ * Get the definition.
+ *
+ * @return Definition
+ */
+ public function getDefinition()
+ {
+ return $this->definition;
+ }
+
+ /**
+ * Get the model.
+ *
+ * @return \Model
+ */
+ public function getModel()
+ {
+ return $this->model;
+ }
+}
diff --git a/src/Netzmacht/Contao/Leaflet/Event/GetJavascriptEvent.php b/src/Netzmacht/Contao/Leaflet/Event/GetJavascriptEvent.php
new file mode 100644
index 0000000..8c188fe
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/Event/GetJavascriptEvent.php
@@ -0,0 +1,71 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet\Event;
+
+use Netzmacht\LeafletPHP\Definition\Map;
+use Symfony\Component\EventDispatcher\Event;
+
+/**
+ * Class GetJavascriptEvent is emitted after the map javascript was created.
+ *
+ * @package Netzmacht\Contao\Leaflet\Event
+ */
+class GetJavascriptEvent extends Event
+{
+ const NAME = 'leaflet.service.get-javascript';
+
+ /**
+ * The generated javascript.
+ *
+ * @var string
+ */
+ private $javascript;
+
+ /**
+ * The map definition.
+ *
+ * @var Map
+ */
+ private $map;
+
+ /**
+ * Construct.
+ *
+ * @param Map $map The map definition.
+ * @param string $javascript The generated javascript.
+ */
+ public function __construct($map, $javascript)
+ {
+ $this->map = $map;
+ $this->javascript = $javascript;
+ }
+
+ /**
+ * Get the generated javascript.
+ *
+ * @return string
+ */
+ public function getJavascript()
+ {
+ return $this->javascript;
+ }
+
+ /**
+ * Get the map definition.
+ *
+ * @return Map
+ */
+ public function getMap()
+ {
+ return $this->map;
+ }
+}
diff --git a/src/Netzmacht/Contao/Leaflet/Event/InitializeDefinitionMapperEvent.php b/src/Netzmacht/Contao/Leaflet/Event/InitializeDefinitionMapperEvent.php
new file mode 100644
index 0000000..586df49
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/Event/InitializeDefinitionMapperEvent.php
@@ -0,0 +1,50 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet\Event;
+
+use Netzmacht\Contao\Leaflet\Mapper\DefinitionMapper;
+use Symfony\Component\EventDispatcher\Event;
+
+/**
+ * Class InitializeDefinitionMapperEvent
+ *
+ * @package Netzmacht\Contao\Leaflet\Event
+ */
+class InitializeDefinitionMapperEvent extends Event
+{
+ const NAME = 'leaflet.boot.initialize-definition-mapper';
+
+ /**
+ * @var DefinitionMapper
+ */
+ private $definitionMapper;
+
+ /**
+ * Construct.
+ *
+ * @param DefinitionMapper $definitionMapper The definition mapper.
+ */
+ public function __construct(DefinitionMapper $definitionMapper)
+ {
+ $this->definitionMapper = $definitionMapper;
+ }
+
+ /**
+ * Get the definition mapper.
+ *
+ * @return DefinitionMapper
+ */
+ public function getDefinitionMapper()
+ {
+ return $this->definitionMapper;
+ }
+}
diff --git a/src/Netzmacht/Contao/Leaflet/Event/InitializeEventDispatcherEvent.php b/src/Netzmacht/Contao/Leaflet/Event/InitializeEventDispatcherEvent.php
new file mode 100644
index 0000000..16c9f72
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/Event/InitializeEventDispatcherEvent.php
@@ -0,0 +1,52 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet\Event;
+
+use Symfony\Component\EventDispatcher\Event;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface as EventDispatcher;
+
+/**
+ * InitializeEventDispatcherEvent is emitted then the internal event dispatcher of the encoding system is initialized.
+ *
+ * @package Netzmacht\Contao\Leaflet\Event
+ */
+class InitializeEventDispatcherEvent extends Event
+{
+ const NAME = 'leaflet.boot.initialize-event-dispatcher';
+
+ /**
+ * The event dispatcher.
+ *
+ * @var EventDispatcher
+ */
+ private $eventDispatcher;
+
+ /**
+ * The event dispatcher.
+ *
+ * @param EventDispatcher $eventDispatcher The event dispatcher.
+ */
+ public function __construct(EventDispatcher $eventDispatcher)
+ {
+ $this->eventDispatcher = $eventDispatcher;
+ }
+
+ /**
+ * Get the event dispatcher.
+ *
+ * @return EventDispatcher
+ */
+ public function getEventDispatcher()
+ {
+ return $this->eventDispatcher;
+ }
+}
diff --git a/src/Netzmacht/Contao/Leaflet/Event/InitializeLeafletBuilderEvent.php b/src/Netzmacht/Contao/Leaflet/Event/InitializeLeafletBuilderEvent.php
new file mode 100644
index 0000000..0aea0dd
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/Event/InitializeLeafletBuilderEvent.php
@@ -0,0 +1,52 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet\Event;
+
+use Netzmacht\LeafletPHP\Leaflet;
+use Symfony\Component\EventDispatcher\Event;
+
+/**
+ * Class InitializeLeafletBuilderEvent is emitted when the leaflet builder is created.
+ *
+ * @package Netzmacht\Contao\Leaflet\Event
+ */
+class InitializeLeafletBuilderEvent extends Event
+{
+ const NAME = 'leaflet.boot.initialize-leaflet-builder';
+
+ /**
+ * The leaflet builder.
+ *
+ * @var Leaflet
+ */
+ private $builder;
+
+ /**
+ * Construct.
+ *
+ * @param Leaflet $builder The leaflet builder.
+ */
+ public function __construct(Leaflet $builder)
+ {
+ $this->builder = $builder;
+ }
+
+ /**
+ * Get the builder.
+ *
+ * @return Leaflet
+ */
+ public function getBuilder()
+ {
+ return $this->builder;
+ }
+}
diff --git a/src/Netzmacht/Contao/Leaflet/LeafletMapElement.php b/src/Netzmacht/Contao/Leaflet/LeafletMapElement.php
new file mode 100644
index 0000000..7968145
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/LeafletMapElement.php
@@ -0,0 +1,62 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet;
+
+/**
+ * @property int leaflet_map
+ */
+class LeafletMapElement extends \ContentElement
+{
+ /**
+ * Template name.
+ *
+ * @var string
+ */
+ protected $strTemplate = 'ce_leaflet_map';
+
+ /**
+ * @var MapService
+ */
+ private $mapService;
+
+ /**
+ * Construct.
+ *
+ * @param \ContentModel $objElement Content element model.
+ * @param string $strColumn Layout column.
+ */
+ public function __construct($objElement, $strColumn = 'main')
+ {
+ parent::__construct($objElement, $strColumn);
+
+ $this->mapService = $GLOBALS['container']['leaflet.map.service'];
+ }
+
+ /**
+ * Compile the content element.
+ *
+ * @return void
+ *
+ * @throws \Exception
+ */
+ protected function compile()
+ {
+ try {
+ $mapId = 'map_' . ($this->cssID[0] ?: $this->id);
+
+ $this->Template->mapId = $mapId;
+ $this->Template->map = $this->mapService->getJavascript($this->leaflet_map, $mapId);
+ } catch(\Exception $e) {
+ throw $e;
+ }
+ }
+}
diff --git a/src/Netzmacht/Contao/Leaflet/MapService.php b/src/Netzmacht/Contao/Leaflet/MapService.php
new file mode 100644
index 0000000..7d6b452
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/MapService.php
@@ -0,0 +1,117 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet;
+
+use Netzmacht\Contao\Leaflet\Event\GetJavascriptEvent;
+use Netzmacht\Contao\Leaflet\Mapper\DefinitionMapper;
+use Netzmacht\Contao\Leaflet\Model\MapModel;
+use Netzmacht\LeafletPHP\Assets;
+use Netzmacht\LeafletPHP\Definition\Map;
+use Netzmacht\LeafletPHP\Leaflet;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface as EventDispatcher;
+
+/**
+ * Class MapService.
+ *
+ * @package Netzmacht\Contao\Leaflet
+ */
+class MapService
+{
+ /**
+ * The definition mapper.
+ *
+ * @var DefinitionMapper
+ */
+ private $mapper;
+
+ /**
+ * The leaflet service.
+ *
+ * @var Leaflet
+ */
+ private $leaflet;
+ /**
+ * @var EventDispatcher
+ */
+ private $eventDispatcher;
+
+ /**
+ * Construct.
+ *
+ * @param DefinitionMapper $mapper The definition mapper.
+ * @param Leaflet $leaflet The Leaflet instance.
+ * @param EventDispatcher $eventDispatcher The Contao event dispatcher.
+ */
+ public function __construct(DefinitionMapper $mapper, Leaflet $leaflet, EventDispatcher $eventDispatcher)
+ {
+ $this->mapper = $mapper;
+ $this->leaflet = $leaflet;
+ $this->eventDispatcher = $eventDispatcher;
+ }
+
+ /**
+ * Get map definition.
+ *
+ * @param int $mapId The map database id.
+ * @param string $elementId Optional element id. If none given the mapId or alias is used.
+ *
+ * @return Map
+ */
+ public function getDefinition($mapId, $elementId = null)
+ {
+ $model = $this->getModel($mapId);
+
+ return $this->mapper->handle($model, $elementId);
+ }
+
+ /**
+ * Get map model.
+ *
+ * @param int $mapId Model id.
+ *
+ * @return MapModel
+ *
+ * @throws \InvalidArgumentException If no model is found.
+ */
+ public function getModel($mapId)
+ {
+ $model = MapModel::findByPk($mapId);
+
+ if ($model === null) {
+ throw new \InvalidArgumentException(sprintf('Model "%s" not found', $mapId));
+ }
+
+ return $model;
+ }
+
+ /**
+ * Get map javascript.
+ *
+ * @param int $mapId The map id.
+ * @param string $elementId Optional element id. If none given the mapId or alias is used.
+ *
+ * @return string
+ *
+ * @throws \Exception If an error occurred in the process.
+ */
+ public function getJavascript($mapId, $elementId = null)
+ {
+ $definition = $this->getDefinition($mapId, $elementId);
+ $assets = new ContaoAssets();
+ $javascript = $this->leaflet->build($definition, $assets);
+
+ $event = new GetJavascriptEvent($definition, $javascript);
+ $this->eventDispatcher->dispatch($event::NAME, $event);
+
+ return $event->getJavascript();
+ }
+}
diff --git a/src/Netzmacht/Contao/Leaflet/Mapper/AbstractMapper.php b/src/Netzmacht/Contao/Leaflet/Mapper/AbstractMapper.php
new file mode 100644
index 0000000..04f9da8
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/Mapper/AbstractMapper.php
@@ -0,0 +1,308 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet\Mapper;
+
+use Netzmacht\LeafletPHP\Definition;
+
+/**
+ * Class AbstractBuilder.
+ *
+ * @package Netzmacht\Contao\Leaflet\Builder
+ */
+abstract class AbstractMapper implements Mapper
+{
+ /**
+ * Class of the model being build.
+ *
+ * @var string
+ */
+ protected static $modelClass = null;
+
+ /**
+ * Class of the definition being created.
+ *
+ * @var string
+ */
+ protected static $definitionClass = null;
+
+ /**
+ * Options mapping.
+ *
+ * @var array
+ */
+ private $options = array();
+
+ /**
+ * Conditional option mapping.
+ *
+ * @var array
+ */
+ private $conditional = array();
+
+ /**
+ * Construct.
+ */
+ public function __construct()
+ {
+ $this->initialize();
+ }
+
+ /**
+ * Add a option mapping.
+ *
+ * @param string $option Name of the option.
+ * @param string $mapping Mapping column name. Set if column name differs.
+ *
+ * @return $this
+ */
+ public function addOption($option, $mapping = null)
+ {
+ if (!isset($this->options[$option])) {
+ $this->options[$option] = $this->getMapping($option, $mapping);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add options mapping.
+ *
+ * @param array|mixed $options List of option names.
+ *
+ * @return $this
+ */
+ public function addOptions($options)
+ {
+ $arguments = func_get_args();
+
+ if (count($arguments) > 1) {
+ $options = $arguments;
+ }
+
+ foreach ($options as $key => $value) {
+ if (is_numeric($key)) {
+ $this->addOption($value);
+ } else {
+ $this->addOption($key, $value);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add a conditional option.
+ *
+ * @param string $column Condition column.
+ * @param string $option Option name.
+ * @param null $mapping Mapping column name.
+ * @param mixed $value Value of the conditional column.
+ *
+ * @return $this
+ */
+ public function addConditionalOption($column, $option, $mapping = null, $value = '1')
+ {
+ if (!isset($this->conditional[$column][$value][$option])) {
+ $this->conditional[$column][$value][$option] = $this->getMapping($option, $mapping);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add a conditional options.
+ *
+ * @param string $column Condition column.
+ * @param array $options Option names.
+ * @param mixed $value Value of the conditional column.
+ *
+ * @return $this
+ */
+ public function addConditionalOptions($column, array $options, $value = '1')
+ {
+ foreach ($options as $key => $option) {
+ if (is_numeric($key)) {
+ $this->addConditionalOption($column, $option, null, $value);
+ } else {
+ $this->addConditionalOption($column, $key, $option, $value);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function handle(\Model $model, DefinitionMapper $builder)
+ {
+ $definition = $this->createInstance($model, $builder);
+
+ $this->buildOptions($definition, $model);
+ $this->buildConditionals($definition, $model);
+ $this->doBuild($definition, $model, $builder);
+
+ return $definition;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function match(\Model $model)
+ {
+ $modelClass = static::$modelClass;
+
+ return ($model instanceof $modelClass);
+ }
+
+ /**
+ * Initialize the builder.
+ *
+ * @return void
+ */
+ abstract protected function initialize();
+
+ /**
+ * Use for specific build methods.
+ *
+ * @param Definition $definition The definition being built.
+ * @param \Model $model The model.
+ * @param DefinitionMapper $builder The definition builder.
+ *
+ * @return void
+ */
+ protected function doBuild(Definition $definition, \Model $model, DefinitionMapper $builder)
+ {
+ }
+
+ /**
+ * Create a new definition instance.
+ *
+ * @param \Model $model The model.
+ * @param DefinitionMapper $mapper The definition mapper.
+ *
+ * @return Definition
+ */
+ protected function createInstance(\Model $model, DefinitionMapper $mapper)
+ {
+ $reflector = new \ReflectionClass(static::$definitionClass);
+ $instance = $reflector->newInstanceArgs($this->buildConstructArguments($model, $mapper));
+
+ return $instance;
+ }
+
+ /**
+ * Get construct arguments.
+ *
+ * @param \Model $model The model.
+ * @param DefinitionMapper $mapper The definition mapper.
+ *
+ * @return array
+ */
+ protected function buildConstructArguments(\Model $model, DefinitionMapper $mapper)
+ {
+ return array(
+ $model->alias ?: $model->id
+ );
+ }
+
+ /**
+ * Build options.
+ *
+ * @param Definition $definition The definition being built.
+ * @param \Model $model The model.
+ *
+ * @return void
+ */
+ private function buildOptions($definition, $model)
+ {
+ $this->applyOptions($this->options, $definition, $model);
+ }
+
+ /**
+ * Build conditional options.
+ *
+ * @param Definition $definition The definition being built.
+ * @param \Model $model The model.
+ *
+ * @return void
+ */
+ private function buildConditionals(Definition $definition, \Model $model)
+ {
+ foreach ($this->conditional as $column => $conditions) {
+ foreach ($conditions as $value => $options) {
+ if ($model->$column == $value) {
+ $this->applyOptions($options, $definition, $model);
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the mapping column.
+ *
+ * @param string $option Option name.
+ * @param string|null $mapping Mapping column.
+ *
+ * @return string
+ */
+ private function getMapping($option, $mapping)
+ {
+ if ($mapping === null) {
+ return $option;
+ }
+
+ return $mapping;
+ }
+
+ /**
+ * Apply options from the model to the definition.
+ *
+ * @param array $options The options.
+ * @param Definition $definition The definition being built.
+ * @param \Model $model The model.
+ */
+ private function applyOptions($options, $definition, $model)
+ {
+ foreach ($options as $option => $mapping) {
+ $setter = 'set' . ucfirst($option);
+
+ if ($model->$option != $this->getDefaultOption($option, $definition)) {
+ $definition->$setter($model->$mapping);
+ }
+ }
+ }
+
+ /**
+ * Get default option value.
+ *
+ * @param string $option The option name.
+ * @param Definition $definition The definition being built.
+ *
+ * @return mixed
+ */
+ private function getDefaultOption($option, $definition)
+ {
+ $keys = array('has', 'is', 'get');
+ $suffix = ucfirst($option);
+
+ foreach ($keys as $key) {
+ $method = $key . $suffix;
+
+ if (method_exists($definition, $method)) {
+ return $definition->$method();
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/src/Netzmacht/Contao/Leaflet/Mapper/DefinitionMapper.php b/src/Netzmacht/Contao/Leaflet/Mapper/DefinitionMapper.php
new file mode 100644
index 0000000..8667e2c
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/Mapper/DefinitionMapper.php
@@ -0,0 +1,116 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet\Mapper;
+
+use Netzmacht\Contao\Leaflet\Event\BuildDefinitionEvent;
+use Netzmacht\LeafletPHP\Definition;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface as EventDispatcher;
+
+/**
+ * Class DefinitionBuilder is the main builder instance which contains all other builders as children.
+ *
+ * @package Netzmacht\Contao\Leaflet\Builder
+ */
+class DefinitionMapper
+{
+ /**
+ * Registered builders.
+ *
+ * @var AbstractMapper[][]
+ */
+ private $builders = array();
+
+ /**
+ * The event dispatcher.
+ *
+ * @var EventDispatcher
+ */
+ private $eventDispatcher;
+
+ /**
+ * Map id of the current built map.
+ *
+ * @var string
+ */
+ private $mapId;
+
+ /**
+ * Construct.
+ *
+ * @param EventDispatcher $eventDispatcher The event dispatcher.
+ */
+ public function __construct($eventDispatcher)
+ {
+ $this->eventDispatcher = $eventDispatcher;
+ }
+
+ /**
+ * Add a builder.
+ *
+ * @param Mapper $builder The builder.
+ * @param int $priority The priority. The higher priorities get called first.
+ *
+ * @return $this
+ */
+ public function register(Mapper $builder, $priority = 0)
+ {
+ $this->builders[$priority][] = $builder;
+
+ return $this;
+ }
+
+ /**
+ * Get the map id of the current built map.
+ *
+ * @return string
+ */
+ public function getMapId()
+ {
+ return $this->mapId;
+ }
+
+ /**
+ * Build a model.
+ *
+ * @param \Model $model The definition model.
+ * @param string $elementId Optional element id. If none given the mapId or alias is used.
+ *
+ * @return Definition
+ */
+ public function handle(\Model $model, $elementId = null)
+ {
+ krsort($this->builders);
+
+ $this->mapId = $elementId ?: ($model->alias ?: ('map_' . $model->id));
+
+ foreach ($this->builders as $builders) {
+ foreach($builders as $builder) {
+ if ($builder->match($model)) {
+ $definition = $builder->handle($model, $this);
+
+ $event = new BuildDefinitionEvent($definition, $model);
+ $this->eventDispatcher->dispatch($event::NAME, $event);
+
+ return $definition;
+ }
+ }
+ }
+
+ throw new \RuntimeException(
+ sprintf(
+ 'Could not build model "%s::%s". No matching builders found.',
+ $model->getTable(),
+ $model->{$model->getPk()}
+ )
+ );
+ }
+}
diff --git a/src/Netzmacht/Contao/Leaflet/Mapper/MapMapper.php b/src/Netzmacht/Contao/Leaflet/Mapper/MapMapper.php
new file mode 100644
index 0000000..a55bd3a
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/Mapper/MapMapper.php
@@ -0,0 +1,106 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet\Mapper;
+
+use Netzmacht\Contao\Leaflet\Model\MapModel;
+use Netzmacht\LeafletPHP\Definition;
+use Netzmacht\LeafletPHP\Definition\Map;
+
+class MapMapper extends AbstractMapper
+{
+ /**
+ * Class of the model being build.
+ *
+ * @var string
+ */
+ protected static $modelClass = 'Netzmacht\Contao\Leaflet\Model\MapModel';
+
+ /**
+ * Class of the definition being created.
+ *
+ * @var string
+ */
+ protected static $definitionClass = 'Netzmacht\LeafletPHP\Definition\Map';
+
+ /**
+ * @inheritdoc
+ */
+ protected function initialize()
+ {
+ $this
+ ->addOptions('center', 'zoom', 'zoomControl')
+ ->addOptions('dragging', 'touchZoom', 'scrollWheelZoom', 'doubleClickZoom', 'boxZoom', 'tap', 'keyboard')
+ ->addOptions('trackResize', 'closePopupOnClick', 'bounceAtZoomLimits')
+ ->addConditionalOptions('adjustZoomExtra', array('minZoom', 'maxZoom'))
+ ->addConditionalOptions('keyboard', array('keyboardPanOffset', 'keyboardZoomOffset'));
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function doBuild(Definition $map, \Model $model, DefinitionMapper $builder)
+ {
+ if ($map instanceof Map && $model instanceof MapModel) {
+ $this->buildCustomOptions($map, $model);
+ $this->buildControls($map, $model, $builder);
+ $this->buildLayers($map, $model, $builder);
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function buildConstructArguments(\Model $model, DefinitionMapper $mapper)
+ {
+ return array(
+ $mapper->getMapId(),
+ $mapper->getMapId()
+ );
+ }
+
+ /**
+ * Build map custom options.
+ *
+ * @param Map $map The map being built.
+ * @param MapModel $model The map model.
+ *
+ * @return void
+ */
+ protected function buildCustomOptions(Map $map, MapModel $model)
+ {
+ if ($model->options) {
+ $map->setOptions(json_decode($model->options, true));
+ }
+ }
+
+ /**
+ * Build map controls.
+ *
+ * @param Map $map The map being built.
+ * @param MapModel $model The map model.
+ * @param DefinitionMapper $mapper The definition mapper.
+ */
+ private function buildControls(Map $map, MapModel$model, DefinitionMapper $mapper)
+ {
+ }
+
+ /**
+ * Build map layers.
+ *
+ * @param Map $map The map being built.
+ * @param MapModel $model The map model.
+ * @param DefinitionMapper $mapper Definition mapper.
+ */
+ private function buildLayers(Map $map, MapModel $model, DefinitionMapper $mapper)
+ {
+ }
+}
diff --git a/src/Netzmacht/Contao/Leaflet/Mapper/Mapper.php b/src/Netzmacht/Contao/Leaflet/Mapper/Mapper.php
new file mode 100644
index 0000000..bc35548
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/Mapper/Mapper.php
@@ -0,0 +1,36 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet\Mapper;
+
+use Netzmacht\LeafletPHP\Definition;
+
+interface Mapper
+{
+ /**
+ * Map model to the definition.
+ *
+ * @param \Model $model The model being built.
+ * @param DefinitionMapper $builder The definition builder.
+ *
+ * @return Definition
+ */
+ public function handle(\Model $model, DefinitionMapper $builder);
+
+ /**
+ * Check if builder is responsible for the model.
+ *
+ * @param \Model $model The model being build.
+ *
+ * @return bool
+ */
+ public function match(\Model $model);
+}
diff --git a/src/Netzmacht/Contao/Leaflet/Model/MapModel.php b/src/Netzmacht/Contao/Leaflet/Model/MapModel.php
new file mode 100644
index 0000000..105a35d
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/Model/MapModel.php
@@ -0,0 +1,19 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet\Model;
+
+
+class MapModel extends \Model
+{
+ protected static $strTable = 'tl_leaflet_map';
+
+}
diff --git a/src/Netzmacht/Contao/Leaflet/Subscriber/BootSubscriber.php b/src/Netzmacht/Contao/Leaflet/Subscriber/BootSubscriber.php
new file mode 100644
index 0000000..44c8b7d
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/Subscriber/BootSubscriber.php
@@ -0,0 +1,117 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet\Subscriber;
+
+use ContaoCommunityAlliance\Contao\EventDispatcher\EventDispatcherInitializer;
+use Netzmacht\Contao\Leaflet\Event\GetJavascriptEvent;
+use Netzmacht\Contao\Leaflet\Event\InitializeDefinitionMapperEvent;
+use Netzmacht\Contao\Leaflet\Event\InitializeEventDispatcherEvent;
+use Netzmacht\Contao\Leaflet\Event\InitializeLeafletBuilderEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Class BootSubscriber
+ *
+ * @package Netzmacht\Contao\Leaflet\Subscriber
+ */
+class BootSubscriber implements EventSubscriberInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public static function getSubscribedEvents()
+ {
+ return array(
+ InitializeDefinitionMapperEvent::NAME => 'initializeDefinitionMapper',
+ InitializeEventDispatcherEvent::NAME => 'initializeEventDispatcher',
+ InitializeLeafletBuilderEvent::NAME => 'initializeLeafletBuilder',
+ GetJavascriptEvent::NAME => 'loadAssets'
+ );
+ }
+
+ /**
+ * Create and register all configured mappers.
+ *
+ * @param InitializeDefinitionMapperEvent $event The subscribed event.
+ *
+ * @return void
+ *
+ * @SuppressWarnings(PHPMD.Superglobals)
+ */
+ public function initializeDefinitionMapper(InitializeDefinitionMapperEvent $event)
+ {
+ $mapper = $event->getDefinitionMapper();
+
+ foreach ($GLOBALS['LEAFLET_MAPPERS'] as $className) {
+ if (is_array($className)) {
+ $mapper->register(new $className[0], $className[1]);
+ } else {
+ $mapper->register(new $className());
+ }
+ }
+ }
+
+ /**
+ * Register all leaflet encoders.
+ *
+ * @param InitializeEventDispatcherEvent $event The subscribed event.
+ *
+ * @return void
+ *
+ * @SuppressWarnings(PHPMD.Superglobals)
+ */
+ public function initializeEventDispatcher(InitializeEventDispatcherEvent $event)
+ {
+ $dispatcher = $event->getEventDispatcher();
+ $initializer = new EventDispatcherInitializer();
+
+ $initializer->addSubscribers($dispatcher, $GLOBALS['LEAFLET_ENCODERS']);
+ }
+
+ /**
+ * Register all libraries assets.
+ *
+ * @param InitializeLeafletBuilderEvent $event The subscribed event.
+ *
+ * @return void
+ *
+ * @SuppressWarnings(PHPMD.Superglobals)
+ */
+ public function initializeLeafletBuilder(InitializeLeafletBuilderEvent $event)
+ {
+ $builder = $event->getBuilder();
+
+ foreach ($GLOBALS['LEAFLET_ASSETS'] as $name => $assets) {
+ if (!empty($assets['css'])) {
+ foreach ($assets['css'] as $javascript) {
+ $builder->registerStylesheet($name, $javascript[0], $javascript[1]);
+ }
+ }
+
+ if (!empty($assets['javascript'])) {
+ foreach ($assets['javascript'] as $javascript) {
+ $builder->registerJavascript($name, $javascript[0], $javascript[1]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Load Contao leaflet assets.
+ *
+ * @return void
+ */
+ public function loadAssets()
+ {
+ $GLOBALS['TL_JAVASCRIPT'][] = 'system/modules/leaflet/assets/js/contao-leaflet.js';
+ }
+}
diff --git a/src/Netzmacht/Contao/Leaflet/Subscriber/EncoderSubscriber.php b/src/Netzmacht/Contao/Leaflet/Subscriber/EncoderSubscriber.php
new file mode 100644
index 0000000..7d6b2b3
--- /dev/null
+++ b/src/Netzmacht/Contao/Leaflet/Subscriber/EncoderSubscriber.php
@@ -0,0 +1,97 @@
+
+ * @copyright 2014 netzmacht creative David Molineus
+ * @license LGPL 3.0
+ * @filesource
+ *
+ */
+
+namespace Netzmacht\Contao\Leaflet\Subscriber;
+
+use Netzmacht\Javascript\Event\BuildEvent;
+use Netzmacht\LeafletPHP\Definition\Map;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Class EncoderSubscriber subscribes to the internal encoding event dispatcher.
+ *
+ * @package Netzmacht\Contao\Leaflet\Subscriber
+ */
+class EncoderSubscriber implements EventSubscriberInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public static function getSubscribedEvents()
+ {
+ return array(
+ BuildEvent::NAME => array(
+ array('startWrapper', 1000),
+ array('addAttribution'),
+ array('endWrapper', -1000)
+ )
+ );
+ }
+
+ /**
+ * Add contao-leaflet attribution.
+ *
+ * @param BuildEvent $event
+ */
+ public function addAttribution(BuildEvent $event)
+ {
+ $object = $event->getObject();
+
+ if ($object instanceof Map) {
+ $attribution = <<netzmacht creative'
+);
+HTML;
+ $event->getOutput()->addLine($attribution);
+
+ $event->getOutput()->addLine("var tileLayer = new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: \"test\"});
+tileLayer.addTo(map);");
+ }
+ }
+
+ /**
+ * Start the wrapper.
+ *
+ * The encoded map is wrapped so that it is added to window.ContaoLeaflet. You can subscribe the
+ * "mapadded" event on window.ContaoLeaflet if you can to do some customize stuff.
+ *
+ * @param BuildEvent $event The subscribed event.
+ *
+ * @return void
+ */
+ public function startWrapper(BuildEvent $event)
+ {
+ $object = $event->getObject();
+
+ if ($object instanceof Map) {
+ $line = sprintf('window.ContaoLeaflet.addMap(\'%s\', (function() {', $object->getId());
+ $event->getOutput()->addLine($line);
+ }
+ }
+
+ /**
+ * End the wrapper.
+ *
+ * @param BuildEvent $event The subscribed event.
+ *
+ * @return void
+ */
+ public function endWrapper(BuildEvent $event)
+ {
+ $object = $event->getObject();
+
+ if ($object instanceof Map) {
+ $line = 'return map; })());';
+ $event->getOutput()->addLine($line);
+ }
+ }
+}