Passed
Push — 4.x ( 651f39...1d49e7 )
by Doug
02:50
created

EPSGImporter::generateConstantsCoordinateSystems()   A

Complexity

Conditions 5
Paths 16

Size

Total Lines 105
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 24
c 1
b 0
f 0
dl 0
loc 105
rs 9.2248
cc 5
nc 16
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * PHPCoord.
4
 *
5
 * @author Doug Wright
6
 */
7
declare(strict_types=1);
8
9
namespace PHPCoord\EPSG\Import;
10
11
use function dirname;
12
use function file_exists;
13
use function file_get_contents;
14
use function file_put_contents;
15
use PHPCoord\Datum\Datum;
16
use PhpCsFixer\AbstractFixer;
17
use PhpCsFixer\Config;
18
use PhpCsFixer\Console\ConfigurationResolver;
19
use PhpCsFixer\Tokenizer\Tokens;
20
use PhpCsFixer\ToolInfo;
21
use PhpParser\Lexer\Emulative;
22
use PhpParser\NodeTraverser;
23
use PhpParser\NodeVisitor\CloningVisitor;
24
use PhpParser\Parser\Php7;
25
use SplFileInfo;
26
use SQLite3;
27
use function unlink;
28
29
class EPSGImporter
30
{
31
    private string $resourceDir;
32
33
    private string $sourceDir;
34
35
    private const BOM = "\xEF\xBB\xBF";
36
37
    public function __construct()
38
    {
39
        $this->resourceDir = __DIR__ . '/../../../resources';
40
        $this->sourceDir = dirname(__DIR__, 2);
41
    }
42
43
    public function createSQLiteDB(): void
44
    {
45
        //remove old file if any
46
        if (file_exists($this->resourceDir . '/epsg/epsg.sqlite')) {
47
            unlink($this->resourceDir . '/epsg/epsg.sqlite');
48
        }
49
50
        $sqlite = new SQLite3(
51
        $this->resourceDir . '/epsg/epsg.sqlite',
52
        SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE
53
        );
54
55
        $sqlite->enableExceptions(true);
56
        $sqlite->exec('PRAGMA journal_mode=WAL'); //WAL is faster
57
58
        $tableSchema = file_get_contents($this->resourceDir . '/epsg/PostgreSQL_Table_Script.sql');
59
        if (strpos($tableSchema, self::BOM) === 0) {
60
            $tableSchema = substr($tableSchema, 3);
61
        }
62
        $sqlite->exec($tableSchema);
63
64
        $tableData = file_get_contents($this->resourceDir . '/epsg/PostgreSQL_Data_Script.sql');
65
        if (strpos($tableData, self::BOM) === 0) {
66
            $tableData = substr($tableData, 3);
67
        }
68
        $sqlite->exec($tableData);
69
70
        $sqlite->exec('VACUUM');
71
        $sqlite->exec('PRAGMA journal_mode=DELETE'); //but WAL is not openable read-only in older SQLite
72
        $sqlite->close();
73
    }
74
75
    public function doCodeGeneration(): void
76
    {
77
        $sqlite = new SQLite3(
78
        $this->resourceDir . '/epsg/epsg.sqlite',
79
        SQLITE3_OPEN_READONLY
80
        );
81
82
        $sqlite->enableExceptions(true);
83
84
        $this->generateDataUnitsOfMeasure($sqlite);
85
        $this->generateDataPrimeMeridians($sqlite);
86
        $this->generateDataEllipsoids($sqlite);
87
        $this->generateDataDatums($sqlite);
88
        $this->generateDataCoordinateSystems($sqlite);
89
        $this->generateDataCoordinateReferenceSystems($sqlite);
90
        $this->generateDataCoordinateOperations($sqlite);
91
92
        $this->generateConstantsUnitsOfMeasure($sqlite);
93
        $this->generateConstantsPrimeMeridians($sqlite);
94
        $this->generateConstantsEllipsoids($sqlite);
95
        $this->generateConstantsDatums($sqlite);
96
        $this->generateConstantsCoordinateSystems($sqlite);
97
        $this->generateConstantsCoordinateReferenceSystems($sqlite);
98
        $this->generateConstantsCoordinateOperationMethods($sqlite);
99
100
        $sqlite->close();
101
    }
102
103
    public function generateConstantsUnitsOfMeasure(SQLite3 $sqlite): void
104
    {
105
        $sql = "
106
            SELECT
107
                'urn:ogc:def:uom:EPSG::' || m.uom_code AS constant_value,
108
                m.unit_of_meas_name AS constant_name,
109
                m.unit_of_meas_name || '\n' || m.remarks AS constant_help,
110
                m.deprecated
111
            FROM epsg_unitofmeasure m
112
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_unitofmeasure' AND dep.object_code = m.uom_code AND dep.deprecation_date <= '2020-12-14'
113
            WHERE m.unit_of_meas_type = 'angle' AND m.unit_of_meas_name NOT LIKE '%per second%' AND m.unit_of_meas_name NOT LIKE '%per year%'
114
            ORDER BY constant_name
115
            ";
116
117
        $result = $sqlite->query($sql);
118
        $constants = [];
119
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
120
            $constants[] = $row;
121
        }
122
123
        $this->updateFileConstants($this->sourceDir . '/UnitOfMeasure/Angle/Angle.php', $constants, 'public');
124
125
        $sql = "
126
            SELECT
127
                'urn:ogc:def:uom:EPSG::' || m.uom_code AS constant_value,
128
                m.unit_of_meas_name AS constant_name,
129
                m.unit_of_meas_name || '\n' || m.remarks AS constant_help,
130
                m.deprecated
131
            FROM epsg_unitofmeasure m
132
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_unitofmeasure' AND dep.object_code = m.uom_code AND dep.deprecation_date <= '2020-12-14'
133
            WHERE m.unit_of_meas_type = 'length' AND m.unit_of_meas_name NOT LIKE '%per second%' AND m.unit_of_meas_name NOT LIKE '%per year%'
134
            AND m.unit_of_meas_name NOT LIKE '%bin%'
135
            ORDER BY constant_name
136
            ";
137
138
        $result = $sqlite->query($sql);
139
        $constants = [];
140
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
141
            $constants[] = $row;
142
        }
143
144
        $this->updateFileConstants($this->sourceDir . '/UnitOfMeasure/Length/Length.php', $constants, 'public');
145
146
        $sql = "
147
            SELECT
148
                'urn:ogc:def:uom:EPSG::' || m.uom_code AS constant_value,
149
                m.unit_of_meas_name AS constant_name,
150
                m.unit_of_meas_name || '\n' || m.remarks AS constant_help,
151
                m.deprecated
152
            FROM epsg_unitofmeasure m
153
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_unitofmeasure' AND dep.object_code = m.uom_code AND dep.deprecation_date <= '2020-12-14'
154
            WHERE m.unit_of_meas_type = 'scale' AND m.unit_of_meas_name NOT LIKE '%per second%' AND m.unit_of_meas_name NOT LIKE '%per year%'
155
            AND m.unit_of_meas_name NOT LIKE '%bin%'
156
            ORDER BY constant_name
157
            ";
158
159
        $result = $sqlite->query($sql);
160
        $constants = [];
161
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
162
            $constants[] = $row;
163
        }
164
165
        $this->updateFileConstants($this->sourceDir . '/UnitOfMeasure/Scale/Scale.php', $constants, 'public');
166
167
        $sql = "
168
            SELECT
169
                'urn:ogc:def:uom:EPSG::' || m.uom_code AS constant_value,
170
                m.unit_of_meas_name AS constant_name,
171
                m.unit_of_meas_name || '\n' || m.remarks AS constant_help,
172
                m.deprecated
173
            FROM epsg_unitofmeasure m
174
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_unitofmeasure' AND dep.object_code = m.uom_code AND dep.deprecation_date <= '2020-12-14'
175
            WHERE m.unit_of_meas_type = 'time' AND m.unit_of_meas_name NOT LIKE '%per second%' AND m.unit_of_meas_name NOT LIKE '%per year%'
176
            ORDER BY constant_name
177
            ";
178
179
        $result = $sqlite->query($sql);
180
        $constants = [];
181
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
182
            $constants[] = $row;
183
        }
184
185
        $this->updateFileConstants($this->sourceDir . '/UnitOfMeasure/Time/Time.php', $constants, 'public');
186
187
        $sql = "
188
            SELECT
189
                'urn:ogc:def:uom:EPSG::' || m.uom_code AS constant_value,
190
                m.unit_of_meas_name AS constant_name,
191
                m.unit_of_meas_name || '\n' || m.remarks AS constant_help,
192
                m.deprecated
193
            FROM epsg_unitofmeasure m
194
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_unitofmeasure' AND dep.object_code = m.uom_code AND dep.deprecation_date <= '2020-12-14'
195
            WHERE (m.unit_of_meas_name LIKE '%per second%' OR m.unit_of_meas_name LIKE '%per year%')
196
            ORDER BY constant_name
197
            ";
198
199
        $result = $sqlite->query($sql);
200
        $constants = [];
201
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
202
            $constants[] = $row;
203
        }
204
205
        $this->updateFileConstants($this->sourceDir . '/UnitOfMeasure/Rate.php', $constants, 'public');
206
207
        $sql = "
208
            SELECT
209
                'urn:ogc:def:uom:EPSG::' || m.uom_code AS constant_value,
210
                m.unit_of_meas_type || '_' || m.unit_of_meas_name AS constant_name,
211
                m.unit_of_meas_name || '\n' || m.remarks AS constant_help,
212
                m.deprecated
213
            FROM epsg_unitofmeasure m
214
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_unitofmeasure' AND dep.object_code = m.uom_code AND dep.deprecation_date <= '2020-12-14'
215
            WHERE m.unit_of_meas_type NOT IN ('angle', 'length', 'scale', 'time') AND m.unit_of_meas_name NOT LIKE '%per second%' AND m.unit_of_meas_name NOT LIKE '%per year%'
216
            ORDER BY constant_name
217
            ";
218
219
        $result = $sqlite->query($sql);
