Skip to content

Commit 2df94c0

Browse files
committed
implement json source
1 parent fef33f3 commit 2df94c0

13 files changed

+152
-27
lines changed

resources/Zip32_11208.zip

472 KB
Binary file not shown.

resources/Zip32_utf8_10501_1.zip

-416 KB
Binary file not shown.

resources/converter.php

+32-11
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,21 @@
22

33
include __DIR__.'/../vendor/autoload.php';
44

5-
use Recca0120\Twzipcode\Sources\CSV;
5+
use Recca0120\Twzipcode\Sources\Csv;
6+
use Recca0120\Twzipcode\Sources\Json;
67
use Recca0120\Twzipcode\Storages\File;
78

9+
// https://data.gov.tw/dataset/5948
10+
$downloadUrl = 'https://quality.data.gov.tw/dq_download_json.php?nid=5948&md5_url=e1f6004ad33eb3ff3a824fb992a4b01a';
11+
$extension = 'json';
12+
$file = __DIR__.'/Zip32_11208.zip';
13+
814
set_error_handler(static function ($severity, $message, $file, $line) {
915
throw new ErrorException($message, $severity, $severity, $file, $line);
1016
});
1117

12-
$start = microtime(true);
13-
$file = __DIR__.'/Zip32_utf8_10501_1.zip';
14-
15-
// https://data.gov.tw/dataset/5948
16-
$url = 'https://quality.data.gov.tw/dq_download_csv.php?nid=5948&md5_url=e1f6004ad33eb3ff3a824fb992a4b01a';
17-
18-
if (file_exists($file) === false) {
19-
touch($file);
18+
function csv($url)
19+
{
2020
$contents = file_get_contents($url);
2121

2222
$encoding = mb_detect_encoding($contents, ['UCS-2LE', 'BIG5', 'UTF-8']);
@@ -30,11 +30,32 @@
3030
throw new RuntimeException($contents);
3131
}
3232

33+
return $contents;
34+
}
35+
36+
function json($url)
37+
{
38+
return file_get_contents($url);
39+
}
40+
41+
$start = microtime(true);
42+
if (file_exists($file) === false) {
43+
$contents = $extension($downloadUrl);
44+
45+
touch($file);
3346
$zip = new ZipArchive;
3447
$zip->open($file, ZipArchive::OVERWRITE);
35-
$zip->addFromString(pathinfo($file, PATHINFO_FILENAME).'.csv', $contents);
48+
$zip->addFromString(pathinfo($file, PATHINFO_FILENAME).'.'.$extension, $contents);
3649
$zip->close();
3750
}
3851

39-
(new File)->load(new CSV($file));
52+
$lookup = [
53+
'csv' => Csv::class,
54+
'json' => Json::class,
55+
];
56+
$class = $lookup[$extension];
57+
58+
$source = new $class($file);
59+
60+
(new File)->load($source);
4061
echo 'benchmark: '.(microtime(true) - $start)."\n";

resources/data/zip5.rules

-7.73 KB
Binary file not shown.

src/Rules.php

+1-4
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ class Rules
1414
*/
1515
private $storage;
1616

17-
/**
18-
* @param Storage|null $storage
19-
*/
20-
public function __construct(Storage $storage = null)
17+
public function __construct(?Storage $storage = null)
2118
{
2219
$this->storage = $storage ?: new File;
2320
}

src/Sources/CSV.php src/Sources/Csv.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace Recca0120\Twzipcode\Sources;
44

5-
class CSV extends Source
5+
class Csv extends Source
66
{
77
/** @var string */
88
protected $file;

src/Sources/Json.php

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Recca0120\Twzipcode\Sources;
4+
5+
class Json extends Csv
6+
{
7+
/**
8+
* @return array{array{zipcode: string, county: string, district: string, text: string}} $rows
9+
*/
10+
protected function rows()
11+
{
12+
return array_map(static function ($data) {
13+
return [
14+
'zipcode' => $data['郵遞區號'],
15+
'county' => $data['縣市名稱'],
16+
'district' => $data['鄉鎮市區'],
17+
'rule' => implode(',', $data),
18+
];
19+
}, json_decode($this->contents(), true));
20+
}
21+
}

src/Sources/Source.php

+9-4
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,15 @@ protected function rows()
3333
return ! empty(trim($line));
3434
});
3535

36-
return array_map(static function ($line) {
37-
$data = explode(',', $line);
36+
return array_map(static function ($rule) {
37+
$data = explode(',', $rule);
3838

39-
return ['zipcode' => $data[0], 'county' => $data[1], 'district' => $data[2], 'text' => $line];
39+
return [
40+
'zipcode' => $data[0],
41+
'county' => $data[1],
42+
'district' => $data[2],
43+
'rule' => $rule,
44+
];
4045
}, $lines);
4146
}
4247

@@ -51,7 +56,7 @@ protected static function prepare($rows)
5156
? self::$tricks[$row['county'].$row['district']]
5257
: substr($row['zipcode'], 0, 3);
5358

54-
$results[$row['county']][$row['district']][$zip3][] = $row['text'];
59+
$results[$row['county']][$row['district']][$zip3][] = $row['rule'];
5560

5661
return $results;
5762
}, []);

