Extracts OpenLayers JS from the GIS PHP classes

Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
This commit is contained in:
Maurício Meneghini Fauth 2024-05-28 16:11:48 -03:00
parent 1f3d644ada
commit bd4bcc92d6
No known key found for this signature in database
GPG Key ID: 6A16FD38AFC89CC8
24 changed files with 379 additions and 329 deletions

View File

@ -9,7 +9,6 @@ interface Window {
zxcvbnts: any;
msCrypto: any;
u2f: any;
drawOpenLayers: () => any;
variableNames: string[];
sprintf(format: string, ...values: (string|number)[]): string;

View File

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

View File

@ -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('<link rel="stylesheet" type="text/css" href="js/vendor/openlayers/theme/ol.css">');
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 {

View File

@ -40,7 +40,7 @@
<div class="col-auto">
<div class="card">
<div class="card-body">
<div id="visualization-placeholder" style="width: {{ width }}px; height: {{ height }}px;">
<div id="visualization-placeholder" style="width: {{ width }}px; height: {{ height }}px;" data-ol-data="{{ open_layers_data|json_encode|e('html_attr') }}">
<div class="visualization-target visualization-target-svg hide">{{ visualization|raw }}</div>
<div class="visualization-target visualization-target-ol hide"></div>
</div>
@ -52,7 +52,6 @@
<label for="useOsmAsBaseLayerSwitch" id="useOsmAsBaseLayerSwitchLabel">{{ t('Use OpenStreetMaps as Base Layer') }}</label>
</div>
</div>
<script>{{ open_layers|raw }}</script>
</div>
</div>
</div>

View File

@ -51,11 +51,10 @@
</div>
</form>
<div id="visualization-placeholder" class="mt-3" style="height: {{ height }}px;">
<div id="visualization-placeholder" class="mt-3" style="height: {{ height }}px;" data-ol-data="{{ open_layers_data|json_encode|e('html_attr') }}">
<div class="visualization-target visualization-target-svg hide">{{ visualization|raw }}</div>
<div class="visualization-target visualization-target-ol hide"></div>
</div>
<script>{{ draw_ol|raw }}</script>
</div>
</div>
</div>

View File

@ -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,

View File

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

View File

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

View File

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

View File

@ -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];
}
/**

View File

@ -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];
}
/**

View File

@ -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];
}
/**

View File

@ -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];
}
/**

View File

@ -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];
}
/**

View File

@ -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];
}
/**

View File

@ -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<mixed[]>
*/
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(\'<link rel="stylesheet" type="text/css" href=\'+olCss+\'>\');'
. '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<mixed[]> : 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);
}
}

View File

@ -94,20 +94,18 @@ class GisVisualizationControllerTest extends AbstractTestCase
. '<svg version="1.1" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"'
. ' width="600" height="450"><g><circle cx="300" cy="225" r="3" name=""'
. ' id="1234567890" class="point vector" fill="white" stroke="#b02ee0" stroke-width="2"/></g></svg>',
'draw_ol' => 'window.drawOpenLayers = function drawOpenLayers(target) {if (typeof ol === "undefined") '
. '{ return undefined; }'
. 'var olCss = "js/vendor/openlayers/theme/ol.css";$(\'head\').append(\'<link rel="stylesheet" '
. 'type="text/css" href=\'+olCss+\'>\');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/')

View File

@ -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<array{string, int, string, int[], string}>
* @return array<array{string, int, string, int[], mixed[]}>
*/
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'],
],
],
],
],
],
];
}

View File

@ -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<array{string, int, string, int[], string}>
* @return array<array{string, int, string, int[], mixed[]}>
*/
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']],
],
],
];
}

View File

@ -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<array{string, int, string, int[], string}>
* @return array<array{string, int, string, int[], mixed[]}>
*/
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']],
],
],
];
}

View File

@ -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<array{string, int, string, int[], string}>
* @return array<array{string, int, string, int[], mixed[]}>
*/
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],
],
],
],
];
}

View File

@ -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<array{string, int, string, int[], string}>
* @return array<array{string, int, string, int[], mixed[]}>
*/
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'],
],
],
],
];
}

View File

@ -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<array{string, int, string, int[], string}>
* @return array<array{string, int, string, int[], mixed[]}>
*/
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],
],
],
],
];
}

View File

@ -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<array{string, int, string, int[], string}>
* @return array<array{string, int, string, int[], mixed[]}>
*/
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'],
],
],
],
];
}