220
        $constants = [];
221
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
222
            $constants[] = $row;
223
        }
224
225
        $this->updateFileConstants($this->sourceDir . '/UnitOfMeasure/UnitOfMeasure.php', $constants, 'public');
226
    }
227
228
    public function generateDataUnitsOfMeasure(SQLite3 $sqlite): void
229
    {
230
        $sql = "
231
            SELECT
232
               'urn:ogc:def:uom:EPSG::' || m.uom_code AS urn,
233
                m.unit_of_meas_name AS name
234
            FROM epsg_unitofmeasure m
235
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_unitofmeasure' AND dep.object_code = m.uom_code AND dep.deprecation_date <= '2020-12-14'
236
            WHERE m.unit_of_meas_type = 'angle' AND m.unit_of_meas_name NOT LIKE '%per second%' AND m.unit_of_meas_name NOT LIKE '%per year%'
237
            AND dep.deprecation_id IS NULL
238
            ORDER BY urn
239
            ";
240
241
        $result = $sqlite->query($sql);
242
        $data = [];
243
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
244
            $data[$row['urn']] = $row;
245
            unset($data[$row['urn']]['urn']);
246
        }
247
248
        $this->updateFileData($this->sourceDir . '/UnitOfMeasure/Angle/Angle.php', $data);
249
250
        $sql = "
251
            SELECT
252
               'urn:ogc:def:uom:EPSG::' || m.uom_code AS urn,
253
                m.unit_of_meas_name AS name
254
            FROM epsg_unitofmeasure m
255
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_unitofmeasure' AND dep.object_code = m.uom_code AND dep.deprecation_date <= '2020-12-14'
256
            WHERE m.unit_of_meas_type = 'length' AND m.unit_of_meas_name NOT LIKE '%per second%' AND m.unit_of_meas_name NOT LIKE '%per year%'
257
            AND m.unit_of_meas_name NOT LIKE '%bin%'
258
            AND dep.deprecation_id IS NULL
259
            ORDER BY urn
260
            ";
261
262
        $result = $sqlite->query($sql);
263
        $data = [];
264
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
265
            $data[$row['urn']] = $row;
266
            unset($data[$row['urn']]['urn']);
267
        }
268
269
        $this->updateFileData($this->sourceDir . '/UnitOfMeasure/Length/Length.php', $data);
270
271
        $sql = "
272
            SELECT
273
               'urn:ogc:def:uom:EPSG::' || m.uom_code AS urn,
274
                m.unit_of_meas_name AS name
275
            FROM epsg_unitofmeasure m
276
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_unitofmeasure' AND dep.object_code = m.uom_code AND dep.deprecation_date <= '2020-12-14'
277
            WHERE m.unit_of_meas_type = 'scale' AND m.unit_of_meas_name NOT LIKE '%per second%' AND m.unit_of_meas_name NOT LIKE '%per year%'
278
            AND m.unit_of_meas_name NOT LIKE '%bin%'
279
            AND dep.deprecation_id IS NULL
280
            ORDER BY urn
281
            ";
282
283
        $result = $sqlite->query($sql);
284
        $data = [];
285
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
286
            $data[$row['urn']] = $row;
287
            unset($data[$row['urn']]['urn']);
288
        }
289
290
        $this->updateFileData($this->sourceDir . '/UnitOfMeasure/Scale/Scale.php', $data);
291
292
        $sql = "
293
            SELECT
294
               'urn:ogc:def:uom:EPSG::' || m.uom_code AS urn,
295
                m.unit_of_meas_name AS name
296
            FROM epsg_unitofmeasure m
297
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_unitofmeasure' AND dep.object_code = m.uom_code AND dep.deprecation_date <= '2020-12-14'
298
            WHERE m.unit_of_meas_type = 'time' AND m.unit_of_meas_name NOT LIKE '%per second%' AND m.unit_of_meas_name NOT LIKE '%per year%'
299
            AND dep.deprecation_id IS NULL
300
            ORDER BY urn
301
            ";
302
303
        $result = $sqlite->query($sql);
304
        $data = [];
305
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
306
            $data[$row['urn']] = $row;
307
            unset($data[$row['urn']]['urn']);
308
        }
309
310
        $this->updateFileData($this->sourceDir . '/UnitOfMeasure/Time/Time.php', $data);
311
312
        $sql = "
313
            SELECT
314
               'urn:ogc:def:uom:EPSG::' || m.uom_code AS urn,
315
                m.unit_of_meas_name AS name
316
            FROM epsg_unitofmeasure m
317
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_unitofmeasure' AND dep.object_code = m.uom_code AND dep.deprecation_date <= '2020-12-14'
318
            WHERE (m.unit_of_meas_name LIKE '%per second%' OR m.unit_of_meas_name LIKE '%per year%')
319
            AND dep.deprecation_id IS NULL
320
            ORDER BY urn
321
            ";
322
323
        $result = $sqlite->query($sql);
324
        $data = [];
325
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
326
            $data[$row['urn']] = $row;
327
            unset($data[$row['urn']]['urn']);
328
        }
329
330
        $this->updateFileData($this->sourceDir . '/UnitOfMeasure/Rate.php', $data);
331
332
        $sql = "
333
            SELECT
334
               'urn:ogc:def:uom:EPSG::' || m.uom_code AS urn,
335
                m.unit_of_meas_name AS name
336
            FROM epsg_unitofmeasure m
337
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_unitofmeasure' AND dep.object_code = m.uom_code AND dep.deprecation_date <= '2020-12-14'
338
            WHERE m.unit_of_meas_type NOT IN ('angle', 'length', 'scale', 'time') AND m.unit_of_meas_name NOT LIKE '%per second%' AND m.unit_of_meas_name NOT LIKE '%per year%'
339
            AND dep.deprecation_id IS NULL
340
            ORDER BY urn
341
            ";
342
343
        $result = $sqlite->query($sql);
344
        $data = [];
345
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
346
            $data[$row['urn']] = $row;
347
            unset($data[$row['urn']]['urn']);
348
        }
349
350
        $this->updateFileData($this->sourceDir . '/UnitOfMeasure/UnitOfMeasureFactory.php', $data);
351
    }
352
353
    public function generateConstantsPrimeMeridians(SQLite3 $sqlite): void
354
    {
355
        $sql = "
356
            SELECT
357
                'urn:ogc:def:meridian:EPSG::' || p.prime_meridian_code AS constant_value,
358
                p.prime_meridian_name AS constant_name,
359
                p.prime_meridian_name || '\n' || p.remarks AS constant_help,
360
                p.deprecated
361
            FROM epsg_primemeridian p
362
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_primemeridian' AND dep.object_code = p.prime_meridian_code AND dep.deprecation_date <= '2020-12-14'
363
            WHERE dep.deprecation_id IS NULL
364
            ORDER BY constant_name
365
            ";
366
367
        $result = $sqlite->query($sql);
368
        $constants = [];
369
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
370
            $constants[] = $row;
371
        }
372
373
        $this->updateFileConstants($this->sourceDir . '/Datum/PrimeMeridian.php', $constants, 'public');
374
    }
375
376
    public function generateDataPrimeMeridians(SQLite3 $sqlite): void
377
    {
378
        $sql = "
379
            SELECT
380
                'urn:ogc:def:meridian:EPSG::' || p.prime_meridian_code AS urn,
381
                p.prime_meridian_name AS name,
382
                p.greenwich_longitude,
383
                'urn:ogc:def:uom:EPSG::' || p.uom_code AS uom
384
            FROM epsg_primemeridian p
385
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_primemeridian' AND dep.object_code = p.prime_meridian_code AND dep.deprecation_date <= '2020-12-14'
386
            WHERE dep.deprecation_id IS NULL
387
            ORDER BY urn
388
            ";
389
390
        $result = $sqlite->query($sql);
391
        $data = [];
392
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
393
            $data[$row['urn']] = $row;
394
            unset($data[$row['urn']]['urn']);
395
        }
396
397
        $this->updateFileData($this->sourceDir . '/Datum/PrimeMeridian.php', $data);
398
    }
399
400
    public function generateConstantsEllipsoids(SQLite3 $sqlite): void
401
    {
402
        $sql = "
403
            SELECT
404
            DISTINCT
405
                'urn:ogc:def:ellipsoid:EPSG::' || e.ellipsoid_code AS constant_value,
406
                e.ellipsoid_name AS constant_name,
407
                e.ellipsoid_name || '\n' || e.remarks AS constant_help,
408
                e.deprecated
409
            FROM epsg_ellipsoid e
410
            JOIN epsg_datum d ON d.ellipsoid_code = e.ellipsoid_code -- there are some never used entries
411
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_ellipsoid' AND dep.object_code = e.ellipsoid_code AND dep.deprecation_date <= '2020-12-14'
412
            WHERE dep.deprecation_id IS NULL
413
            ORDER BY constant_name
414
            ";
415
416
        $result = $sqlite->query($sql);
417
        $constants = [];
418
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
419
            $constants[] = $row;
420
        }
421
422
        $this->updateFileConstants($this->sourceDir . '/Datum/Ellipsoid.php', $constants, 'public');
423
    }
424
425
    public function generateDataEllipsoids(SQLite3 $sqlite): void
426
    {
427
        $sql = "
428
            SELECT
429
                'urn:ogc:def:ellipsoid:EPSG::' || e.ellipsoid_code AS urn,
430
                e.ellipsoid_name AS name,
431
                e.semi_major_axis,
432
                e.semi_minor_axis,
433
                e.inv_flattening,
434
                'urn:ogc:def:uom:EPSG::' || e.uom_code AS uom
435
            FROM epsg_ellipsoid e
436
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_ellipsoid' AND dep.object_code = e.ellipsoid_code AND dep.deprecation_date <= '2020-12-14'
437
            WHERE dep.deprecation_id IS NULL
438
            ORDER BY urn
439
        ";
440
441
        $result = $sqlite->query($sql);
442
        $data = [];
443
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
444
            // some ellipsoids are defined via inverse flattening and the DB doesn't store the calculated data...
445
            if (!$row['semi_minor_axis']) {
446
                $row['semi_minor_axis'] = $row['semi_major_axis'] - ($row['semi_major_axis'] / $row['inv_flattening']);
447
            }
448
            $data[$row['urn']] = $row;
449
            unset($data[$row['urn']]['urn']);
450
            unset($data[$row['urn']]['inv_flattening']);
451
        }