src/Tricky.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class Tricky
66
{
77
/** @var Tricky */
88
private static $instance;
9+
910
private static $cached = [];
1011

1112
/*
@@ -87,7 +88,7 @@ public function flip($token)
8788
public static function instance()
8889
{
8990
if (! self::$instance) {
90-
self::$instance = new self();
91+
self::$instance = new self;
9192
self::$instance->init();
9293
}
9394

src/Zipcode.php

+2-4
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ class Zipcode
1616

1717
/**
1818
* @param string|Address $address
19-
* @param ?Rules $rules
2019
*/
21-
public function __construct($address, Rules $rules = null)
20+
public function __construct($address, ?Rules $rules = null)
2221
{
2322
$rules = $rules ?: new Rules;
2423
$address = new Address($address);
@@ -44,10 +43,9 @@ public function __construct($address, Rules $rules = null)
4443

4544
/**
4645
* @param string|Address $address
47-
* @param ?Rules $rules
4846
* @return static
4947
*/
50-
public static function parse($address, Rules $rules = null)
48+
public static function parse($address, ?Rules $rules = null)
5149
{
5250
return new static($address, $rules);
5351
}

tests/Sources/CsvTest.php

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace Recca0120\Twzipcode\Tests\Sources;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Recca0120\Twzipcode\Sources\Csv;
7+
8+
class CsvTest extends TestCase
9+
{
10+
public function test_csv_contents()
11+
{
12+
$source = new StubCsv('test.csv');
13+
$source->setContents('10058,臺北市,中正區,八德路1段,全
14+
10079,臺北市,中正區,三元街,單全
15+
');
16+
17+
$source->each(function ($zipcode, $county, $district, $rules) {
18+
self::assertEquals(100, $zipcode);
19+
self::assertEquals('臺北市', $county);
20+
self::assertEquals('中正區', $district);
21+
self::assertEquals([
22+
'10058,臺北市,中正區,八德路1段,全',
23+
'10079,臺北市,中正區,三元街,單全',
24+
], $rules);
25+
});
26+
}
27+
}
28+
29+
class StubCsv extends Csv
30+
{
31+
private $contents = '';
32+
33+
public function setContents($contents)
34+
{
35+
$this->contents = $contents;
36+
}
37+
38+
public function contents()
39+
{
40+
return $this->contents;
41+
}
42+
}

tests/Sources/JsonTest.php

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace Recca0120\Twzipcode\Tests\Sources;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Recca0120\Twzipcode\Sources\Json;
7+
8+
class JsonTest extends TestCase
9+
{
10+
public function test_csv_contents()
11+
{
12+
$source = new StubJson('test.json');
13+
$source->setContents('[{"郵遞區號":"10058","縣市名稱":"臺北市","鄉鎮市區":"中正區","原始路名":"八德路1段","投遞範圍":"全"},{"郵遞區號":"10079","縣市名稱":"臺北市","鄉鎮市區":"中正區","原始路名":"三元街","投遞範圍":"單全"}]');
14+
15+
$source->each(function ($zipcode, $county, $district, $rules) {
16+
self::assertEquals(100, $zipcode);
17+
self::assertEquals('臺北市', $county);
18+
self::assertEquals('中正區', $district);
19+
self::assertEquals([
20+
'10058,臺北市,中正區,八德路1段,全',
21+
'10079,臺北市,中正區,三元街,單全',
22+
], $rules);
23+
});
24+
}
25+
}
26+
27+
class StubJson extends Json
28+
{
29+
private $contents = '';
30+
31+
public function setContents($contents)
32+
{
33+
$this->contents = $contents;
34+
}
35+
36+
public function contents()
37+
{
38+
return $this->contents;
39+
}
40+
}

tests/Storages/FileTest.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use org\bovigo\vfs\vfsStream;
88
use PHPUnit\Framework\TestCase;
99
use Recca0120\Twzipcode\Address;
10-
use Recca0120\Twzipcode\Sources\CSV;
10+
use Recca0120\Twzipcode\Sources\Json;
1111
use Recca0120\Twzipcode\Sources\Text;
1212
use Recca0120\Twzipcode\Storages\File as Storage;
1313

@@ -125,7 +125,7 @@ public function testLoadResources()
125125
Storage::$cached = ['zip3' => null, 'zip5' => null];
126126
$root = vfsStream::setup();
127127
$storage = new Storage($root->url());
128-
$storage->flush()->load(new CSV(__DIR__.'/../../resources/Zip32_utf8_10501_1.zip'));
128+
$storage->flush()->load(new Json(__DIR__.'/../../resources/Zip32_11208.zip'));
129129

130130
$address = m::mock(Address::class);
131131

0 commit comments

Comments
 (0)