-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathOverpassCommand.php
More file actions
140 lines (121 loc) · 4.65 KB
/
OverpassCommand.php
File metadata and controls
140 lines (121 loc) · 4.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<?php
namespace App\Command;
use App\Exception\FileException;
use ErrorException;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Execute Overpass query for relations and ways using Overpass API and store result.
*
* @package App\Command
*/
class OverpassCommand extends AbstractCommand
{
/** {@inheritdoc} */
protected static $defaultName = 'overpass';
/** @var string Filename for the result of Overpass query for relations. */
public const FILENAME_RELATION = 'relation.json';
/** @var string Filename for the result of Overpass query for ways. */
public const FILENAME_WAY = 'way.json';
/** @var string Filename of Overpass query for relations. */
protected const OVERPASS_RELATION = 'relation-full-json.overpassql';
/** @var string Filename of Overpass query for ways. */
protected const OVERPASS_WAY = 'way-full-json.overpassql';
/** @var string Overpass API URL. */
protected const URL = 'https://overpass-api.de/api/interpreter';
/**
* {@inheritdoc}
*
* @return void
*
* @throws InvalidArgumentException
*/
protected function configure(): void
{
parent::configure();
$this->setDescription('Download data from OpenStreetMap with Overpass API.');
}
/**
* {@inheritdoc}
*
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
try {
parent::execute($input, $output);
// Check path of Overpass query for relations.
$relationPath = sprintf('%s/overpass/%s', $this->cityDir, self::OVERPASS_RELATION);
if (!file_exists($relationPath) || !is_readable($relationPath)) {
throw new FileException(sprintf('File "%s" doesn\'t exist or is not readable.', $relationPath));
}
// Check path of Overpass query for ways.
$wayPath = sprintf('%s/overpass/%s', $this->cityDir, self::OVERPASS_WAY);
if (!file_exists($wayPath) || !is_readable($wayPath)) {
throw new FileException(sprintf('File "%s" doesn\'t exist or is not readable.', $wayPath));
}
// Create `overpass` directory to store results.
$outputDir = sprintf('%s/overpass', self::OUTPUTDIR);
if (!file_exists($outputDir) || !is_dir($outputDir)) {
mkdir($outputDir, 0777, true);
}
// Execute Overpass query for relations and store result.
$overpassR = file_get_contents($relationPath);
if ($overpassR !== false) {
self::save($overpassR, sprintf('%s/%s', $outputDir, self::FILENAME_RELATION));
}
// Execute Overpass query for ways and store result.
$overpassW = file_get_contents($wayPath);
if ($overpassW !== false) {
self::save($overpassW, sprintf('%s/%s', $outputDir, self::FILENAME_WAY));
}
return Command::SUCCESS;
} catch (Exception $error) {
$output->writeln(sprintf('<error>%s</error>', $error->getMessage()));
return Command::FAILURE;
}
}
/**
* Send request and store result.
*
* @param string $query Overpass query.
* @param string $path Path where to store the result.
* @return void
*
* @throws GuzzleException
*/
private static function save(string $query, string $path): void
{
$retryMiddleware = Middleware::retry(
function ($retries, $request, $response, $exception) {
// Stop retrying after 3 attempts
if ($retries >= 3) {
return false;
}
// Retry on 504 Gateway Timeout
if ($response && $response->getStatusCode() === 504) {
return true;
}
return false;
}
);
$stack = HandlerStack::create();
$stack->push($retryMiddleware);
$client = new \GuzzleHttp\Client(['handler' => $stack]);
$client->request('POST', self::URL, [
'body' => sprintf('data=%s', urlencode($query)),
'headers' => [
'User-Agent' => 'EqualStreetNames (+https://equalstreetnames.org/)',
],
'sink' => $path,
]);
}
}