452
453
        $this->updateFileData($this->sourceDir . '/Datum/Ellipsoid.php', $data);
454
    }
455
456
    public function generateConstantsDatums(SQLite3 $sqlite): void
457
    {
458
        $sql = "
459
            SELECT
460
                DISTINCT
461
                'urn:ogc:def:datum:EPSG::' || d.datum_code AS constant_value,
462
                d.datum_name AS constant_name,
463
                d.datum_name || '\n' || 'Type: ' || d.datum_type || '\n' || 'Extent: ' || e.extent_description || '\n' || d.origin_description || '\n' || d.remarks AS constant_help,
464
                d.deprecated
465
            FROM epsg_datum d
466
            LEFT JOIN epsg_usage u ON u.object_table_name = 'epsg_datum' AND u.object_code = d.datum_code
467
            LEFT JOIN epsg_extent e ON u.extent_code = e.extent_code
468
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_datum' AND dep.object_code = d.datum_code AND dep.deprecation_date <= '2020-12-14'
469
            WHERE dep.deprecation_id IS NULL AND d.datum_type != 'engineering'
470
            ORDER BY constant_name
471
        ";
472
473
        $result = $sqlite->query($sql);
474
        $constants = [];
475
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
476
            $constants[] = $row;
477
        }
478
479
        $this->updateFileConstants($this->sourceDir . '/Datum/Datum.php', $constants, 'public');
480
    }
481
482
    public function generateDataDatums(SQLite3 $sqlite): void
483
    {
484
        $sql = "
485
            SELECT
486
                'urn:ogc:def:datum:EPSG::' || d.datum_code AS urn,
487
                d.datum_name AS name,
488
                d.datum_type AS type,
489
                'urn:ogc:def:ellipsoid:EPSG::' || d.ellipsoid_code AS ellipsoid,
490
                'urn:ogc:def:meridian:EPSG::' || d.prime_meridian_code AS prime_meridian,
491
                d.conventional_rs_code AS conventional_rs,
492
                d.frame_reference_epoch
493
            FROM epsg_datum d
494
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_datum' AND dep.object_code = d.datum_code AND dep.deprecation_date <= '2020-12-14'
495
            WHERE dep.deprecation_id IS NULL AND d.datum_type != 'engineering'
496
            ORDER BY urn
497
        ";
498
499
        $result = $sqlite->query($sql);
500
        $data = [];
501
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
502
            if ($row['type'] === Datum::DATUM_TYPE_ENSEMBLE) {
503
                $row['ensemble'] = [];
504
                $ensembleSql = "
505
                    SELECT
506
                        'urn:ogc:def:datum:EPSG::' || d.datum_ensemble_code AS ensemble,
507
                        'urn:ogc:def:datum:EPSG::' || d.datum_code AS datum,
508
                        d.datum_sequence
509
                    FROM epsg_datumensemblemember d
510
                    WHERE ensemble = '{$row['urn']}'
511
                    ORDER BY d.datum_sequence
512
                    ";
513
514
                $ensembleResult = $sqlite->query($ensembleSql);
515
                while ($ensembleRow = $ensembleResult->fetchArray(SQLITE3_ASSOC)) {
516
                    $row['ensemble'][] = $ensembleRow['datum'];
517
                }
518
            }
519
            $data[$row['urn']] = $row;
520
            unset($data[$row['urn']]['urn']);
521
        }
522
523
        $this->updateFileData($this->sourceDir . '/Datum/Datum.php', $data);
524
    }
525
526
    public function generateConstantsCoordinateSystems(SQLite3 $sqlite): void
527
    {
528
        /*
529
         * cartesian
530
         */
531
        $sql = "
532
            SELECT
533
                DISTINCT
534
                'urn:ogc:def:cs:EPSG::' || cs.coord_sys_code AS constant_value,
535
                REPLACE(REPLACE(REPLACE(cs.coord_sys_name, 'Cartesian 2D CS', ''), 'Cartesian 3D CS', ''), 'for', '') || CASE cs.coord_sys_code WHEN 4531 THEN '_LOWERCASE' ELSE '' END AS constant_name,
536
                cs.coord_sys_name || '\n' || 'Type: ' || cs.coord_sys_type || '\n' || cs.remarks AS constant_help,
537
                cs.deprecated
538
            FROM epsg_coordinatesystem cs
539
            JOIN epsg_coordinatereferencesystem crs ON crs.coord_sys_code = cs.coord_sys_code AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
540
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatesystem' AND dep.object_code = cs.coord_sys_code AND dep.deprecation_date <= '2020-12-14'
541
            WHERE dep.deprecation_id IS NULL AND cs.coord_sys_type != 'ordinal'
542
            AND cs.coord_sys_type = 'Cartesian'
543
            ORDER BY constant_name
544
        ";
545
546
        $result = $sqlite->query($sql);
547
        $constants = [];
548
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
549
            $constants[] = $row;
550
        }
551
552
        $this->updateFileConstants($this->sourceDir . '/CoordinateSystem/Cartesian.php', $constants, 'public');
553
554
        /*
555
         * ellipsoidal
556
         */
557
        $sql = "
558
            SELECT
559
                DISTINCT
560
                'urn:ogc:def:cs:EPSG::' || cs.coord_sys_code AS constant_value,
561
                REPLACE(REPLACE(REPLACE(cs.coord_sys_name, 'Ellipsoidal 2D CS', ''), 'Ellipsoidal 3D CS', ''), 'for', '') AS constant_name,
562
                cs.coord_sys_name || '\n' || 'Type: ' || cs.coord_sys_type || '\n' || cs.remarks AS constant_help,
563
                cs.deprecated
564
            FROM epsg_coordinatesystem cs
565
            JOIN epsg_coordinatereferencesystem crs ON crs.coord_sys_code = cs.coord_sys_code AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
566
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatesystem' AND dep.object_code = cs.coord_sys_code AND dep.deprecation_date <= '2020-12-14'
567
            WHERE dep.deprecation_id IS NULL AND cs.coord_sys_type != 'ordinal'
568
            AND cs.coord_sys_type = 'ellipsoidal'
569
            ORDER BY constant_name
570
        ";
571
572
        $result = $sqlite->query($sql);
573
        $constants = [];
574
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
575
            $constants[] = $row;
576
        }
577
578
        $this->updateFileConstants($this->sourceDir . '/CoordinateSystem/Ellipsoidal.php', $constants, 'public');
579
580
        /*
581
         * vertical
582
         */
583
        $sql = "
584
            SELECT
585
                DISTINCT
586
                'urn:ogc:def:cs:EPSG::' || cs.coord_sys_code AS constant_value,
587
                REPLACE(REPLACE(cs.coord_sys_name, 'Vertical CS', ''), 'for', '') AS constant_name,
588
                cs.coord_sys_name || '\n' || 'Type: ' || cs.coord_sys_type || '\n' || cs.remarks AS constant_help,
589
                cs.deprecated
590
            FROM epsg_coordinatesystem cs
591
            JOIN epsg_coordinatereferencesystem crs ON crs.coord_sys_code = cs.coord_sys_code AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
592
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatesystem' AND dep.object_code = cs.coord_sys_code AND dep.deprecation_date <= '2020-12-14'
593
            WHERE dep.deprecation_id IS NULL AND cs.coord_sys_type != 'ordinal'
594
            AND cs.coord_sys_type = 'vertical'
595
            ORDER BY constant_name
596
        ";
597
598
        $result = $sqlite->query($sql);
599
        $constants = [];
600
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
601
            $constants[] = $row;
602
        }
603
604
        $this->updateFileConstants($this->sourceDir . '/CoordinateSystem/Vertical.php', $constants, 'public');
605
606
        /*
607
         * other
608
         */
609
        $sql = "
610
            SELECT
611
                DISTINCT
612
                'urn:ogc:def:cs:EPSG::' || cs.coord_sys_code AS constant_value,
613
                cs.coord_sys_name AS constant_name,
614
                cs.coord_sys_name || '\n' || 'Type: ' || cs.coord_sys_type || '\n' || cs.remarks AS constant_help,
615
                cs.deprecated
616
            FROM epsg_coordinatesystem cs
617
            JOIN epsg_coordinatereferencesystem crs ON crs.coord_sys_code = cs.coord_sys_code AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
618
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatesystem' AND dep.object_code = cs.coord_sys_code AND dep.deprecation_date <= '2020-12-14'
619
            WHERE dep.deprecation_id IS NULL AND cs.coord_sys_type != 'ordinal'
620
            AND cs.coord_sys_type NOT IN ('Cartesian', 'ellipsoidal', 'vertical')
621
            ORDER BY constant_name
622
        ";
623
624
        $result = $sqlite->query($sql);
625
        $constants = [];
626
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
627
            $constants[] = $row;
628
        }
629
630
        $this->updateFileConstants($this->sourceDir . '/CoordinateSystem/CoordinateSystem.php', $constants, 'public');
631
    }
632
633
    public function generateDataCoordinateSystems(SQLite3 $sqlite): void
