diff --git a/resources/js/global.d.ts b/resources/js/global.d.ts index 69176af7da..e1807611ef 100644 --- a/resources/js/global.d.ts +++ b/resources/js/global.d.ts @@ -9,7 +9,6 @@ interface Window { zxcvbnts: any; msCrypto: any; u2f: any; - drawOpenLayers: () => any; variableNames: string[]; sprintf(format: string, ...values: (string|number)[]): string; diff --git a/resources/js/src/gis_data_editor.ts b/resources/js/src/gis_data_editor.ts index 72a2d06161..1998e66c85 100644 --- a/resources/js/src/gis_data_editor.ts +++ b/resources/js/src/gis_data_editor.ts @@ -363,10 +363,8 @@ function onCoordinateEdit (data) { $('#visualization-placeholder > .visualization-target-svg').html(data.visualization); $('#gis_data_textarea').val(data.result); - /* TODO: the gis_data_editor should rather return JSON than JS code to eval */ - // eslint-disable-next-line no-eval - eval(data.openLayers); initGISEditorVisualization(); + visualizationController.setOpenLayersData(data.openLayersData); } /** diff --git a/resources/js/src/table/gis_visualization.ts b/resources/js/src/table/gis_visualization.ts index ec5dc9e6a8..9a0b3005e1 100644 --- a/resources/js/src/table/gis_visualization.ts +++ b/resources/js/src/table/gis_visualization.ts @@ -2,6 +2,8 @@ import $ from 'jquery'; import { AJAX } from '../modules/ajax.ts'; import { escapeHtml } from '../modules/functions/escape.ts'; +let openLayersData: any[]|null = null; + /** * @fileoverview functions used for visualizing GIS data * @@ -449,6 +451,107 @@ class OlVisualization extends GisVisualization { } } +function getFeaturesFromOpenLayersData (geometries: any[]): any[] { + let features = []; + for (const geometry of geometries) { + if (geometry.isCollection) { + features = features.concat(getFeaturesFromOpenLayersData(geometry.geometries)); + + continue; + } + + let olGeometry: any = null; + const style: any = {}; + if (geometry.geometry.type === 'LineString') { + olGeometry = new window.ol.geom.LineString(geometry.geometry.coordinates); + style.stroke = new window.ol.style.Stroke(geometry.style.stroke); + } else if (geometry.geometry.type === 'MultiLineString') { + olGeometry = new window.ol.geom.MultiLineString(geometry.geometry.coordinates); + style.stroke = new window.ol.style.Stroke(geometry.style.stroke); + } else if (geometry.geometry.type === 'MultiPoint') { + olGeometry = new window.ol.geom.MultiPoint(geometry.geometry.coordinates); + style.image = new window.ol.style.Circle({ + fill: new window.ol.style.Fill(geometry.style.circle.fill), + stroke: new window.ol.style.Stroke(geometry.style.circle.stroke), + radius: geometry.style.circle.radius, + }); + } else if (geometry.geometry.type === 'MultiPolygon') { + olGeometry = new window.ol.geom.MultiPolygon(geometry.geometry.coordinates); + style.fill = new window.ol.style.Fill(geometry.style.fill); + style.stroke = new window.ol.style.Stroke(geometry.style.stroke); + } else if (geometry.geometry.type === 'Point') { + olGeometry = new window.ol.geom.Point(geometry.geometry.coordinates); + style.image = new window.ol.style.Circle({ + fill: new window.ol.style.Fill(geometry.style.circle.fill), + stroke: new window.ol.style.Stroke(geometry.style.circle.stroke), + radius: geometry.style.circle.radius, + }); + } else if (geometry.geometry.type === 'Polygon') { + olGeometry = new window.ol.geom.Polygon(geometry.geometry.coordinates); + style.fill = new window.ol.style.Fill(geometry.style.fill); + style.stroke = new window.ol.style.Stroke(geometry.style.stroke); + } else { + throw new Error(); + } + + if (geometry.geometry.srid !== 3857) { + olGeometry = olGeometry.transform( + 'EPSG:' + (geometry.geometry.srid !== 0 ? geometry.geometry.srid : 4326), + 'EPSG:3857' + ); + } + + if (geometry.style.text) { + style.text = new window.ol.style.Text(geometry.style.text); + } + + const feature = new window.ol.Feature(olGeometry); + feature.setStyle(new window.ol.style.Style(style)); + features.push(feature); + } + + return features; +} + +function drawOpenLayers (target: HTMLElement) { + if (typeof window.ol === 'undefined') { + return undefined; + } + + $('head').append(''); + + const vectorSource = new window.ol.source.Vector({}); + const map = new window.ol.Map({ + target: target, + layers: [ + new window.ol.layer.Tile({ source: new window.ol.source.OSM() }), + new window.ol.layer.Vector({ source: vectorSource }) + ], + view: new window.ol.View({ center: [0, 0], zoom: 4 }), + controls: [ + new window.ol.control.MousePosition({ + coordinateFormat: window.ol.coordinate.createStringXY(4), + projection: 'EPSG:4326' + }), + new window.ol.control.Zoom, + new window.ol.control.Attribution + ] + }); + + openLayersData = openLayersData ?? JSON.parse($('#visualization-placeholder').attr('data-ol-data')); + const features = getFeaturesFromOpenLayersData(openLayersData); + for (const feature of features) { + vectorSource.addFeature(feature); + } + + const extent = vectorSource.getExtent(); + if (! window.ol.extent.isEmpty(extent)) { + map.getView().fit(extent, { padding: [20, 20, 20, 20] }); + } + + return map; +} + class GisVisualizationController { private svgVis: SvgVisualization|undefined = undefined; @@ -488,7 +591,7 @@ class GisVisualizationController { if (!this.olVis) { this.olVis = new OlVisualization( $('#visualization-placeholder > .visualization-target-ol').get(0), - window.drawOpenLayers + drawOpenLayers ); } @@ -518,6 +621,10 @@ class GisVisualizationController { this.olVis.dispose(); } } + + public setOpenLayersData (olData: any[]): void { + openLayersData = olData; + } } declare global { diff --git a/resources/templates/gis_data_editor_form.twig b/resources/templates/gis_data_editor_form.twig index f3ed891cb1..bc689a9a2c 100644 --- a/resources/templates/gis_data_editor_form.twig +++ b/resources/templates/gis_data_editor_form.twig @@ -40,7 +40,7 @@
-
+
{{ visualization|raw }}
@@ -52,7 +52,6 @@
-
diff --git a/resources/templates/table/gis_visualization/gis_visualization.twig b/resources/templates/table/gis_visualization/gis_visualization.twig index 5372f5e10e..df8cd28ce6 100644 --- a/resources/templates/table/gis_visualization/gis_visualization.twig +++ b/resources/templates/table/gis_visualization/gis_visualization.twig @@ -51,11 +51,10 @@ -
+
{{ visualization|raw }}
-
diff --git a/src/Controllers/GisDataEditorController.php b/src/Controllers/GisDataEditorController.php index 4066137460..68e6c927cf 100644 --- a/src/Controllers/GisDataEditorController.php +++ b/src/Controllers/GisDataEditorController.php @@ -87,11 +87,15 @@ final class GisDataEditorController implements InvocableController $visualization = GisVisualization::getByData($data, $visualizationSettings); $svg = $visualization->asSVG(); - $openLayers = $visualization->asOl(); + $openLayersData = $visualization->asOl(); // If the call is to update the WKT and visualization make an AJAX response if ($request->hasBodyParam('generate')) { - $this->response->addJSON(['result' => $result, 'visualization' => $svg, 'openLayers' => $openLayers]); + $this->response->addJSON([ + 'result' => $result, + 'visualization' => $svg, + 'openLayersData' => $openLayersData, + ]); return $this->response->response(); } @@ -103,7 +107,7 @@ final class GisDataEditorController implements InvocableController 'input_name' => $inputName, 'srid' => $srid, 'visualization' => $svg, - 'open_layers' => $openLayers, + 'open_layers_data' => $openLayersData, 'column_type' => mb_strtoupper($type), 'gis_types' => self::GIS_TYPES, 'geom_type' => $geomType, diff --git a/src/Controllers/Table/GisVisualizationController.php b/src/Controllers/Table/GisVisualizationController.php index a1df1307c9..33883ba3a0 100644 --- a/src/Controllers/Table/GisVisualizationController.php +++ b/src/Controllers/Table/GisVisualizationController.php @@ -164,7 +164,7 @@ final class GisVisualizationController implements InvocableController 'start_and_number_of_rows_fieldset' => $startAndNumberOfRowsFieldset, 'useBaseLayer' => $useBaseLayer, 'visualization' => $visualization->asSVG(), - 'draw_ol' => $visualization->asOl(), + 'open_layers_data' => $visualization->asOl(), ]); $this->response->addHTML($html); diff --git a/src/Gis/GisGeometry.php b/src/Gis/GisGeometry.php index a83910936b..c39983e403 100644 --- a/src/Gis/GisGeometry.php +++ b/src/Gis/GisGeometry.php @@ -15,7 +15,6 @@ use TCPDF; use function array_map; use function defined; use function explode; -use function json_encode; use function mb_strripos; use function mb_substr; use function mt_getrandmax; @@ -81,22 +80,21 @@ abstract class GisGeometry ): void; /** - * Prepares the JavaScript related to a row in the GIS dataset - * to visualize it with OpenLayers. + * Prepares the data related to a row in the GIS dataset to visualize it with OpenLayers. * * @param string $spatial GIS data object * @param int $srid spatial reference ID * @param string $label label for the GIS data object * @param int[] $color color for the GIS data object * - * @return string the JavaScript related to a row in the GIS dataset + * @return mixed[] */ abstract public function prepareRowAsOl( string $spatial, int $srid, string $label, array $color, - ): string; + ): array; /** * Get coordinate extent for this wkt. @@ -332,27 +330,6 @@ abstract class GisGeometry return array_map(fn (string $coord): array => $this->extractPoints2d($coord, $scaleData), $parts); } - /** - * @param string $constructor OpenLayers geometry constructor string - * @param float[]|float[][]|float[][][]|float[][][][] $coordinates Array of coordinates 1-4 dimensions - */ - protected function toOpenLayersObject(string $constructor, array $coordinates, int $srid): string - { - $ol = 'new ' . $constructor . '(' . json_encode($coordinates) . ')'; - if ($srid !== 3857) { - $ol .= '.transform(\'EPSG:' . ($srid !== 0 ? $srid : 4326) . '\', \'EPSG:3857\')'; - } - - return $ol; - } - - protected function addGeometryToLayer(string $olGeometry, string $style): string - { - return 'var feature = new ol.Feature(' . $olGeometry . ');' - . 'feature.setStyle(' . $style . ');' - . 'vectorSource.addFeature(feature);'; - } - protected function getRandomId(): int { return ! defined('TESTSUITE') ? random_int(0, mt_getrandmax()) : 1234567890; diff --git a/src/Gis/GisGeometryCollection.php b/src/Gis/GisGeometryCollection.php index d04887d47e..8958acaf9e 100644 --- a/src/Gis/GisGeometryCollection.php +++ b/src/Gis/GisGeometryCollection.php @@ -166,19 +166,18 @@ class GisGeometryCollection extends GisGeometry } /** - * Prepares JavaScript related to a row in the GIS dataset - * to visualize it with OpenLayers. + * Prepares data related to a row in the GIS dataset to visualize it with OpenLayers. * * @param string $spatial GIS GEOMETRYCOLLECTION object * @param int $srid spatial reference ID * @param string $label label for the GIS GEOMETRYCOLLECTION object * @param int[] $color color for the GIS GEOMETRYCOLLECTION object * - * @return string JavaScript related to a row in the GIS dataset + * @return mixed[] */ - public function prepareRowAsOl(string $spatial, int $srid, string $label, array $color): string + public function prepareRowAsOl(string $spatial, int $srid, string $label, array $color): array { - $row = ''; + $row = ['isCollection' => true, 'geometries' => []]; // Trim to remove leading 'GEOMETRYCOLLECTION(' and trailing ')' $geomCol = mb_substr($spatial, 19, -1); @@ -191,7 +190,7 @@ class GisGeometryCollection extends GisGeometry continue; } - $row .= $gisObj->prepareRowAsOl($subPart, $srid, $label, $color); + $row['geometries'][] = $gisObj->prepareRowAsOl($subPart, $srid, $label, $color); } return $row; diff --git a/src/Gis/GisLineString.php b/src/Gis/GisLineString.php index 80e009383c..bb58d85ee4 100644 --- a/src/Gis/GisLineString.php +++ b/src/Gis/GisLineString.php @@ -14,7 +14,6 @@ use TCPDF; use function count; use function implode; -use function json_encode; use function max; use function mb_substr; use function round; @@ -196,38 +195,32 @@ class GisLineString extends GisGeometry } /** - * Prepares JavaScript related to a row in the GIS dataset - * to visualize it with OpenLayers. + * Prepares data related to a row in the GIS dataset to visualize it with OpenLayers. * * @param string $spatial GIS LINESTRING object * @param int $srid Spatial reference ID * @param string $label Label for the GIS LINESTRING object * @param int[] $color Color for the GIS LINESTRING object * - * @return string JavaScript related to a row in the GIS dataset + * @return mixed[] */ - public function prepareRowAsOl(string $spatial, int $srid, string $label, array $color): string + public function prepareRowAsOl(string $spatial, int $srid, string $label, array $color): array { $strokeStyle = ['color' => $color, 'width' => 2]; - - $style = 'new ol.style.Style({' - . 'stroke: new ol.style.Stroke(' . json_encode($strokeStyle) . ')'; + $style = ['stroke' => $strokeStyle]; if ($label !== '') { - $textStyle = ['text' => $label]; - $style .= ', text: new ol.style.Text(' . json_encode($textStyle) . ')'; + $style['text'] = ['text' => $label]; } - $style .= '})'; - // Trim to remove leading 'LINESTRING(' and trailing ')' $wktCoordinates = mb_substr($spatial, 11, -1); - $olGeometry = $this->toOpenLayersObject( - 'ol.geom.LineString', - $this->extractPoints1d($wktCoordinates, null), - $srid, - ); + $geometry = [ + 'type' => 'LineString', + 'coordinates' => $this->extractPoints1d($wktCoordinates, null), + 'srid' => $srid, + ]; - return $this->addGeometryToLayer($olGeometry, $style); + return ['geometry' => $geometry, 'style' => $style]; } /** diff --git a/src/Gis/GisMultiLineString.php b/src/Gis/GisMultiLineString.php index 3b9792e934..214215ba6f 100644 --- a/src/Gis/GisMultiLineString.php +++ b/src/Gis/GisMultiLineString.php @@ -15,7 +15,6 @@ use TCPDF; use function count; use function explode; use function implode; -use function json_encode; use function max; use function mb_substr; use function round; @@ -223,38 +222,32 @@ class GisMultiLineString extends GisGeometry } /** - * Prepares JavaScript related to a row in the GIS dataset - * to visualize it with OpenLayers. + * Prepares data related to a row in the GIS dataset to visualize it with OpenLayers. * * @param string $spatial GIS MULTILINESTRING object * @param int $srid Spatial reference ID * @param string $label Label for the GIS MULTILINESTRING object * @param int[] $color Color for the GIS MULTILINESTRING object * - * @return string JavaScript related to a row in the GIS dataset + * @return mixed[] */ - public function prepareRowAsOl(string $spatial, int $srid, string $label, array $color): string + public function prepareRowAsOl(string $spatial, int $srid, string $label, array $color): array { $strokeStyle = ['color' => $color, 'width' => 2]; - - $style = 'new ol.style.Style({' - . 'stroke: new ol.style.Stroke(' . json_encode($strokeStyle) . ')'; + $style = ['stroke' => $strokeStyle]; if ($label !== '') { - $textStyle = ['text' => $label]; - $style .= ', text: new ol.style.Text(' . json_encode($textStyle) . ')'; + $style['text'] = ['text' => $label]; } - $style .= '})'; - // Trim to remove leading 'MULTILINESTRING((' and trailing '))' $wktCoordinates = mb_substr($spatial, 17, -2); - $olGeometry = $this->toOpenLayersObject( - 'ol.geom.MultiLineString', - $this->extractPoints2d($wktCoordinates, null), - $srid, - ); + $geometry = [ + 'type' => 'MultiLineString', + 'coordinates' => $this->extractPoints2d($wktCoordinates, null), + 'srid' => $srid, + ]; - return $this->addGeometryToLayer($olGeometry, $style); + return ['geometry' => $geometry, 'style' => $style]; } /** diff --git a/src/Gis/GisMultiPoint.php b/src/Gis/GisMultiPoint.php index 0df64c371e..2aa374eff8 100644 --- a/src/Gis/GisMultiPoint.php +++ b/src/Gis/GisMultiPoint.php @@ -14,7 +14,6 @@ use TCPDF; use function count; use function implode; -use function json_encode; use function max; use function mb_substr; use function round; @@ -201,46 +200,37 @@ class GisMultiPoint extends GisGeometry } /** - * Prepares JavaScript related to a row in the GIS dataset - * to visualize it with OpenLayers. + * Prepares data related to a row in the GIS dataset to visualize it with OpenLayers. * * @param string $spatial GIS MULTIPOINT object * @param int $srid Spatial reference ID * @param string $label Label for the GIS MULTIPOINT object * @param int[] $color Color for the GIS MULTIPOINT object * - * @return string JavaScript related to a row in the GIS dataset + * @return mixed[] */ public function prepareRowAsOl( string $spatial, int $srid, string $label, array $color, - ): string { + ): array { $fillStyle = ['color' => 'white']; $strokeStyle = ['color' => $color, 'width' => 2]; - $style = 'new ol.style.Style({' - . 'image: new ol.style.Circle({' - . 'fill: new ol.style.Fill(' . json_encode($fillStyle) . '),' - . 'stroke: new ol.style.Stroke(' . json_encode($strokeStyle) . '),' - . 'radius: 3' - . '})'; + $style = ['circle' => ['fill' => $fillStyle, 'stroke' => $strokeStyle, 'radius' => 3]]; if ($label !== '') { - $textStyle = ['text' => $label, 'offsetY' => -9]; - $style .= ',text: new ol.style.Text(' . json_encode($textStyle) . ')'; + $style['text'] = ['text' => $label, 'offsetY' => -9]; } - $style .= '})'; - // Trim to remove leading 'MULTIPOINT(' and trailing ')' $wktCoordinates = mb_substr($spatial, 11, -1); - $olGeometry = $this->toOpenLayersObject( - 'ol.geom.MultiPoint', - $this->extractPoints1d($wktCoordinates, null), - $srid, - ); + $geometry = [ + 'type' => 'MultiPoint', + 'coordinates' => $this->extractPoints1d($wktCoordinates, null), + 'srid' => $srid, + ]; - return $this->addGeometryToLayer($olGeometry, $style); + return ['geometry' => $geometry, 'style' => $style]; } /** diff --git a/src/Gis/GisMultiPolygon.php b/src/Gis/GisMultiPolygon.php index ba447d7a27..25fda11fa7 100644 --- a/src/Gis/GisMultiPolygon.php +++ b/src/Gis/GisMultiPolygon.php @@ -18,7 +18,6 @@ use function array_slice; use function count; use function explode; use function implode; -use function json_encode; use function max; use function mb_substr; use function round; @@ -232,40 +231,34 @@ class GisMultiPolygon extends GisGeometry } /** - * Prepares JavaScript related to a row in the GIS dataset - * to visualize it with OpenLayers. + * Prepares data related to a row in the GIS dataset to visualize it with OpenLayers. * * @param string $spatial GIS MULTIPOLYGON object * @param int $srid Spatial reference ID * @param string $label Label for the GIS MULTIPOLYGON object * @param int[] $color Color for the GIS MULTIPOLYGON object * - * @return string JavaScript related to a row in the GIS dataset + * @return mixed[] */ - public function prepareRowAsOl(string $spatial, int $srid, string $label, array $color): string + public function prepareRowAsOl(string $spatial, int $srid, string $label, array $color): array { $color[] = 0.8; $fillStyle = ['color' => $color]; $strokeStyle = ['color' => [0, 0, 0], 'width' => 0.5]; - $style = 'new ol.style.Style({' - . 'fill: new ol.style.Fill(' . json_encode($fillStyle) . '),' - . 'stroke: new ol.style.Stroke(' . json_encode($strokeStyle) . ')'; + $style = ['fill' => $fillStyle, 'stroke' => $strokeStyle]; if ($label !== '') { - $textStyle = ['text' => $label]; - $style .= ',text: new ol.style.Text(' . json_encode($textStyle) . ')'; + $style['text'] = ['text' => $label]; } - $style .= '})'; - // Trim to remove leading 'MULTIPOLYGON(((' and trailing ')))' $wktCoordinates = mb_substr($spatial, 15, -3); - $olGeometry = $this->toOpenLayersObject( - 'ol.geom.MultiPolygon', - $this->extractPoints3d($wktCoordinates, null), - $srid, - ); + $geometry = [ + 'type' => 'MultiPolygon', + 'coordinates' => $this->extractPoints3d($wktCoordinates, null), + 'srid' => $srid, + ]; - return $this->addGeometryToLayer($olGeometry, $style); + return ['geometry' => $geometry, 'style' => $style]; } /** diff --git a/src/Gis/GisPoint.php b/src/Gis/GisPoint.php index dbc4e29510..1771dcc4ed 100644 --- a/src/Gis/GisPoint.php +++ b/src/Gis/GisPoint.php @@ -12,7 +12,6 @@ use PhpMyAdmin\Gis\Ds\ScaleData; use PhpMyAdmin\Image\ImageWrapper; use TCPDF; -use function json_encode; use function mb_substr; use function round; use function sprintf; @@ -188,46 +187,37 @@ class GisPoint extends GisGeometry } /** - * Prepares JavaScript related to a row in the GIS dataset - * to visualize it with OpenLayers. + * Prepares data related to a row in the GIS dataset to visualize it with OpenLayers. * * @param string $spatial GIS POINT object * @param int $srid Spatial reference ID * @param string $label Label for the GIS POINT object * @param int[] $color Color for the GIS POINT object * - * @return string JavaScript related to a row in the GIS dataset + * @return mixed[] */ public function prepareRowAsOl( string $spatial, int $srid, string $label, array $color, - ): string { + ): array { $fillStyle = ['color' => 'white']; $strokeStyle = ['color' => $color, 'width' => 2]; - $style = 'new ol.style.Style({' - . 'image: new ol.style.Circle({' - . 'fill: new ol.style.Fill(' . json_encode($fillStyle) . '),' - . 'stroke: new ol.style.Stroke(' . json_encode($strokeStyle) . '),' - . 'radius: 3' - . '})'; + $style = ['circle' => ['fill' => $fillStyle, 'stroke' => $strokeStyle, 'radius' => 3]]; if ($label !== '') { - $textStyle = ['text' => $label, 'offsetY' => -9]; - $style .= ',text: new ol.style.Text(' . json_encode($textStyle) . ')'; + $style['text'] = ['text' => $label, 'offsetY' => -9]; } - $style .= '})'; - // Trim to remove leading 'POINT(' and trailing ')' $point = mb_substr($spatial, 6, -1); - $olGeometry = $this->toOpenLayersObject( - 'ol.geom.Point', - $this->extractPoints1dLinear($point, null), - $srid, - ); + $geometry = [ + 'type' => 'Point', + 'coordinates' => $this->extractPoints1dLinear($point, null), + 'srid' => $srid, + ]; - return $this->addGeometryToLayer($olGeometry, $style); + return ['geometry' => $geometry, 'style' => $style]; } /** diff --git a/src/Gis/GisPolygon.php b/src/Gis/GisPolygon.php index ab103f804d..a844d1fced 100644 --- a/src/Gis/GisPolygon.php +++ b/src/Gis/GisPolygon.php @@ -17,7 +17,6 @@ use function array_slice; use function count; use function explode; use function implode; -use function json_encode; use function max; use function mb_substr; use function round; @@ -195,40 +194,34 @@ class GisPolygon extends GisGeometry } /** - * Prepares JavaScript related to a row in the GIS dataset - * to visualize it with OpenLayers. + * Prepares data related to a row in the GIS dataset to visualize it with OpenLayers. * * @param string $spatial GIS POLYGON object * @param int $srid Spatial reference ID * @param string $label Label for the GIS POLYGON object * @param int[] $color Color for the GIS POLYGON object * - * @return string JavaScript related to a row in the GIS dataset + * @return mixed[] */ - public function prepareRowAsOl(string $spatial, int $srid, string $label, array $color): string + public function prepareRowAsOl(string $spatial, int $srid, string $label, array $color): array { $color[] = 0.8; $fillStyle = ['color' => $color]; $strokeStyle = ['color' => [0, 0, 0], 'width' => 0.5]; - $style = 'new ol.style.Style({' - . 'fill: new ol.style.Fill(' . json_encode($fillStyle) . '),' - . 'stroke: new ol.style.Stroke(' . json_encode($strokeStyle) . ')'; + $style = ['fill' => $fillStyle, 'stroke' => $strokeStyle]; if ($label !== '') { - $textStyle = ['text' => $label]; - $style .= ',text: new ol.style.Text(' . json_encode($textStyle) . ')'; + $style['text'] = ['text' => $label]; } - $style .= '})'; - // Trim to remove leading 'POLYGON((' and trailing '))' $wktCoordinates = mb_substr($spatial, 9, -2); - $olGeometry = $this->toOpenLayersObject( - 'ol.geom.Polygon', - $this->extractPoints2d($wktCoordinates, null), - $srid, - ); + $geometry = [ + 'type' => 'Polygon', + 'coordinates' => $this->extractPoints2d($wktCoordinates, null), + 'srid' => $srid, + ]; - return $this->addGeometryToLayer($olGeometry, $style); + return ['geometry' => $geometry, 'style' => $style]; } /** diff --git a/src/Gis/GisVisualization.php b/src/Gis/GisVisualization.php index fe4a887a22..abd1b8530c 100644 --- a/src/Gis/GisVisualization.php +++ b/src/Gis/GisVisualization.php @@ -383,48 +383,13 @@ class GisVisualization } /** - * Get the code for visualization with OpenLayers. + * Get the data for visualization with OpenLayers. * - * @return string the code for visualization with OpenLayers - * - * @todo Should return JSON to avoid eval() in gis_data_editor.js + * @psalm-return list */ - public function asOl(): string + public function asOl(): array { - $olCode = $this->prepareDataSet($this->data, 'ol'); - - return 'window.drawOpenLayers = function drawOpenLayers(target) {' - . 'if (typeof ol === "undefined") { return undefined; }' - . 'var olCss = "js/vendor/openlayers/theme/ol.css";' - . '$(\'head\').append(\'\');' - . 'var vectorSource = new ol.source.Vector({});' - . 'var map = new ol.Map({' - . 'target: target,' - . 'layers: [' - . 'new ol.layer.Tile({' - . 'source: new ol.source.OSM()' - . '}),' - . 'new ol.layer.Vector({' - . 'source: vectorSource' - . '})' - . '],' - . 'view: new ol.View({' - . 'center: [0, 0],' - . 'zoom: 4' - . '}),' - . 'controls: [new ol.control.MousePosition({' - . 'coordinateFormat: ol.coordinate.createStringXY(4),' - . 'projection: \'EPSG:4326\'}),' - . 'new ol.control.Zoom,' - . 'new ol.control.Attribution]' - . '});' - . $olCode - . 'var extent = vectorSource.getExtent();' - . 'if (!ol.extent.isEmpty(extent)) {' - . 'map.getView().fit(extent, {padding: [20, 20, 20, 20]});' - . '}' - . 'return map;' - . '}'; + return $this->prepareDataSet($this->data, 'ol'); } /** @@ -529,11 +494,10 @@ class GisVisualization * * @param mixed[][] $data Raw data * @param string $format Format of the visualization - * @param ImageWrapper|TCPDF|null $renderer Image object in the case of png - * TCPDF object in the case of pdf + * @param ImageWrapper|TCPDF|null $renderer Image object in the case of png, TCPDF object in the case of pdf * @psalm-param T $format * - * @psalm-return (T is 'ol'|'svg' ? string : null) The exported data + * @psalm-return (T is 'svg' ? string : (T is 'ol' ? list : null)) The exported data * * @template T of 'ol'|'pdf'|'png'|'svg' */ @@ -541,8 +505,9 @@ class GisVisualization array $data, string $format, ImageWrapper|TCPDF|null $renderer = null, - ): string|null { - $results = ''; + ): array|string|null { + $svg = ''; + $olDataset = []; $scaleData = $this->scaleDataSet($this->data); if ($scaleData !== null) { $colorIndex = 0; @@ -563,7 +528,7 @@ class GisVisualization $label = trim((string) ($row[$this->labelColumn] ?? '')); if ($format === 'svg') { - $results .= $gisObj->prepareRowAsSvg($wkt, $label, $color, $scaleData); + $svg .= $gisObj->prepareRowAsSvg($wkt, $label, $color, $scaleData); } elseif ($format === 'png') { assert($renderer instanceof ImageWrapper); $gisObj->prepareRowAsPng($wkt, $label, $color, $scaleData, $renderer); @@ -571,13 +536,13 @@ class GisVisualization assert($renderer instanceof TCPDF); $gisObj->prepareRowAsPdf($wkt, $label, $color, $scaleData, $renderer); } elseif ($format === 'ol') { - $results .= $gisObj->prepareRowAsOl($wkt, (int) $row['srid'], $label, $color); + $olDataset[] = $gisObj->prepareRowAsOl($wkt, (int) $row['srid'], $label, $color); } $colorIndex = ($colorIndex + 1) % count(self::COLORS); } } - return $format === 'svg' || $format === 'ol' ? $results : null; + return $format === 'svg' ? $svg : ($format === 'ol' ? $olDataset : null); } } diff --git a/tests/unit/Controllers/Table/GisVisualizationControllerTest.php b/tests/unit/Controllers/Table/GisVisualizationControllerTest.php index 3cff300f8c..8ab7133825 100644 --- a/tests/unit/Controllers/Table/GisVisualizationControllerTest.php +++ b/tests/unit/Controllers/Table/GisVisualizationControllerTest.php @@ -94,20 +94,18 @@ class GisVisualizationControllerTest extends AbstractTestCase . '', - 'draw_ol' => 'window.drawOpenLayers = function drawOpenLayers(target) {if (typeof ol === "undefined") ' - . '{ return undefined; }' - . 'var olCss = "js/vendor/openlayers/theme/ol.css";$(\'head\').append(\'\');var vectorSource = new ol.source.Vector({});' - . 'var map = new ol.Map({target: target,layers: [new ol.layer.Tile({source: ' - . 'new ol.source.OSM()}),new ol.layer.Vector({source: vectorSource})],view: new ol.View({center: ' - . '[0, 0],zoom: 4}),controls: [new ol.control.MousePosition({coordinateFormat: ol.coordinate.' - . 'createStringXY(4),projection: \'EPSG:4326\'}),new ol.control.Zoom,new ol.control.Attribution]});' - . 'var feature = new ol.Feature(new ol.geom.Point([100,250]).transform(\'EPSG:4326\', ' - . '\'EPSG:3857\'));feature.setStyle(new ol.style.Style({image: new ol.style.Circle({fill: ' - . 'new ol.style.Fill({"color":"white"}),stroke: new ol.style.Stroke({"color":[176,46,224],' - . '"width":2}),radius: 3})}));vectorSource.addFeature(feature);var extent = vectorSource.getExtent();' - . 'if (!ol.extent.isEmpty(extent)) {map.getView().fit(extent, {padding: [20, 20, 20, 20]});}' - . 'return map;}', + 'open_layers_data' => [ + [ + 'geometry' => ['type' => 'Point', 'coordinates' => [100.0, 250.0], 'srid' => 0], + 'style' => [ + 'circle' => [ + 'fill' => ['color' => 'white'], + 'stroke' => ['color' => [176, 46, 224], 'width' => 2], + 'radius' => 3, + ], + ], + ], + ], ]); $request = ServerRequestFactory::create()->createServerRequest('POST', 'http://example.com/') diff --git a/tests/unit/Gis/GisGeometryCollectionTest.php b/tests/unit/Gis/GisGeometryCollectionTest.php index dff5e3c2c2..3ffd7d3d9d 100644 --- a/tests/unit/Gis/GisGeometryCollectionTest.php +++ b/tests/unit/Gis/GisGeometryCollectionTest.php @@ -390,11 +390,11 @@ class GisGeometryCollectionTest extends GisGeomTestCase /** * Test for prepareRowAsOl * - * @param string $spatial string to parse - * @param int $srid SRID - * @param string $label field label - * @param int[] $color line color - * @param string $output expected output + * @param string $spatial string to parse + * @param int $srid SRID + * @param string $label field label + * @param int[] $color line color + * @param mixed[] $expected */ #[DataProvider('providerForPrepareRowAsOl')] public function testPrepareRowAsOl( @@ -402,24 +402,16 @@ class GisGeometryCollectionTest extends GisGeomTestCase int $srid, string $label, array $color, - string $output, + array $expected, ): void { $object = GisGeometryCollection::singleton(); - self::assertSame( - $output, - $object->prepareRowAsOl( - $spatial, - $srid, - $label, - $color, - ), - ); + self::assertSame($expected, $object->prepareRowAsOl($spatial, $srid, $label, $color)); } /** * Data provider for testPrepareRowAsOl() test case * - * @return array + * @return array */ public static function providerForPrepareRowAsOl(): array { @@ -429,13 +421,26 @@ class GisGeometryCollectionTest extends GisGeomTestCase 4326, 'Ol', [176, 46, 224], - 'var feature = new ol.Feature(new ol.geom.Polygon([[[35,10],' - . '[10,20],[15,40],[45,45],[35,10]],[[20,30],[35,32],[30,20]' - . ',[20,30]]]).transform(\'EPSG:4326\', \'EPSG:3857\'));feat' - . 'ure.setStyle(new ol.style.Style({fill: new ol.style.Fill(' - . '{"color":[176,46,224,0.8]}),stroke: new ol.style.Stroke({' - . '"color":[0,0,0],"width":0.5}),text: new ol.style.Text({"t' - . 'ext":"Ol"})}));vectorSource.addFeature(feature);', + [ + 'isCollection' => true, + 'geometries' => [ + [ + 'geometry' => [ + 'type' => 'Polygon', + 'coordinates' => [ + [[35.0, 10.0], [10.0, 20.0], [15.0, 40.0], [45.0, 45.0], [35.0, 10.0]], + [[20.0, 30.0], [35.0, 32.0], [30.0, 20.0], [20.0, 30.0]], + ], + 'srid' => 4326, + ], + 'style' => [ + 'fill' => ['color' => [176, 46, 224, 0.8]], + 'stroke' => ['color' => [0, 0, 0], 'width' => 0.5], + 'text' => ['text' => 'Ol'], + ], + ], + ], + ], ], ]; } diff --git a/tests/unit/Gis/GisLineStringTest.php b/tests/unit/Gis/GisLineStringTest.php index 6303567b01..080cb42395 100644 --- a/tests/unit/Gis/GisLineStringTest.php +++ b/tests/unit/Gis/GisLineStringTest.php @@ -260,11 +260,11 @@ class GisLineStringTest extends GisGeomTestCase /** * test case for prepareRowAsOl() method * - * @param string $spatial GIS LINESTRING object - * @param int $srid spatial reference ID - * @param string $label label for the GIS LINESTRING object - * @param int[] $color color for the GIS LINESTRING object - * @param string $output expected output + * @param string $spatial GIS LINESTRING object + * @param int $srid spatial reference ID + * @param string $label label for the GIS LINESTRING object + * @param int[] $color color for the GIS LINESTRING object + * @param mixed[] $expected */ #[DataProvider('providerForPrepareRowAsOl')] public function testPrepareRowAsOl( @@ -272,17 +272,16 @@ class GisLineStringTest extends GisGeomTestCase int $srid, string $label, array $color, - string $output, + array $expected, ): void { $object = GisLineString::singleton(); - $ol = $object->prepareRowAsOl($spatial, $srid, $label, $color); - self::assertSame($output, $ol); + self::assertSame($expected, $object->prepareRowAsOl($spatial, $srid, $label, $color)); } /** * data provider for testPrepareRowAsOl() test case * - * @return array + * @return array */ public static function providerForPrepareRowAsOl(): array { @@ -292,10 +291,21 @@ class GisLineStringTest extends GisGeomTestCase 4326, 'Ol', [176, 46, 224], - 'var feature = new ol.Feature(new ol.geom.LineString([[12,35],[48,75],[69,23],[25,4' - . '5],[14,53],[35,78]]).transform(\'EPSG:4326\', \'EPSG:3857\'));feature.setStyle(n' - . 'ew ol.style.Style({stroke: new ol.style.Stroke({"color":[176,46,224],"width":2})' - . ', text: new ol.style.Text({"text":"Ol"})}));vectorSource.addFeature(feature);', + [ + 'geometry' => [ + 'type' => 'LineString', + 'coordinates' => [ + [12.0, 35.0], + [48.0, 75.0], + [69.0, 23.0], + [25.0, 45.0], + [14.0, 53.0], + [35.0, 78.0], + ], + 'srid' => 4326, + ], + 'style' => ['stroke' => ['color' => [176, 46, 224], 'width' => 2], 'text' => ['text' => 'Ol']], + ], ], ]; } diff --git a/tests/unit/Gis/GisMultiLineStringTest.php b/tests/unit/Gis/GisMultiLineStringTest.php index f10056eeb8..7bbfeed640 100644 --- a/tests/unit/Gis/GisMultiLineStringTest.php +++ b/tests/unit/Gis/GisMultiLineStringTest.php @@ -270,11 +270,11 @@ class GisMultiLineStringTest extends GisGeomTestCase /** * test case for prepareRowAsOl() method * - * @param string $spatial GIS MULTILINESTRING object - * @param int $srid spatial reference ID - * @param string $label label for the GIS MULTILINESTRING object - * @param int[] $color color for the GIS MULTILINESTRING object - * @param string $output expected output + * @param string $spatial GIS MULTILINESTRING object + * @param int $srid spatial reference ID + * @param string $label label for the GIS MULTILINESTRING object + * @param int[] $color color for the GIS MULTILINESTRING object + * @param mixed[] $expected */ #[DataProvider('providerForPrepareRowAsOl')] public function testPrepareRowAsOl( @@ -282,17 +282,16 @@ class GisMultiLineStringTest extends GisGeomTestCase int $srid, string $label, array $color, - string $output, + array $expected, ): void { $object = GisMultiLineString::singleton(); - $ol = $object->prepareRowAsOl($spatial, $srid, $label, $color); - self::assertSame($output, $ol); + self::assertSame($expected, $object->prepareRowAsOl($spatial, $srid, $label, $color)); } /** * data provider for testPrepareRowAsOl() test case * - * @return array + * @return array */ public static function providerForPrepareRowAsOl(): array { @@ -302,11 +301,17 @@ class GisMultiLineStringTest extends GisGeomTestCase 4326, 'Ol', [176, 46, 224], - 'var feature = new ol.Feature(new ol.geom.MultiLineString([[[36,14],[47,23],[62,75]' - . '],[[36,10],[17,23],[178,53]]]).transform(\'EPSG:4326\', \'EPSG:3857\'));feature.' - . 'setStyle(new ol.style.Style({stroke: new ol.style.Stroke({"color":[176,46,224],"' - . 'width":2}), text: new ol.style.Text({"text":"Ol"})}));vectorSource.addFeature(fea' - . 'ture);', + [ + 'geometry' => [ + 'type' => 'MultiLineString', + 'coordinates' => [ + [[36.0, 14.0], [47.0, 23.0], [62.0, 75.0]], + [[36.0, 10.0], [17.0, 23.0], [178.0, 53.0]], + ], + 'srid' => 4326, + ], + 'style' => ['stroke' => ['color' => [176, 46, 224], 'width' => 2], 'text' => ['text' => 'Ol']], + ], ], ]; } diff --git a/tests/unit/Gis/GisMultiPointTest.php b/tests/unit/Gis/GisMultiPointTest.php index 2f6e1b15af..5cf2ce6804 100644 --- a/tests/unit/Gis/GisMultiPointTest.php +++ b/tests/unit/Gis/GisMultiPointTest.php @@ -255,11 +255,11 @@ class GisMultiPointTest extends GisGeomTestCase /** * test case for prepareRowAsOl() method * - * @param string $spatial GIS MULTIPOINT object - * @param int $srid spatial reference ID - * @param string $label label for the GIS MULTIPOINT object - * @param int[] $color color for the GIS MULTIPOINT object - * @param string $output expected output + * @param string $spatial GIS MULTIPOINT object + * @param int $srid spatial reference ID + * @param string $label label for the GIS MULTIPOINT object + * @param int[] $color color for the GIS MULTIPOINT object + * @param mixed[] $expected */ #[DataProvider('providerForPrepareRowAsOl')] public function testPrepareRowAsOl( @@ -267,17 +267,16 @@ class GisMultiPointTest extends GisGeomTestCase int $srid, string $label, array $color, - string $output, + array $expected, ): void { $object = GisMultiPoint::singleton(); - $ol = $object->prepareRowAsOl($spatial, $srid, $label, $color); - self::assertSame($output, $ol); + self::assertSame($expected, $object->prepareRowAsOl($spatial, $srid, $label, $color)); } /** * data provider for testPrepareRowAsOl() test case * - * @return array + * @return array */ public static function providerForPrepareRowAsOl(): array { @@ -287,12 +286,28 @@ class GisMultiPointTest extends GisGeomTestCase 4326, 'Ol', [176, 46, 224], - 'var feature = new ol.Feature(new ol.geom.MultiPoint([[12,35],[48,75],[69,23],[25,4' - . '5],[14,53],[35,78]]).transform(\'EPSG:4326\', \'EPSG:3857\'));feature.setStyle(n' - . 'ew ol.style.Style({image: new ol.style.Circle({fill: new ol.style.Fill({"color":' - . '"white"}),stroke: new ol.style.Stroke({"color":[176,46,224],"width":2}),radius: ' - . '3}),text: new ol.style.Text({"text":"Ol","offsetY":-9})}));vectorSource.addFeatur' - . 'e(feature);', + [ + 'geometry' => [ + 'type' => 'MultiPoint', + 'coordinates' => [ + [12.0, 35.0], + [48.0, 75.0], + [69.0, 23.0], + [25.0, 45.0], + [14.0, 53.0], + [35.0, 78.0], + ], + 'srid' => 4326, + ], + 'style' => [ + 'circle' => [ + 'fill' => ['color' => 'white'], + 'stroke' => ['color' => [176, 46, 224], 'width' => 2], + 'radius' => 3, + ], + 'text' => ['text' => 'Ol', 'offsetY' => -9], + ], + ], ], ]; } diff --git a/tests/unit/Gis/GisMultiPolygonTest.php b/tests/unit/Gis/GisMultiPolygonTest.php index b597f49262..d1cf239a40 100644 --- a/tests/unit/Gis/GisMultiPolygonTest.php +++ b/tests/unit/Gis/GisMultiPolygonTest.php @@ -361,11 +361,11 @@ class GisMultiPolygonTest extends GisGeomTestCase /** * test case for prepareRowAsOl() method * - * @param string $spatial GIS MULTIPOLYGON object - * @param int $srid spatial reference ID - * @param string $label label for the GIS MULTIPOLYGON object - * @param int[] $color color for the GIS MULTIPOLYGON object - * @param string $output expected output + * @param string $spatial GIS MULTIPOLYGON object + * @param int $srid spatial reference ID + * @param string $label label for the GIS MULTIPOLYGON object + * @param int[] $color color for the GIS MULTIPOLYGON object + * @param mixed[] $expected */ #[DataProvider('providerForPrepareRowAsOl')] public function testPrepareRowAsOl( @@ -373,17 +373,16 @@ class GisMultiPolygonTest extends GisGeomTestCase int $srid, string $label, array $color, - string $output, + array $expected, ): void { $object = GisMultiPolygon::singleton(); - $ol = $object->prepareRowAsOl($spatial, $srid, $label, $color); - self::assertSame($output, $ol); + self::assertSame($expected, $object->prepareRowAsOl($spatial, $srid, $label, $color)); } /** * data provider for testPrepareRowAsOl() test case * - * @return array + * @return array */ public static function providerForPrepareRowAsOl(): array { @@ -393,11 +392,21 @@ class GisMultiPolygonTest extends GisGeomTestCase 4326, 'Ol', [176, 46, 224], - 'var feature = new ol.Feature(new ol.geom.MultiPolygon([[[[136,40],[147,83],[16,75]' - . ',[136,40]]],[[[105,0],[56,20],[78,73],[105,0]]]]).transform(\'EPSG:4326\', \'EPS' - . 'G:3857\'));feature.setStyle(new ol.style.Style({fill: new ol.style.Fill({"color"' - . ':[176,46,224,0.8]}),stroke: new ol.style.Stroke({"color":[0,0,0],"width":0.5}),t' - . 'ext: new ol.style.Text({"text":"Ol"})}));vectorSource.addFeature(feature);', + [ + 'geometry' => [ + 'type' => 'MultiPolygon', + 'coordinates' => [ + [[[136.0, 40.0], [147.0, 83.0], [16.0, 75.0], [136.0, 40.0]]], + [[[105.0, 0.0], [56.0, 20.0], [78.0, 73.0], [105.0, 0.0]]], + ], + 'srid' => 4326, + ], + 'style' => [ + 'fill' => ['color' => [176, 46, 224, 0.8]], + 'stroke' => ['color' => [0, 0, 0], 'width' => 0.5], + 'text' => ['text' => 'Ol'], + ], + ], ], ]; } diff --git a/tests/unit/Gis/GisPointTest.php b/tests/unit/Gis/GisPointTest.php index 16222b5b6c..63cf1e3de4 100644 --- a/tests/unit/Gis/GisPointTest.php +++ b/tests/unit/Gis/GisPointTest.php @@ -256,11 +256,11 @@ class GisPointTest extends GisGeomTestCase /** * test case for prepareRowAsOl() method * - * @param string $spatial GIS POINT object - * @param int $srid spatial reference ID - * @param string $label label for the GIS POINT object - * @param int[] $color color for the GIS POINT object - * @param string $output expected output + * @param string $spatial GIS POINT object + * @param int $srid spatial reference ID + * @param string $label label for the GIS POINT object + * @param int[] $color color for the GIS POINT object + * @param mixed[] $expected */ #[DataProvider('providerForPrepareRowAsOl')] public function testPrepareRowAsOl( @@ -268,17 +268,16 @@ class GisPointTest extends GisGeomTestCase int $srid, string $label, array $color, - string $output, + array $expected, ): void { $object = GisPoint::singleton(); - $ol = $object->prepareRowAsOl($spatial, $srid, $label, $color); - self::assertSame($output, $ol); + self::assertSame($expected, $object->prepareRowAsOl($spatial, $srid, $label, $color)); } /** * data provider for testPrepareRowAsOl() test case * - * @return array + * @return array */ public static function providerForPrepareRowAsOl(): array { @@ -288,13 +287,17 @@ class GisPointTest extends GisGeomTestCase 4326, 'Ol', [176, 46, 224], - 'var feature = new ol.Feature(new ol.geom.Point([12,35]' - . ').transform(\'EPSG:4326\', \'EPSG:3857\'));feature.s' - . 'etStyle(new ol.style.Style({image: new ol.style.Circ' - . 'le({fill: new ol.style.Fill({"color":"white"}),strok' - . 'e: new ol.style.Stroke({"color":[176,46,224],"width"' - . ':2}),radius: 3}),text: new ol.style.Text({"text":"Ol' - . '","offsetY":-9})}));vectorSource.addFeature(feature);', + [ + 'geometry' => ['type' => 'Point', 'coordinates' => [12.0, 35.0], 'srid' => 4326], + 'style' => [ + 'circle' => [ + 'fill' => ['color' => 'white'], + 'stroke' => ['color' => [176, 46, 224], 'width' => 2], + 'radius' => 3, + ], + 'text' => ['text' => 'Ol', 'offsetY' => -9], + ], + ], ], ]; } diff --git a/tests/unit/Gis/GisPolygonTest.php b/tests/unit/Gis/GisPolygonTest.php index 1b07ca4ac1..d3bcd8fe80 100644 --- a/tests/unit/Gis/GisPolygonTest.php +++ b/tests/unit/Gis/GisPolygonTest.php @@ -264,11 +264,11 @@ class GisPolygonTest extends GisGeomTestCase /** * test case for prepareRowAsOl() method * - * @param string $spatial GIS POLYGON object - * @param int $srid spatial reference ID - * @param string $label label for the GIS POLYGON object - * @param int[] $color color for the GIS POLYGON object - * @param string $output expected output + * @param string $spatial GIS POLYGON object + * @param int $srid spatial reference ID + * @param string $label label for the GIS POLYGON object + * @param int[] $color color for the GIS POLYGON object + * @param mixed[] $expected */ #[DataProvider('providerForPrepareRowAsOl')] public function testPrepareRowAsOl( @@ -276,17 +276,16 @@ class GisPolygonTest extends GisGeomTestCase int $srid, string $label, array $color, - string $output, + array $expected, ): void { $object = GisPolygon::singleton(); - $ol = $object->prepareRowAsOl($spatial, $srid, $label, $color); - self::assertSame($output, $ol); + self::assertSame($expected, $object->prepareRowAsOl($spatial, $srid, $label, $color)); } /** * data provider for testPrepareRowAsOl() test case * - * @return array + * @return array */ public static function providerForPrepareRowAsOl(): array { @@ -296,11 +295,18 @@ class GisPolygonTest extends GisGeomTestCase 4326, 'Ol', [176, 46, 224], - 'var feature = new ol.Feature(new ol.geom.Polygon([[[123,0],[23,30],[17,63],[123,0' - . ']]]).transform(\'EPSG:4326\', \'EPSG:3857\'));feature.setStyle(new ol.style.Sty' - . 'le({fill: new ol.style.Fill({"color":[176,46,224,0.8]}),stroke: new ol.style.St' - . 'roke({"color":[0,0,0],"width":0.5}),text: new ol.style.Text({"text":"Ol"})}));v' - . 'ectorSource.addFeature(feature);', + [ + 'geometry' => [ + 'type' => 'Polygon', + 'coordinates' => [[[123.0, 0.0], [23.0, 30.0], [17.0, 63.0], [123.0, 0.0]]], + 'srid' => 4326, + ], + 'style' => [ + 'fill' => ['color' => [176, 46, 224, 0.8]], + 'stroke' => ['color' => [0, 0, 0], 'width' => 0.5], + 'text' => ['text' => 'Ol'], + ], + ], ], ]; }