LGV_TZ_Lookup 1.4.2
Time zone lookup for PHP applications and HTTP clients
Loading...
Searching...
No Matches
composer.php
Go to the documentation of this file.
1<?php
2
3declare(strict_types=1);
4
5// Run against a clean consumer installation to verify the library's actual Composer autoload paths.
6$options = getopt('', ['autoload:', 'with-loader', 'mysql:']);
7$autoload = $options['autoload'] ?? dirname(__DIR__).'/vendor/autoload.php';
8if (!is_file($autoload)) {
9 throw new RuntimeException('Install Composer dependencies first, or supply --autoload=/path/to/vendor/autoload.php.');
10}
12function composerCheck($expected, $actual, string $message): void {
13 global $checks;
14 ++$checks;
15 if ($expected !== $actual) {
16 throw new RuntimeException($message.': expected '.var_export($expected, true).', got '.var_export($actual, true));
17 }
18}
19ob_start();
20require $autoload;
21composerCheck('', ob_get_clean(), 'Autoloading has no output');
22// Load PDO first: it must work independently of the database class or a server-specific constant.
23ob_start();
24foreach (['LGV_TZ_Lookup_PDO', 'LGV_TZ_Lookup_Entity', 'LGV_TZ_Lookup_Database', 'LGV_TZ_Lookup_Query'] as $class) {
25 composerCheck(true, class_exists($class), 'Composer autoloads '.$class);
26}
27composerCheck('', ob_get_clean(), 'Loading library classes has no output');
28composerCheck(false, class_exists('LGV_TZ_Lookup_Loader', false), 'Lookup does not eagerly load the boundary loader');
29composerCheck(false, class_exists('JsonStreamingParser\\Parser', false), 'Lookup does not eagerly load the JSON parser');
30
31$connection = new PDO('sqlite::memory:');
32$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
33$connection->exec('CREATE TABLE timezones (
34 id INTEGER PRIMARY KEY, tzname TEXT, east REAL, west REAL, north REAL, south REAL, polygon BLOB
35)');
36$insert = $connection->prepare('INSERT INTO timezones VALUES (?, ?, 4, 0, 4, 0, ?)');
37foreach ([
38 [1, 'America/New_York', [0, 0, 4, 0, 4, 1, 0, 1, 0, 0]],
39 [2, 'America/Chicago', [0, 0, 4, 0, 4, 4, 0, 4, 0, 0]],
40 [3, 'Etc/GMT', [0, 0, 4, 0, 4, 4, 0, 4, 0, 0]],
41] as [$id, $zone, $points]) {
42 $insert->bindValue(1, $id, PDO::PARAM_INT);
43 $insert->bindValue(2, $zone, PDO::PARAM_STR);
44 $insert->bindValue(3, pack('d*', ...$points), PDO::PARAM_LOB);
45 $insert->execute();
46}
47$wrapper = (new ReflectionClass(LGV_TZ_Lookup_PDO::class))->newInstanceWithoutConstructor();
48$connectionProperty = new ReflectionProperty(LGV_TZ_Lookup_PDO::class, '_pdo');
49if (PHP_VERSION_ID < 80100) { $connectionProperty->setAccessible(true); }
51$wrapper->driver_type = 'sqlite';
52$database = (new ReflectionClass(LGV_TZ_Lookup_Database::class))->newInstanceWithoutConstructor();
53$database->pdo_instance = $wrapper;
55composerCheck('America/Chicago', $lookup->get_tz(2, 2), 'Installed package decodes candidate polygons');
56composerCheck('', $lookup->get_tz(10, 10), 'Installed package returns empty for no match');
57$connection->exec('DELETE FROM timezones WHERE id = 2');
58$connection->exec("INSERT INTO timezones SELECT 4, 'America/Los_Angeles', east, west, north, south, polygon FROM timezones WHERE id = 1");
59composerCheck('Etc/GMT', $lookup->get_tz(2, 2), 'Installed package handles ocean fallback');
60
61if (isset($options['with-loader'])) {
62 $loaded = new class {
63 public array $entities = [];
64 public int $resets = 0;
65 public function reset_database() { ++$this->resets; }
66 public function store_entity($entity) { $this->entities[] = $entity; }
67 };
68 $listener = new LGV_TZ_Lookup_Loader($loaded);
69 $stream = fopen('php://memory', 'w+b');
70 fwrite($stream, json_encode([
71 'type' => 'FeatureCollection', 'features' => [[
72 'type' => 'Feature', 'properties' => ['tzid' => 'Etc/GMT'],
73 'geometry' => ['type' => 'Polygon', 'coordinates' => [[[0, 0], [4, 0], [4, 4], [0, 4], [0, 0]]]],
74 ]],
75 ], JSON_THROW_ON_ERROR));
76 rewind($stream);
77 try {
78 (new JsonStreamingParser\Parser($stream, $listener))->parse();
79 } finally {
80 fclose($stream);
81 }
82 composerCheck(1, $loaded->resets, 'Optional loader initializes its database');
83 composerCheck(1, count($loaded->entities), 'Optional loader parses a GeoJSON feature');
84 composerCheck('Etc/GMT', $loaded->entities[0]->tzID, 'Optional loader retains the timezone');
85 composerCheck(['east' => 4, 'west' => 0, 'north' => 4, 'south' => 0], $loaded->entities[0]->domainRect, 'Optional loader computes bounds');
86} else {
87 composerCheck(false, class_exists(JsonStreamingParser\Listener\GeoJsonListener::class), 'Lookup installation has no parser dependency');
88 try {
89 class_exists('LGV_TZ_Lookup_Loader');
90 throw new RuntimeException('Expected an optional-loader dependency exception.');
91 } catch (RuntimeException $error) {
92 composerCheck(true, str_contains($error->getMessage(), 'composer require salsify/json-streaming-parser'), 'Missing parser gives installation guidance');
93 }
94}
95
96if (isset($options['mysql'])) {
97 if (!preg_match('/^lgv_tz_benchmark_[a-zA-Z0-9_]+$/D', $options['mysql'])) {
98 throw new InvalidArgumentException('Use an isolated lgv_tz_benchmark_NAME database.');
99 }
100 $timeLimit = ini_get('max_execution_time');
101 $database = new LGV_TZ_Lookup_Database($options['mysql'], getenv('LGV_TZ_BENCH_USER') ?: 'root',
102 getenv('LGV_TZ_BENCH_PASSWORD') ?: '', 'mysql', getenv('LGV_TZ_BENCH_HOST') ?: 'localhost',
103 (int)(getenv('LGV_TZ_BENCH_PORT') ?: 3306));
104 composerCheck($timeLimit, ini_get('max_execution_time'), 'Library connection preserves the application time limit');
106 require __DIR__.'/../src/TestLocations.php';
107 foreach ($test_locations_param_array as $case) {
108 $lng = $case['params']['lng'];
109 $lat = $case['params']['lat'];
110 while ($lng < -180) { $lng += 360; }
111 while ($lng > 180) { $lng -= 360; }
112 while ($lat < -90) { $lat += 180; }
113 while ($lat > 90) { $lat -= 180; }
114 composerCheck($case['result'], $lookup->get_tz($lng, $lat), $case['title']);
115 }
116}
117echo 'Passed '.$checks." Composer integration checks.\n";
$test_locations_param_array
This file has a list of long/lat pairs, along with the expected results, when presented to the server...
$options
Definition composer.php:6
$connection
Definition composer.php:31
foreach([[1, 'America/New_York', [0, 0, 4, 0, 4, 1, 0, 1, 0, 0]], [2, 'America/Chicago', [0, 0, 4, 0, 4, 4, 0, 4, 0, 0]], [3, 'Etc/GMT', [0, 0, 4, 0, 4, 4, 0, 4, 0, 0]],] as[$id, $zone, $points]) $wrapper
Definition composer.php:47
$database
Definition composer.php:52
$insert
Definition composer.php:36
$autoload
Definition composer.php:7
composerCheck($expected, $actual, string $message)
Definition composer.php:12
$connectionProperty
Definition composer.php:48
if(!is_file($autoload)) $checks
Definition composer.php:11
$lookup
Definition composer.php:54
$error
Definition demo.php:116