634
    {
635
        /*
636
         * cartesian
637
         */
638
        $sql = "
639
            SELECT
640
                'urn:ogc:def:cs:EPSG::' || cs.coord_sys_code AS urn,
641
                cs.coord_sys_name AS name
642
            FROM epsg_coordinatesystem cs
643
            JOIN epsg_coordinatereferencesystem crs ON crs.coord_sys_code = cs.coord_sys_code AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
644
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatesystem' AND dep.object_code = cs.coord_sys_code AND dep.deprecation_date <= '2020-12-14'
645
            WHERE dep.deprecation_id IS NULL AND cs.coord_sys_type != 'ordinal'
646
            AND cs.coord_sys_type = 'Cartesian'
647
            ";
648
649
        $result = $sqlite->query($sql);
650
        $data = [];
651
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
652
            $row['axes'] = [];
653
            $axisSql = "
654
                SELECT
655
                    'urn:ogc:def:cs:EPSG::' || a.coord_sys_code AS coord_sys,
656
                    a.coord_axis_orientation AS orientation,
657
                    a.coord_axis_abbreviation AS abbreviation,
658
                    an.coord_axis_name AS name,
659
                    'urn:ogc:def:uom:EPSG::' || a.uom_code AS uom
660
                FROM epsg_coordinateaxis a
661
                JOIN epsg_coordinateaxisname an on a.coord_axis_name_code = an.coord_axis_name_code
662
                WHERE coord_sys = '{$row['urn']}'
663
                ORDER BY a.coord_axis_order
664
                ";
665
666
            $axisResult = $sqlite->query($axisSql);
667
            while ($axisRow = $axisResult->fetchArray(SQLITE3_ASSOC)) {
668
                unset($axisRow['coord_sys']);
669
                $row['axes'][] = $axisRow;
670
            }
671
            $data[$row['urn']] = $row;
672
            unset($data[$row['urn']]['urn']);
673
        }
674
675
        $this->updateFileData($this->sourceDir . '/CoordinateSystem/Cartesian.php', $data);
676
677
        /*
678
         * ellipsoidal
679
         */
680
        $sql = "
681
            SELECT
682
                'urn:ogc:def:cs:EPSG::' || cs.coord_sys_code AS urn,
683
                cs.coord_sys_name AS name
684
            FROM epsg_coordinatesystem cs
685
            JOIN epsg_coordinatereferencesystem crs ON crs.coord_sys_code = cs.coord_sys_code AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
686
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatesystem' AND dep.object_code = cs.coord_sys_code AND dep.deprecation_date <= '2020-12-14'
687
            WHERE dep.deprecation_id IS NULL AND cs.coord_sys_type != 'ordinal'
688
            AND cs.coord_sys_type = 'ellipsoidal'
689
            ";
690
691
        $result = $sqlite->query($sql);
692
        $data = [];
693
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
694
            $row['axes'] = [];
695
            $axisSql = "
696
                SELECT
697
                    'urn:ogc:def:cs:EPSG::' || a.coord_sys_code AS coord_sys,
698
                    a.coord_axis_orientation AS orientation,
699
                    a.coord_axis_abbreviation AS abbreviation,
700
                    an.coord_axis_name AS name,
701
                    'urn:ogc:def:uom:EPSG::' || a.uom_code AS uom
702
                FROM epsg_coordinateaxis a
703
                JOIN epsg_coordinateaxisname an on a.coord_axis_name_code = an.coord_axis_name_code
704
                WHERE coord_sys = '{$row['urn']}'
705
                ORDER BY a.coord_axis_order
706
                ";
707
708
            $axisResult = $sqlite->query($axisSql);
709
            while ($axisRow = $axisResult->fetchArray(SQLITE3_ASSOC)) {
710
                unset($axisRow['coord_sys']);
711
                $row['axes'][] = $axisRow;
712
            }
713
            $data[$row['urn']] = $row;
714
            unset($data[$row['urn']]['urn']);
715
        }
716
717
        $this->updateFileData($this->sourceDir . '/CoordinateSystem/Ellipsoidal.php', $data);
718
719
        /*
720
         * vertical
721
         */
722
        $sql = "
723
            SELECT
724
                'urn:ogc:def:cs:EPSG::' || cs.coord_sys_code AS urn,
725
                cs.coord_sys_name AS name
726
            FROM epsg_coordinatesystem cs
727
            JOIN epsg_coordinatereferencesystem crs ON crs.coord_sys_code = cs.coord_sys_code AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
728
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatesystem' AND dep.object_code = cs.coord_sys_code AND dep.deprecation_date <= '2020-12-14'
729
            WHERE dep.deprecation_id IS NULL AND cs.coord_sys_type != 'ordinal'
730
            AND cs.coord_sys_type = 'vertical'
731
            ";
732
733
        $result = $sqlite->query($sql);
734
        $data = [];
735
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
736
            $row['axes'] = [];
737
            $axisSql = "
738
                SELECT
739
                    'urn:ogc:def:cs:EPSG::' || a.coord_sys_code AS coord_sys,
740
                    a.coord_axis_orientation AS orientation,
741
                    a.coord_axis_abbreviation AS abbreviation,
742
                    an.coord_axis_name AS name,
743
                    'urn:ogc:def:uom:EPSG::' || a.uom_code AS uom
744
                FROM epsg_coordinateaxis a
745
                JOIN epsg_coordinateaxisname an on a.coord_axis_name_code = an.coord_axis_name_code
746
                WHERE coord_sys = '{$row['urn']}'
747
                ORDER BY a.coord_axis_order
748
                ";
749
750
            $axisResult = $sqlite->query($axisSql);
751
            while ($axisRow = $axisResult->fetchArray(SQLITE3_ASSOC)) {
752
                unset($axisRow['coord_sys']);
753
                $row['axes'][] = $axisRow;
754
            }
755
            $data[$row['urn']] = $row;
756
            unset($data[$row['urn']]['urn']);
757
        }
758
759
        $this->updateFileData($this->sourceDir . '/CoordinateSystem/Vertical.php', $data);
760
761
        /*
762
         * other
763
         */
764
        $sql = "
765
            SELECT
766
                'urn:ogc:def:cs:EPSG::' || cs.coord_sys_code AS urn,
767
                cs.coord_sys_name AS name,
768
                cs.coord_sys_type AS type
769
            FROM epsg_coordinatesystem cs
770
            JOIN epsg_coordinatereferencesystem crs ON crs.coord_sys_code = cs.coord_sys_code AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
771
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatesystem' AND dep.object_code = cs.coord_sys_code AND dep.deprecation_date <= '2020-12-14'
772
            WHERE dep.deprecation_id IS NULL AND cs.coord_sys_type != 'ordinal'
773
            AND cs.coord_sys_type NOT IN ('Cartesian', 'ellipsoidal', 'vertical')
774
            ";
775
776
        $result = $sqlite->query($sql);
777
        $data = [];
778
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
779
            $row['axes'] = [];
780
            $axisSql = "
781
                SELECT
782
                    'urn:ogc:def:cs:EPSG::' || a.coord_sys_code AS coord_sys,
783
                    a.coord_axis_orientation AS orientation,
784
                    a.coord_axis_abbreviation AS abbreviation,
785
                    an.coord_axis_name AS name,
786
                    'urn:ogc:def:uom:EPSG::' || a.uom_code AS uom
787
                FROM epsg_coordinateaxis a
788
                JOIN epsg_coordinateaxisname an on a.coord_axis_name_code = an.coord_axis_name_code
789
                WHERE coord_sys = '{$row['urn']}'
790
                ORDER BY a.coord_axis_order
791
                ";
792
793
            $axisResult = $sqlite->query($axisSql);
794
            while ($axisRow = $axisResult->fetchArray(SQLITE3_ASSOC)) {
795
                unset($axisRow['coord_sys']);
796
                $row['axes'][] = $axisRow;
797
            }
798
            $data[$row['urn']] = $row;
799
            unset($data[$row['urn']]['urn']);
800
        }
801
802
        $this->updateFileData($this->sourceDir . '/CoordinateSystem/CoordinateSystem.php', $data);
803
    }
804
805
    public function generateConstantsCoordinateReferenceSystems(SQLite3 $sqlite): void
806
    {
807
        /*
808
         * compound
809
         */
810
        $sql = "
811
            SELECT
812
                'urn:ogc:def:crs:EPSG::' || crs.coord_ref_sys_code AS constant_value,
813
                crs.coord_ref_sys_name AS constant_name,
814
                crs.coord_ref_sys_name || '\n' || 'Extent: ' || e.extent_description || '\n' || crs.remarks AS constant_help,
815
                crs.deprecated
816
            FROM epsg_coordinatereferencesystem crs
817
            LEFT JOIN epsg_usage u ON u.object_table_name = 'epsg_coordinatereferencesystem' AND u.object_code = crs.coord_ref_sys_code
818
            LEFT JOIN epsg_extent e ON u.extent_code = e.extent_code
819
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatereferencesystem' AND dep.object_code = crs.coord_ref_sys_code AND dep.deprecation_date <= '2020-12-14'
820
            WHERE dep.deprecation_id IS NULL AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
821
            AND (crs.cmpd_horizcrs_code IS NULL OR crs.cmpd_horizcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind IN ('engineering', 'derived')))
822
            AND (crs.cmpd_vertcrs_code IS NULL OR crs.cmpd_vertcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind IN ('engineering', 'derived')))
823
            AND crs.coord_ref_sys_kind = 'compound'
824
            GROUP BY crs.coord_ref_sys_code
825
            ORDER BY constant_name
826
        ";
827
828
        $result = $sqlite->query($sql);
829
        $constants = [];
830
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
831
            $constants[] = $row;
832
        }
833
834
        $this->updateFileConstants($this->sourceDir . '/CoordinateReferenceSystem/Compound.php', $constants, 'public');
835
836
        /*
837
         * geocentric
838
         */
839
        $sql = "
840
            SELECT
841
                'urn:ogc:def:crs:EPSG::' || crs.coord_ref_sys_code AS constant_value,
842
                crs.coord_ref_sys_name AS constant_name,
843
                crs.coord_ref_sys_name || '\n' || 'Extent: ' || e.extent_description || '\n' || crs.remarks AS constant_help,
844
                crs.deprecated
845
            FROM epsg_coordinatereferencesystem crs
846
            LEFT JOIN epsg_usage u ON u.object_table_name = 'epsg_coordinatereferencesystem' AND u.object_code = crs.coord_ref_sys_code
847
            LEFT JOIN epsg_extent e ON u.extent_code = e.extent_code
848
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatereferencesystem' AND dep.object_code = crs.coord_ref_sys_code AND dep.deprecation_date <= '2020-12-14'
849
            WHERE dep.deprecation_id IS NULL AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
