File::__construct()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 2
eloc 2
nc 2
nop 1
crap 2
1
<?php
2
3
namespace Recca0120\Twzipcode\Storages;
4
5
use ZipArchive;
6
use Recca0120\Lodash\JArray;
7
use Recca0120\Twzipcode\Rule;
8
use Recca0120\Twzipcode\Address;
9
use Recca0120\Twzipcode\Contracts\Storage;
10
11
class File implements Storage
12
{
13
    /**
14
     * $path.
15
     *
16
     * @var string
17
     */
18
    public $path;
19
20
    /**
21
     * $suffix.
22
     *
23
     * @var string
24
     */
25
    public $suffix = '.rules';
26
27
    /**
28
     * cached.
29
     *
30
     * @var array
31
     */
32
    public static $cached = [
33
        'zip3' => null,
34
        'zip5' => null,
35
    ];
36
37
    /**
38
     * __construct.
39
     *
40
     * @param string $path
41
     */
42 13
    public function __construct($path = null)
43
    {
44 13
        $this->path = ($path ?: realpath(__DIR__.'/../../resources/data')).'/';
45 13
    }
46
47
    /**
48
     * zip3.
49
     *
50
     * @param \Recca0120\Twzipcode\Address $address
51
     * @return string
52
     */
53 9
    public function zip3(Address $address)
54
    {
55 9
        $this->restore('zip3');
56 9
        $flat = $address->flat(2);
57
58 9
        return isset(self::$cached['zip3'][$flat]) === true ? self::$cached['zip3'][$flat] : null;
59
    }
60
61
    /**
62
     * rules.
63
     *
64
     * @param string $zip3
65
     * @return \Recca0120\Lodash\JArray
66
     */
67 8
    public function rules($zip3)
68
    {
69 8
        $this->restore('zip5');
70
71 8
        return isset(self::$cached['zip5'][$zip3]) === true
72 8
            ? $this->decompress(self::$cached['zip5'][$zip3])
73 8
            : new JArray([]);
74
    }
75
76
    /**
77
     * load.
78
     *
79
     * @param string $source
80
     * @return $this
81
     */
82 13
    public function load($source)
83
    {
84 13
        $zip5 = new JArray;
85 13
        $zip3 = new JArray;
86
        $this->each($this->prepareSource($source), function ($zipcode, $county, $district, $rules) use ($zip5, $zip3) {
87 13
            $zip5[$zipcode] = $this->compress(
88 13
                (new JArray($rules))->map(function ($rule) {
89 13
                    return new Rule($rule);
90 13
                })
91 13
            );
92
93 13 View Code Duplication
            if (isset($zip3[$county]) === false) {
94 13
                $zip3[$county] = substr($zipcode, 0, 1);
95 13
            }
96
97 13 View Code Duplication
            if (isset($zip3[$county.$district]) === false) {
98 13
                $zip3[$county.$district] = substr($zipcode, 0, 3);
99 13
            }
100 13
        });
101
102 13
        $this->store('zip3', $zip3);
103 13
        $this->store('zip5', $zip5);
104
105 13
        return $this;
106
    }
107
108
    /**
109
     * loadFile.
110
     *
111
     * @param string $file
112
     * @return $this
113
     */
114 1
    public function loadFile($file = null)
115
    {
116 1
        $file = $file ?: $this->path.'../Zip32_utf8_10501_1.csv';
117 1
        $this->load($this->getSource($file));
118
119 1
        return $this;
120
    }
121
122
    /**
123
     * flush.
124
     *
125
     * @return $this
126
     */
127 13
    public function flush()
128
    {
129 13
        static::$cached = [
130 13
            'zip3' => null,
131 13
            'zip5' => null,
132 13
        ];
133
134 13
        return $this;
135
    }
136
137
    /**
138
     * getSource.
139
     *
140
     * @param string $file
141
     * @return string
142
     */
143 1
    protected function getSource($file)
144
    {
145 1
        $extension = pathinfo($file, PATHINFO_EXTENSION);
146
147 1
        if ($extension === 'zip') {
148 1
            $zip = new ZipArchive;
149 1
            $zip->open($file);
150 1
            $content = $zip->getFromIndex(0);
151 1
            $zip->close();
152 1
        } else {
153
            $content = file_get_contents($file);
154
        }
155
156 1
        $content = mb_convert_encoding($content, 'UTF-8', 'UCS-2LE');
157 1
        $content = preg_replace("/^\xEF\xBB\xBF/", '', $content);
158
159 1
        return $content;
160
    }
161
162
    /**
163
     * prepareSource.
164
     *
165
     * @param string $source
166
     * @return array
167
     */
168 13
    protected function prepareSource($source)
169
    {
170
        $tickies = [
171 13
            '宜蘭縣壯圍鄉' => '263',
172 13
            '新竹縣寶山鄉' => '308',
173 13
            '臺南市新市區' => '744',
174 13
        ];
175 13
        $results = [];
176 13
        $rules = preg_split('/\n|\r\n$/', $source);
177 13
        foreach ($rules as $rule) {
178 13
            if (empty(trim($rule)) === false) {
179 13
                list($zipcode, $county, $district) = explode(',', $rule);
180 13
                $zip3 = isset($tickies[$county.$district]) === true
181 13
                    ? $tickies[$county.$district]
182 13
                    : substr($zipcode, 0, 3);
183 13
                $results[$county][$district][$zip3][] = $rule;
184 13
            }
185 13
        }
186
187 13
        return $results;
188
    }
189
190
    /**
191
     * each.
192
     *
193
     * @param array $rules
194
     * @param \Closure $callback
195
     */
196 13
    protected function each($rules, $callback)
197
    {
198 13
        foreach ($rules as $county => $temp) {
199 13
            foreach ($temp as $district => $temp2) {
200 13
                foreach ($temp2 as $zipcode => $rules) {
201 13
                    $callback($zipcode, $county, $district, $rules);
202 13
                }
203 13
            }
204 13
        }
205 13
    }
206
207
    /**
208
     * compress.
209
     *
210
     * @param \Recca0120\Lodash\JArray $plainText
211
     * @return string
212
     */
213 13
    protected function compress($plainText)
214
    {
215 13
        return gzcompress(serialize($plainText));
216
    }
217
218
    /**
219
     * decompress.
220
     *
221
     * @param string $compressed
222
     * @return mixed
223
     */
224 10
    protected function decompress($compressed)
225
    {
226 10
        return unserialize(gzuncompress($compressed));
227
    }
228
229
    /**
230
     * store.
231
     *
232
     * @param string $filename
233
     * @param \Recca0120\Lodash\JArray $data
234
     * @return $this
235
     */
236 13
    protected function store($filename, $data)
237
    {
238 13
        file_put_contents(
239 13
            $this->path.$filename.$this->suffix,
240 13
            $this->compress($data)
241 13
        );
242
243 13
        return $this;
244
    }
245
246
    /**
247
     * restore.
248
     *
249
     * @param string $filename
250
     * @return mixed
251
     */
252 10
    protected function restore($filename)
253
    {
254 10
        if (file_exists($this->path.$filename.$this->suffix) === false) {
255
            return false;
256
        }
257
258 10
        if (is_null(self::$cached[$filename]) === false) {
259 5
            return self::$cached[$filename];
260
        }
261
262 10
        return self::$cached[$filename] = $this->decompress(
263 10
            file_get_contents($this->path.$filename.$this->suffix)
264 10
        );
265
    }
266
}
267