1<?php
2/**
3 * Editor for Geometry data types.
4 */
5
6declare(strict_types=1);
7
8namespace PhpMyAdmin\Controllers;
9
10use PhpMyAdmin\Core;
11use PhpMyAdmin\Gis\GisFactory;
12use PhpMyAdmin\Gis\GisVisualization;
13use function array_merge;
14use function in_array;
15use function intval;
16use function mb_strpos;
17use function mb_strtoupper;
18use function mb_substr;
19use function substr;
20use function trim;
21
22/**
23 * Editor for Geometry data types.
24 */
25class GisDataEditorController extends AbstractController
26{
27    public function index(): void
28    {
29        global $gis_data, $gis_types, $start, $geom_type, $gis_obj, $srid, $wkt, $wkt_with_zero, $PMA_Theme;
30        global $result, $visualizationSettings, $data, $visualization, $open_layers, $geom_count, $dbi;
31
32        if (! isset($_POST['field'])) {
33            return;
34        }
35
36        // Get data if any posted
37        $gis_data = [];
38        if (Core::isValid($_POST['gis_data'], 'array')) {
39            $gis_data = $_POST['gis_data'];
40        }
41
42        $gis_types = [
43            'POINT',
44            'MULTIPOINT',
45            'LINESTRING',
46            'MULTILINESTRING',
47            'POLYGON',
48            'MULTIPOLYGON',
49            'GEOMETRYCOLLECTION',
50        ];
51
52        // Extract type from the initial call and make sure that it's a valid one.
53        // Extract from field's values if available, if not use the column type passed.
54        if (! isset($gis_data['gis_type'])) {
55            if (isset($_POST['type']) && $_POST['type'] != '') {
56                $gis_data['gis_type'] = mb_strtoupper($_POST['type']);
57            }
58            if (isset($_POST['value']) && trim($_POST['value']) != '') {
59                $start = substr($_POST['value'], 0, 1) == "'" ? 1 : 0;
60                $gis_data['gis_type'] = mb_substr(
61                    $_POST['value'],
62                    $start,
63                    mb_strpos($_POST['value'], '(') - $start
64                );
65            }
66            if (! isset($gis_data['gis_type'])
67                || (! in_array($gis_data['gis_type'], $gis_types))
68            ) {
69                $gis_data['gis_type'] = $gis_types[0];
70            }
71        }
72        $geom_type = $gis_data['gis_type'];
73
74        // Generate parameters from value passed.
75        $gis_obj = GisFactory::factory($geom_type);
76        if ($gis_obj === false) {
77            return;
78        }
79
80        if (isset($_POST['value'])) {
81            $gis_data = array_merge(
82                $gis_data,
83                $gis_obj->generateParams($_POST['value'])
84            );
85        }
86
87        // Generate Well Known Text
88        $srid = isset($gis_data['srid']) && $gis_data['srid'] != '' ? $gis_data['srid'] : 0;
89        $wkt = $gis_obj->generateWkt($gis_data, 0);
90        $wkt_with_zero = $gis_obj->generateWkt($gis_data, 0, '0');
91        $result = "'" . $wkt . "'," . $srid;
92
93        // Generate SVG based visualization
94        $visualizationSettings = [
95            'width' => 450,
96            'height' => 300,
97            'spatialColumn' => 'wkt',
98            'mysqlVersion' => $dbi->getVersion(),
99            'isMariaDB' => $dbi->isMariaDB(),
100        ];
101        $data = [
102            [
103                'wkt' => $wkt_with_zero,
104                'srid' => $srid,
105            ],
106        ];
107        $visualization = GisVisualization::getByData($data, $visualizationSettings)
108            ->toImage('svg');
109
110        $open_layers = GisVisualization::getByData($data, $visualizationSettings)
111            ->asOl();
112
113        // If the call is to update the WKT and visualization make an AJAX response
114        if (isset($_POST['generate']) && $_POST['generate'] == true) {
115            $this->response->addJSON([
116                'result' => $result,
117                'visualization' => $visualization,
118                'openLayers' => $open_layers,
119            ]);
120
121            return;
122        }
123
124        $geom_count = 1;
125        if ($geom_type === 'GEOMETRYCOLLECTION') {
126            $geom_count = isset($gis_data[$geom_type]['geom_count'])
127                ? intval($gis_data[$geom_type]['geom_count']) : 1;
128            if (isset($gis_data[$geom_type]['add_geom'])) {
129                $geom_count++;
130            }
131        }
132
133        $templateOutput = $this->template->render('gis_data_editor_form', [
134            'width' => $visualizationSettings['width'],
135            'height' => $visualizationSettings['height'],
136            'theme_image_path' => $PMA_Theme->getImgPath(),
137            'field' => $_POST['field'],
138            'input_name' => $_POST['input_name'],
139            'srid' => $srid,
140            'visualization' => $visualization,
141            'open_layers' => $open_layers,
142            'gis_types' => $gis_types,
143            'geom_type' => $geom_type,
144            'geom_count' => $geom_count,
145            'gis_data' => $gis_data,
146            'result' => $result,
147        ]);
148
149        $this->response->addJSON(['gis_editor' => $templateOutput]);
150    }
151}
152