850
            AND (crs.cmpd_horizcrs_code IS NULL OR crs.cmpd_horizcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind IN ('engineering', 'derived')))
851
            AND (crs.cmpd_vertcrs_code IS NULL OR crs.cmpd_vertcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind IN ('engineering', 'derived')))
852
            AND crs.coord_ref_sys_kind = 'geocentric'
853
            GROUP BY crs.coord_ref_sys_code
854
            ORDER BY constant_name
855
        ";
856
857
        $result = $sqlite->query($sql);
858
        $constants = [];
859
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
860
            $constants[] = $row;
861
        }
862
863
        $this->updateFileConstants($this->sourceDir . '/CoordinateReferenceSystem/Geocentric.php', $constants, 'public');
864
865
        /*
866
         * geographic 2D
867
         */
868
        $sql = "
869
            SELECT
870
                'urn:ogc:def:crs:EPSG::' || crs.coord_ref_sys_code AS constant_value,
871
                crs.coord_ref_sys_name AS constant_name,
872
                crs.coord_ref_sys_name || '\n' || 'Extent: ' || e.extent_description || '\n' || crs.remarks AS constant_help,
873
                crs.deprecated
874
            FROM epsg_coordinatereferencesystem crs
875
            LEFT JOIN epsg_usage u ON u.object_table_name = 'epsg_coordinatereferencesystem' AND u.object_code = crs.coord_ref_sys_code
876
            LEFT JOIN epsg_extent e ON u.extent_code = e.extent_code
877
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatereferencesystem' AND dep.object_code = crs.coord_ref_sys_code AND dep.deprecation_date <= '2020-12-14'
878
            WHERE dep.deprecation_id IS NULL AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
879
            AND (crs.cmpd_horizcrs_code IS NULL OR crs.cmpd_horizcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind IN ('engineering', 'derived')))
880
            AND (crs.cmpd_vertcrs_code IS NULL OR crs.cmpd_vertcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind IN ('engineering', 'derived')))
881
            AND crs.coord_ref_sys_kind = 'geographic 2D'
882
            GROUP BY crs.coord_ref_sys_code
883
            ORDER BY constant_name
884
        ";
885
886
        $result = $sqlite->query($sql);
887
        $constants = [];
888
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
889
            $constants[] = $row;
890
        }
891
892
        $this->updateFileConstants($this->sourceDir . '/CoordinateReferenceSystem/Geographic2D.php', $constants, 'public');
893
894
        /*
895
         * geographic 3D
896
         */
897
        $sql = "
898
            SELECT
899
                'urn:ogc:def:crs:EPSG::' || crs.coord_ref_sys_code AS constant_value,
900
                crs.coord_ref_sys_name AS constant_name,
901
                crs.coord_ref_sys_name || '\n' || 'Extent: ' || e.extent_description || '\n' || crs.remarks AS constant_help,
902
                crs.deprecated
903
            FROM epsg_coordinatereferencesystem crs
904
            LEFT JOIN epsg_usage u ON u.object_table_name = 'epsg_coordinatereferencesystem' AND u.object_code = crs.coord_ref_sys_code
905
            LEFT JOIN epsg_extent e ON u.extent_code = e.extent_code
906
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatereferencesystem' AND dep.object_code = crs.coord_ref_sys_code AND dep.deprecation_date <= '2020-12-14'
907
            WHERE dep.deprecation_id IS NULL AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
908
            AND (crs.cmpd_horizcrs_code IS NULL OR crs.cmpd_horizcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind IN ('engineering', 'derived')))
909
            AND (crs.cmpd_vertcrs_code IS NULL OR crs.cmpd_vertcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind IN ('engineering', 'derived')))
910
            AND crs.coord_ref_sys_kind = 'geographic 3D'
911
            GROUP BY crs.coord_ref_sys_code
912
            ORDER BY constant_name
913
        ";
914
915
        $result = $sqlite->query($sql);
916
        $constants = [];
917
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
918
            $constants[] = $row;
919
        }
920
921
        $this->updateFileConstants($this->sourceDir . '/CoordinateReferenceSystem/Geographic3D.php', $constants, 'public');
922
923
        /*
924
         * projected
925
         */
926
        $sql = "
927
            SELECT
928
                'urn:ogc:def:crs:EPSG::' || crs.coord_ref_sys_code AS constant_value,
929
                crs.coord_ref_sys_name AS constant_name,
930
                crs.coord_ref_sys_name || '\n' || 'Extent: ' || e.extent_description || '\n' || crs.remarks AS constant_help,
931
                crs.deprecated
932
            FROM epsg_coordinatereferencesystem crs
933
            LEFT JOIN epsg_usage u ON u.object_table_name = 'epsg_coordinatereferencesystem' AND u.object_code = crs.coord_ref_sys_code
934
            LEFT JOIN epsg_extent e ON u.extent_code = e.extent_code
935
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatereferencesystem' AND dep.object_code = crs.coord_ref_sys_code AND dep.deprecation_date <= '2020-12-14'
936
            WHERE dep.deprecation_id IS NULL AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
937
            AND (crs.cmpd_horizcrs_code IS NULL OR crs.cmpd_horizcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind IN ('engineering', 'derived')))
938
            AND (crs.cmpd_vertcrs_code IS NULL OR crs.cmpd_vertcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind IN ('engineering', 'derived')))
939
            AND crs.coord_ref_sys_kind = 'projected'
940
            AND crs.coord_ref_sys_name NOT LIKE '%(ft%'  -- some US states do require feet, but official SPCS definitions are metric so prefer those for constants
941
            GROUP BY crs.coord_ref_sys_code
942
            ORDER BY constant_name
943
        ";
944
945
        $result = $sqlite->query($sql);
946
        $constants = [];
947
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
948
            $constants[] = $row;
949
        }
950
951
        $this->updateFileConstants($this->sourceDir . '/CoordinateReferenceSystem/Projected.php', $constants, 'public');
952
953
        /*
954
         * vertical
955
         */
956
        $sql = "
957
            SELECT
958
                'urn:ogc:def:crs:EPSG::' || crs.coord_ref_sys_code AS constant_value,
959
                crs.coord_ref_sys_name AS constant_name,
960
                crs.coord_ref_sys_name || '\n' || 'Extent: ' || e.extent_description || '\n' || crs.remarks AS constant_help,
961
                crs.deprecated
962
            FROM epsg_coordinatereferencesystem crs
963
            LEFT JOIN epsg_usage u ON u.object_table_name = 'epsg_coordinatereferencesystem' AND u.object_code = crs.coord_ref_sys_code
964
            LEFT JOIN epsg_extent e ON u.extent_code = e.extent_code
965
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatereferencesystem' AND dep.object_code = crs.coord_ref_sys_code AND dep.deprecation_date <= '2020-12-14'
966
            WHERE dep.deprecation_id IS NULL AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
967
            AND (crs.cmpd_horizcrs_code IS NULL OR crs.cmpd_horizcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind IN ('engineering', 'derived')))
968
            AND (crs.cmpd_vertcrs_code IS NULL OR crs.cmpd_vertcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind IN ('engineering', 'derived')))
969
            AND crs.coord_ref_sys_kind = 'vertical'
970
            GROUP BY crs.coord_ref_sys_code
971
            ORDER BY constant_name
972
        ";
973
974
        $result = $sqlite->query($sql);
975
        $constants = [];
976
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
977
            $constants[] = $row;
978
        }
979
980
        $this->updateFileConstants($this->sourceDir . '/CoordinateReferenceSystem/Vertical.php', $constants, 'public');
981
982
        /*
983
         * other
984
         */
985
        $sql = "
986
            SELECT
987
                'urn:ogc:def:crs:EPSG::' || crs.coord_ref_sys_code AS constant_value,
988
                crs.coord_ref_sys_kind || '_' || crs.coord_ref_sys_name AS constant_name,
989
                crs.coord_ref_sys_name || '\n' || 'Type: ' || crs.coord_ref_sys_kind || '\n' || 'Extent: ' || e.extent_description || '\n' || crs.remarks AS constant_help,
990
                crs.deprecated
991
            FROM epsg_coordinatereferencesystem crs
992
            LEFT JOIN epsg_usage u ON u.object_table_name = 'epsg_coordinatereferencesystem' AND u.object_code = crs.coord_ref_sys_code
993
            LEFT JOIN epsg_extent e ON u.extent_code = e.extent_code
994
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatereferencesystem' AND dep.object_code = crs.coord_ref_sys_code AND dep.deprecation_date <= '2020-12-14'
995
            WHERE dep.deprecation_id IS NULL AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
996
            AND (crs.cmpd_horizcrs_code IS NULL OR crs.cmpd_horizcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind IN ('engineering', 'derived')))
997
            AND (crs.cmpd_vertcrs_code IS NULL OR crs.cmpd_vertcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind IN ('engineering', 'derived')))
998
            AND crs.coord_ref_sys_kind NOT IN ('compound', 'geocentric', 'geographic 2D', 'geographic 3D', 'projected', 'vertical')
999
            GROUP BY crs.coord_ref_sys_code
1000
            ORDER BY constant_name
1001
        ";
1002
1003
        $result = $sqlite->query($sql);
1004
        $constants = [];
1005
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
1006
            $constants[] = $row;
1007
        }
1008
1009
        $this->updateFileConstants($this->sourceDir . '/CoordinateReferenceSystem/CoordinateReferenceSystem.php', $constants, 'public');
1010
    }
1011
1012
    public function generateDataCoordinateReferenceSystems(SQLite3 $sqlite): void
1013
    {
1014
        /*
1015
         * compound
1016
         */
1017
        $sql = "
1018
            SELECT
1019
                'urn:ogc:def:crs:EPSG::' || crs.coord_ref_sys_code AS urn,
1020
                crs.coord_ref_sys_name AS name,
1021
                'urn:ogc:def:crs:EPSG::' || crs.cmpd_horizcrs_code AS horizontal_crs,
1022
                horizontal.coord_ref_sys_kind AS horizontal_crs_type,
1023
                'urn:ogc:def:crs:EPSG::' || crs.cmpd_vertcrs_code AS vertical_crs
1024
            FROM epsg_coordinatereferencesystem crs
1025
            JOIN epsg_coordinatereferencesystem horizontal ON horizontal.coord_ref_sys_code = crs.cmpd_horizcrs_code
1026
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatereferencesystem' AND dep.object_code = crs.coord_ref_sys_code AND dep.deprecation_date <= '2020-12-14'
1027
            WHERE dep.deprecation_id IS NULL AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
1028
            AND (crs.cmpd_horizcrs_code IS NULL OR crs.cmpd_horizcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind = 'engineering'))
1029
            AND (crs.cmpd_vertcrs_code IS NULL OR crs.cmpd_vertcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind = 'engineering'))
1030
            AND crs.coord_ref_sys_kind = 'compound'
1031
            ORDER BY urn
1032
            ";
1033
1034
        $result = $sqlite->query($sql);
1035
        $data = [];
1036
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
1037
            $data[$row['urn']] = $row;
1038
            unset($data[$row['urn']]['urn']);
1039
        }
1040
1041
        $this->updateFileData($this->sourceDir . '/CoordinateReferenceSystem/Compound.php', $data);
1042
1043
        /*
1044
         * geocentric
1045
         */
1046
        $sql = "
1047
            SELECT
1048
                'urn:ogc:def:crs:EPSG::' || crs.coord_ref_sys_code AS urn,
1049
                crs.coord_ref_sys_name AS name,
1050
                'urn:ogc:def:cs:EPSG::' || crs.coord_sys_code AS coordinate_system,
1051
                'urn:ogc:def:datum:EPSG::' || COALESCE(crs.datum_code, crs_base.datum_code) AS datum
1052
            FROM epsg_coordinatereferencesystem crs
1053
            LEFT JOIN epsg_coordinatereferencesystem crs_base ON crs_base.coord_ref_sys_code = crs.base_crs_code
1054
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatereferencesystem' AND dep.object_code = crs.coord_ref_sys_code AND dep.deprecation_date <= '2020-12-14'
1055
            WHERE dep.deprecation_id IS NULL AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
1056
            AND (crs.cmpd_horizcrs_code IS NULL OR crs.cmpd_horizcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind = 'engineering'))
1057
            AND (crs.cmpd_vertcrs_code IS NULL OR crs.cmpd_vertcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind = 'engineering'))
1058
            AND crs.coord_ref_sys_kind = 'geocentric'
1059
            ORDER BY urn
1060
            ";
1061
1062
        $result = $sqlite->query($sql);
1063
        $data = [];
1064
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
1065
            $data[$row['urn']] = $row;
1066
            unset($data[$row['urn']]['urn']);
1067
        }
1068
1069
        $this->updateFileData($this->sourceDir . '/CoordinateReferenceSystem/Geocentric.php', $data);
1070
1071
        /*
1072
         * geographic 2D
1073
         */
1074
        $sql = "
1075
            SELECT
1076
                'urn:ogc:def:crs:EPSG::' || crs.coord_ref_sys_code AS urn,
1077
                crs.coord_ref_sys_name AS name,
1078
                'urn:ogc:def:cs:EPSG::' || crs.coord_sys_code AS coordinate_system,
1079
                'urn:ogc:def:datum:EPSG::' || COALESCE(crs.datum_code, crs_base.datum_code) AS datum
1080
            FROM epsg_coordinatereferencesystem crs
1081
            LEFT JOIN epsg_coordinatereferencesystem crs_base ON crs_base.coord_ref_sys_code = crs.base_crs_code
1082
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatereferencesystem' AND dep.object_code = crs.coord_ref_sys_code AND dep.deprecation_date <= '2020-12-14'
1083
            WHERE dep.deprecation_id IS NULL AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
1084
            AND (crs.cmpd_horizcrs_code IS NULL OR crs.cmpd_horizcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind = 'engineering'))
1085
            AND (crs.cmpd_vertcrs_code IS NULL OR crs.cmpd_vertcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind = 'engineering'))
1086
            AND crs.coord_ref_sys_kind = 'geographic 2D'
1087
            ORDER BY urn
1088
            ";
1089
1090
        $result = $sqlite->query($sql);
1091
        $data = [];
1092
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
1093
            $data[$row['urn']] = $row;
1094
            unset($data[$row['urn']]['urn']);
1095
        }
1096
1097
        $this->updateFileData($this->sourceDir . '/CoordinateReferenceSystem/Geographic2D.php', $data);
1098
1099
        /*
1100
         * geographic 3D
1101
         */
1102
        $sql = "
1103
            SELECT
1104
                'urn:ogc:def:crs:EPSG::' || crs.coord_ref_sys_code AS urn,
1105
                crs.coord_ref_sys_name AS name,
1106
                'urn:ogc:def:cs:EPSG::' || crs.coord_sys_code AS coordinate_system,
1107
                'urn:ogc:def:datum:EPSG::' || COALESCE(crs.datum_code, crs_base.datum_code) AS datum
1108
            FROM epsg_coordinatereferencesystem crs
1109
            LEFT JOIN epsg_coordinatereferencesystem crs_base ON crs_base.coord_ref_sys_code = crs.base_crs_code
1110
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatereferencesystem' AND dep.object_code = crs.coord_ref_sys_code AND dep.deprecation_date <= '2020-12-14'
1111
            WHERE dep.deprecation_id IS NULL AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
1112
            AND (crs.cmpd_horizcrs_code IS NULL OR crs.cmpd_horizcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind = 'engineering'))
1113
            AND (crs.cmpd_vertcrs_code IS NULL OR crs.cmpd_vertcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind = 'engineering'))
1114
            AND crs.coord_ref_sys_kind = 'geographic 3D'
1115
            ORDER BY urn
1116
            ";
1117
1118
        $result = $sqlite->query($sql);
1119
        $data = [];
1120
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
1121
            $data[$row['urn']] = $row;
1122
            unset($data[$row['urn']]['urn']);
1123
        }
1124
1125
        $this->updateFileData($this->sourceDir . '/CoordinateReferenceSystem/Geographic3D.php', $data);
1126
1127
        /*
1128
         * projected
1129
         */
1130
        $sql = "
1131
            SELECT
1132
                'urn:ogc:def:crs:EPSG::' || crs.coord_ref_sys_code AS urn,
1133
                crs.coord_ref_sys_name AS name,
1134
                'urn:ogc:def:cs:EPSG::' || crs.coord_sys_code AS coordinate_system,
1135
                'urn:ogc:def:datum:EPSG::' || COALESCE(crs.datum_code, crs_base.datum_code) AS datum
1136
            FROM epsg_coordinatereferencesystem crs
1137
            LEFT JOIN epsg_coordinatereferencesystem crs_base ON crs_base.coord_ref_sys_code = crs.base_crs_code
1138
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatereferencesystem' AND dep.object_code = crs.coord_ref_sys_code AND dep.deprecation_date <= '2020-12-14'
1139
            WHERE dep.deprecation_id IS NULL AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
1140
            AND (crs.cmpd_horizcrs_code IS NULL OR crs.cmpd_horizcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind = 'engineering'))
1141
            AND (crs.cmpd_vertcrs_code IS NULL OR crs.cmpd_vertcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind = 'engineering'))
1142
            AND crs.coord_ref_sys_kind = 'projected'
1143
            ORDER BY urn
1144
            ";
1145
1146
        $result = $sqlite->query($sql);
1147
        $data = [];
1148
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
1149
            $data[$row['urn']] = $row;
1150
            unset($data[$row['urn']]['urn']);
1151
        }
1152
1153
        $this->updateFileData($this->sourceDir . '/CoordinateReferenceSystem/Projected.php', $data);
1154
1155
        /*
1156
         * vertical
1157
         */
1158
        $sql = "
1159
            SELECT
1160
                'urn:ogc:def:crs:EPSG::' || crs.coord_ref_sys_code AS urn,
1161
                crs.coord_ref_sys_name AS name,
1162
                'urn:ogc:def:cs:EPSG::' || crs.coord_sys_code AS coordinate_system,
1163
                'urn:ogc:def:datum:EPSG::' || COALESCE(crs.datum_code, crs_base.datum_code) AS datum
1164
            FROM epsg_coordinatereferencesystem crs
1165
            LEFT JOIN epsg_coordinatereferencesystem crs_base ON crs_base.coord_ref_sys_code = crs.base_crs_code
1166
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatereferencesystem' AND dep.object_code = crs.coord_ref_sys_code AND dep.deprecation_date <= '2020-12-14'
1167
            WHERE dep.deprecation_id IS NULL AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
1168
            AND (crs.cmpd_horizcrs_code IS NULL OR crs.cmpd_horizcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind = 'engineering'))
1169
            AND (crs.cmpd_vertcrs_code IS NULL OR crs.cmpd_vertcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind = 'engineering'))
1170
            AND crs.coord_ref_sys_kind = 'vertical'
1171
            ORDER BY urn
1172
            ";
1173
1174
        $result = $sqlite->query($sql);
1175
        $data = [];
1176
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
1177
            $data[$row['urn']] = $row;
1178
            unset($data[$row['urn']]['urn']);
1179
        }
1180
1181
        $this->updateFileData($this->sourceDir . '/CoordinateReferenceSystem/Vertical.php', $data);
1182
1183
        /*
1184
         * other
1185
         */
1186
        $sql = "
1187
            SELECT
1188
                'urn:ogc:def:crs:EPSG::' || crs.coord_ref_sys_code AS urn,
1189
                crs.coord_ref_sys_kind AS kind,
1190
                crs.coord_ref_sys_name AS name,
1191
                'urn:ogc:def:cs:EPSG::' || crs.coord_sys_code AS coordinate_system,
1192
                'urn:ogc:def:datum:EPSG::' || COALESCE(crs.datum_code, crs_base.datum_code) AS datum
1193
            FROM epsg_coordinatereferencesystem crs
1194
            LEFT JOIN epsg_coordinatereferencesystem crs_base ON crs_base.coord_ref_sys_code = crs.base_crs_code
1195
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordinatereferencesystem' AND dep.object_code = crs.coord_ref_sys_code AND dep.deprecation_date <= '2020-12-14'
1196
            WHERE dep.deprecation_id IS NULL AND crs.coord_ref_sys_kind NOT IN ('engineering', 'derived') AND crs.coord_ref_sys_name NOT LIKE '%example%'
1197
            AND (crs.cmpd_horizcrs_code IS NULL OR crs.cmpd_horizcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind = 'engineering'))
1198
            AND (crs.cmpd_vertcrs_code IS NULL OR crs.cmpd_vertcrs_code NOT IN (SELECT coord_ref_sys_code FROM epsg_coordinatereferencesystem WHERE coord_ref_sys_kind = 'engineering'))
1199
            AND crs.coord_ref_sys_kind NOT IN ('compound', 'geocentric', 'geographic 2D', 'geographic 3D', 'projected', 'vertical')
1200
            ORDER BY urn
1201
            ";
1202
1203
        $result = $sqlite->query($sql);
1204
        $data = [];
1205
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
1206
            $data[$row['urn']] = $row;
1207
            unset($data[$row['urn']]['urn']);
1208
        }
1209
1210
        $this->updateFileData($this->sourceDir . '/CoordinateReferenceSystem/CoordinateReferenceSystem.php', $data);
1211
    }
1212
1213
    public function generateConstantsCoordinateOperationMethods(SQLite3 $sqlite): void
1214
    {
1215
        $sql = "
1216
            SELECT
1217
                'urn:ogc:def:method:EPSG::' || m.coord_op_method_code AS constant_value,
1218
                m.coord_op_method_name AS constant_name,
1219
                m.coord_op_method_name || '\n' || m.remarks AS constant_help,
1220
                m.deprecated
1221
            FROM epsg_coordoperationmethod m
1222
            JOIN epsg_coordoperation o on m.coord_op_method_code = o.coord_op_method_code -- only want methods that are actually used
1223
            LEFT JOIN epsg_coordoperationparamvalue p ON p.coord_op_code = o.coord_op_code AND p.coord_op_method_code = m.coord_op_method_code
1224
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordoperationmethod' AND dep.object_code = m.coord_op_method_code AND dep.deprecation_date <= '2020-12-14'
1225
            WHERE dep.deprecation_id IS NULL
1226
            AND o.coord_op_type != 'conversion'
1227
            AND m.coord_op_method_name NOT LIKE '%wellbore%'
1228
            AND m.coord_op_method_name NOT LIKE '%mining%'
1229
            AND m.coord_op_method_name NOT LIKE '%seismic%'
1230
            AND o.coord_op_name NOT LIKE '%example%'
1231
            AND o.remarks NOT LIKE '%user-defined%'
1232
            GROUP BY m.coord_op_method_code
1233
            HAVING (SUM(CASE WHEN p.param_value_file_ref != '' THEN 1 ELSE 0 END) = 0) -- skip anything that needs some kind of datafile
1234
1235
            UNION
1236
1237
            SELECT
1238
                'urn:ogc:def:method:EPSG::' || m.coord_op_method_code AS constant_value,
1239
                m.coord_op_method_name AS constant_name,
1240
                m.coord_op_method_name || '\n' || m.remarks AS constant_help,
1241
                m.deprecated
1242
            FROM epsg_coordoperationmethod m
1243
            JOIN epsg_coordoperation o on m.coord_op_method_code = o.coord_op_method_code -- only want methods that are actually used
1244
            JOIN epsg_coordinatereferencesystem crs ON crs.projection_conv_code = o.coord_op_code
1245
            LEFT JOIN epsg_coordoperationparamvalue p ON p.coord_op_code = o.coord_op_code AND p.coord_op_method_code = m.coord_op_method_code
1246
            LEFT JOIN epsg_deprecation dep_method ON dep_method.object_table_name = 'epsg_coordoperationmethod' AND dep_method.object_code = m.coord_op_method_code AND dep_method.deprecation_date <= '2020-12-14'
1247
            LEFT JOIN epsg_deprecation dep_crs ON dep_crs.object_table_name = 'epsg_coordinatereferencesystem' AND dep_crs.object_code = crs.coord_ref_sys_code AND dep_crs.deprecation_date <= '2020-12-14'
1248
            WHERE dep_method.deprecation_id IS NULL AND dep_crs.deprecation_id IS NULL
1249
            AND m.coord_op_method_name NOT LIKE '%wellbore%'
1250
            AND m.coord_op_method_name NOT LIKE '%mining%'
1251
            AND m.coord_op_method_name NOT LIKE '%seismic%'
1252
            AND o.coord_op_name NOT LIKE '%example%'
1253
            AND o.remarks NOT LIKE '%user-defined%'
1254
            GROUP BY m.coord_op_method_code
1255
            HAVING (SUM(CASE WHEN p.param_value_file_ref != '' THEN 1 ELSE 0 END) = 0) -- skip anything that needs some kind of datafile
1256
1257
            ORDER BY constant_name
1258
        ";
1259
1260
        $result = $sqlite->query($sql);
1261
        $constants = [];
1262
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
1263
            $constants[] = $row;
1264
        }
1265
1266
        $this->updateFileConstants($this->sourceDir . '/CoordinateOperation/CoordinateOperationMethods.php', $constants, 'protected');
1267
    }
1268
1269
    public function generateDataCoordinateOperations(SQLite3 $sqlite): void
1270
    {
1271
        $sql = "
1272
            SELECT
1273
                'urn:ogc:def:coordinateOperation:EPSG::' || o.coord_op_code AS urn,
1274
                o.coord_op_name AS name,
1275
                o.coord_op_type AS type,
1276
                'urn:ogc:def:crs:EPSG::' || o.source_crs_code AS source_crs,
1277
                'urn:ogc:def:crs:EPSG::' || o.target_crs_code AS target_crs,
1278
                'urn:ogc:def:method:EPSG::' || o.coord_op_method_code AS method,
1279
                m.reverse_op AS reversible,
1280
                e.bbox_north_bound_lat AS bbox_north_bound_latitude,
1281
                e.bbox_east_bound_lon AS bbox_east_bound_longitude,
1282
                e.bbox_south_bound_lat AS bbox_south_bound_latitude,
1283
                e.bbox_west_bound_lon AS bbox_west_bound_longitude
1284
            FROM epsg_coordoperation o
1285
            JOIN epsg_coordoperationmethod m ON m.coord_op_method_code = o.coord_op_method_code
1286
            LEFT JOIN epsg_usage u ON u.object_table_name = 'epsg_coordoperation' AND u.object_code = o.coord_op_code
1287
            LEFT JOIN epsg_extent e ON u.extent_code = e.extent_code
1288
            LEFT JOIN epsg_coordoperationparamvalue p ON p.coord_op_code = o.coord_op_code
1289
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordoperation' AND dep.object_code = o.coord_op_code AND dep.deprecation_date <= '2020-12-14'
1290
            WHERE o.coord_op_type != 'conversion' AND o.coord_op_type != 'concatenated operation'
1291
            AND dep.deprecation_id IS NULL
1292
            GROUP BY o.coord_op_code
1293
            HAVING (SUM(CASE WHEN p.param_value_file_ref != '' THEN 1 ELSE 0 END) = 0) -- skip anything that needs some kind of datafile
1294
1295
            UNION
1296
1297
            SELECT
1298
                'urn:ogc:def:coordinateOperation:EPSG::' || o.coord_op_code AS urn,
1299
                o.coord_op_name AS name,
1300
                o.coord_op_type AS type,
1301
                'urn:ogc:def:crs:EPSG::' || crs.base_crs_code AS source_crs,
1302
                'urn:ogc:def:crs:EPSG::' || crs.coord_ref_sys_code AS target_crs,
1303
                'urn:ogc:def:method:EPSG::' || o.coord_op_method_code AS method,
1304
                m.reverse_op AS reversible,
1305
                e.bbox_north_bound_lat AS bbox_north_bound_latitude,
1306
                e.bbox_east_bound_lon AS bbox_east_bound_longitude,
1307
                e.bbox_south_bound_lat AS bbox_south_bound_latitude,
1308
                e.bbox_west_bound_lon AS bbox_west_bound_longitude
1309
            FROM epsg_coordoperation o
1310
            JOIN epsg_coordinatereferencesystem crs ON crs.projection_conv_code = o.coord_op_code
1311
            JOIN epsg_coordoperationmethod m ON m.coord_op_method_code = o.coord_op_method_code
1312
            LEFT JOIN epsg_usage u ON u.object_table_name = 'epsg_coordoperation' AND u.object_code = o.coord_op_code
1313
            LEFT JOIN epsg_extent e ON u.extent_code = e.extent_code
1314
            LEFT JOIN epsg_coordoperationparamvalue p ON p.coord_op_code = o.coord_op_code
1315
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordoperation' AND dep.object_code = o.coord_op_code AND dep.deprecation_date <= '2020-12-14'
1316
            WHERE o.coord_op_type = 'conversion'
1317
            AND dep.deprecation_id IS NULL
1318
            GROUP BY o.coord_op_code
1319
            HAVING (SUM(CASE WHEN p.param_value_file_ref != '' THEN 1 ELSE 0 END) = 0) -- skip anything that needs some kind of datafile
1320
1321
            UNION
1322
1323
            SELECT
1324
                'urn:ogc:def:coordinateOperation:EPSG::' || o.coord_op_code AS urn,
1325
                o.coord_op_name AS name,
1326
                o.coord_op_type AS type,
1327
                'urn:ogc:def:crs:EPSG::' || o.source_crs_code AS source_crs,
1328
                'urn:ogc:def:crs:EPSG::' || o.target_crs_code AS target_crs,
1329
                null AS method,
1330
                CASE WHEN SUM(CASE WHEN cm.reverse_op = 0 THEN 1 ELSE 0 END) = 0 THEN 1 ELSE 0 END AS reversible,
1331
                e.bbox_north_bound_lat AS bbox_north_bound_latitude,
1332
                e.bbox_east_bound_lon AS bbox_east_bound_longitude,
1333
                e.bbox_south_bound_lat AS bbox_south_bound_latitude,
1334
                e.bbox_west_bound_lon AS bbox_west_bound_longitude
1335
            FROM epsg_coordoperation o
1336
            LEFT JOIN epsg_coordoperationpath p ON p.concat_operation_code = o.coord_op_code
1337
            LEFT JOIN epsg_coordoperation co ON p.single_operation_code = co.coord_op_code
1338
            LEFT JOIN epsg_coordoperationmethod cm ON co.coord_op_method_code = cm.coord_op_method_code
1339
            LEFT JOIN epsg_usage u ON u.object_table_name = 'epsg_coordoperation' AND u.object_code = o.coord_op_code
1340
            LEFT JOIN epsg_extent e ON u.extent_code = e.extent_code
1341
            LEFT JOIN epsg_coordoperationparamvalue p ON p.coord_op_code = o.coord_op_code
1342
            LEFT JOIN epsg_deprecation dep ON dep.object_table_name = 'epsg_coordoperation' AND dep.object_code = o.coord_op_code AND dep.deprecation_date <= '2020-12-14'
1343
            WHERE o.coord_op_type = 'concatenated operation'
1344
            AND dep.deprecation_id IS NULL
1345
            GROUP BY o.coord_op_code
1346
            HAVING (SUM(CASE WHEN p.param_value_file_ref != '' THEN 1 ELSE 0 END) = 0) -- skip anything that needs some kind of datafile
1347
1348
            ORDER BY urn
1349
            ";
1350
1351
        $result = $sqlite->query($sql);
1352
        $data = [];
1353
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
1354
            if ($row['type'] === 'concatenated operation') {
1355
                unset($row['method']);
1356
                $row['operations'] = [];
1357
                $operationsSql = "
1358
                    SELECT
1359
                        'urn:ogc:def:coordinateOperation:EPSG::' || p.concat_operation_code AS concat_code,
1360
                        'urn:ogc:def:coordinateOperation:EPSG::' || p.single_operation_code AS single_code
1361
                    FROM epsg_coordoperationpath p
1362
                    WHERE concat_code = '{$row['urn']}'
1363
                    ORDER BY p.op_path_step
1364
                    ";
1365
1366
                $operationsResult = $sqlite->query($operationsSql);
1367
                while ($operationsRow = $operationsResult->fetchArray(SQLITE3_ASSOC)) {
1368
                    $row['operations'][] = $operationsRow['single_code'];
1369
                }
1370
            } else {
1371
                $row['params'] = [];
1372
                $paramsSql = "
1373
                    SELECT
1374
                        'urn:ogc:def:coordinateOperation:EPSG::' || pv.coord_op_code AS operation_code,
1375
                        'urn:ogc:def:method:EPSG::' || pv.coord_op_method_code AS method_code,
1376
                        p.parameter_name AS name,
1377
                        pv.parameter_value AS value,
1378
                        CASE WHEN pv.uom_code IS NULL THEN NULL ELSE 'urn:ogc:def:uom:EPSG::' || pv.uom_code END AS uom,
1379
                        CASE WHEN pu.param_sign_reversal = 'Yes' THEN 1 ELSE 0 END AS reverses
1380
                    FROM epsg_coordoperationparamvalue pv
1381
                    JOIN epsg_coordoperationparamusage pu ON pv.coord_op_method_code = pu.coord_op_method_code AND pv.parameter_code = pu.parameter_code
1382
                    JOIN epsg_coordoperationparam p ON pv.parameter_code = p.parameter_code
1383
                    WHERE operation_code = '{$row['urn']}' AND method_code = '{$row['method']}'
1384
                    ORDER BY pu.sort_order
1385
                    ";
1386
1387
                $paramsResult = $sqlite->query($paramsSql);
1388
                while ($paramsRow = $paramsResult->fetchArray(SQLITE3_ASSOC)) {
1389
                    unset($paramsRow['operation_code']);
1390
                    unset($paramsRow['method_code']);
1391
                    $paramsRow['reverses'] = (bool) $paramsRow['reverses'];
1392
                    if (!$row['reversible']) {
1393
                        unset($paramsRow['reverses']);
1394
                    }
1395
                    $row['params'][$paramsRow['name']] = $paramsRow;
1396
                    unset($row['params'][$paramsRow['name']]['name']);
1397
                }
1398
            }
1399
1400
            $row['reversible'] = (bool) $row['reversible'];
1401
            $row['bounding_box'] = ['north' => $row['bbox_north_bound_latitude'], 'east' => $row['bbox_east_bound_longitude'], 'south' => $row['bbox_south_bound_latitude'], 'west' => $row['bbox_west_bound_longitude']];
1402
            $data[$row['urn']] = $row;
1403
            unset($data[$row['urn']]['urn']);
1404
            unset($data[$row['urn']]['bbox_north_bound_latitude']);
1405
            unset($data[$row['urn']]['bbox_east_bound_longitude']);
1406
            unset($data[$row['urn']]['bbox_south_bound_latitude']);
1407
            unset($data[$row['urn']]['bbox_west_bound_longitude']);
1408
        }
1409
1410
        $this->updateFileData($this->sourceDir . '/CoordinateOperation/CoordinateOperation.php', $data);
1411
    }
1412
1413
    private function updateFileConstants(string $fileName, array $classConstants, string $visibility): void
1414
    {
1415
        echo "Updating constants in {$fileName}...";
1416
1417
        $lexer = new Emulative(
1418
            [
1419
                'usedAttributes' => [
1420
                    'comments',
1421
                    'startLine', 'endLine',
1422
                    'startTokenPos', 'endTokenPos',
1423
                ],
1424
            ]
1425
        );
1426
        $parser = new Php7($lexer);
1427
1428
        $traverser = new NodeTraverser();
1429
        $traverser->addVisitor(new CloningVisitor());
1430
1431
        $oldStmts = $parser->parse(file_get_contents($fileName));
1432
        $oldTokens = $lexer->getTokens();
1433
1434
        $newStmts = $traverser->traverse($oldStmts);
1435
1436
        /*
1437
         * First remove all existing EPSG consts
1438
         */
1439
        $traverser = new NodeTraverser();
1440
        $traverser->addVisitor(new RemoveExistingConstantsVisitor());
1441
        $newStmts = $traverser->traverse($newStmts);
1442
1443
        /*
1444
         * Then add the ones wanted
1445
         */
1446
        $traverser = new NodeTraverser();
1447
        $traverser->addVisitor(new AddNewConstantsVisitor($classConstants, $visibility));
1448
        $newStmts = $traverser->traverse($newStmts);
1449
1450
        $prettyPrinter = new ASTPrettyPrinter();
1451
        file_put_contents($fileName, $prettyPrinter->printFormatPreserving($newStmts, $oldStmts, $oldTokens));
1452
        $this->csFixFile($fileName);
1453
        echo 'done' . PHP_EOL;
1454
    }
1455
1456
    private function updateFileData(string $fileName, array $data): void
1457
    {
1458
        echo "Updating data in {$fileName}...";
1459
1460
        $lexer = new Emulative(
1461
            [
1462
                'usedAttributes' => [
1463
                    'comments',
1464
                    'startLine', 'endLine',
1465
                    'startTokenPos', 'endTokenPos',
1466
                ],
1467
            ]
1468
        );
1469
        $parser = new Php7($lexer);
1470
1471
        $traverser = new NodeTraverser();
1472
        $traverser->addVisitor(new CloningVisitor());
1473
1474
        $oldStmts = $parser->parse(file_get_contents($fileName));
1475
        $oldTokens = $lexer->getTokens();
1476
1477
        $newStmts = $traverser->traverse($oldStmts);
1478
1479
        /*
1480
         * First remove all existing EPSG consts
1481
         */
1482
        $traverser = new NodeTraverser();
1483
        $traverser->addVisitor(new RemoveExistingDataVisitor());
1484
        $newStmts = $traverser->traverse($newStmts);
1485
1486
        /*
1487
         * Then add the ones wanted
1488
         */
1489
        if ($data) {
1490
            $traverser = new NodeTraverser();
1491
            $traverser->addVisitor(new AddNewDataVisitor($data));
1492
            $newStmts = $traverser->traverse($newStmts);
1493
        }
1494
1495
        $prettyPrinter = new ASTPrettyPrinter();
1496
        file_put_contents($fileName, $prettyPrinter->printFormatPreserving($newStmts, $oldStmts, $oldTokens));
1497
        $this->csFixFile($fileName);
1498
        echo 'done' . PHP_EOL;
1499
    }
1500
1501
    private function csFixFile(string $fileName): void
1502
    {
1503
        /** @var Config $config */
1504
        $config = require __DIR__ . '/../../../.php_cs.dist';
1505
1506
        $resolver = new ConfigurationResolver(
1507
            $config,
1508
            [],
1509
            dirname($this->sourceDir),
1510
            new ToolInfo()
1511
        );
1512
1513
        $file = new SplFileInfo($fileName);
1514
        $old = file_get_contents($fileName);
1515
        $fixers = $resolver->getFixers();
1516
1517
        $tokens = Tokens::fromCode($old);
1518
1519
        foreach ($fixers as $fixer) {
1520
            if (
1521
                !$fixer instanceof AbstractFixer &&
1522
                (!$fixer->supports($file) || !$fixer->isCandidate($tokens))
1523
            ) {
1524
                continue;
1525
            }
1526
1527
            $fixer->fix($file, $tokens);
1528
1529
            if ($tokens->isChanged()) {
1530
                $tokens->clearEmptyTokens();
1531
                $tokens->clearChanged();
1532
            }
1533
        }
1534
1535
        $new = $tokens->generateCode();
1536
1537
        if ($old !== $new) {
1538
            file_put_contents($fileName, $new);
1539
        }
1540
    }
1541
}
1542