Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
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) |
|
46 | |||
47 | /** |
||
48 | * zip3. |
||
49 | * |
||
50 | * @param \Recca0120\Twzipcode\Address $address |
||
51 | * @return string |
||
52 | */ |
||
53 | 9 | public function zip3(Address $address) |
|
60 | |||
61 | /** |
||
62 | * rules. |
||
63 | * |
||
64 | * @param string $zip3 |
||
65 | * @return \Recca0120\Lodash\JArray |
||
66 | */ |
||
67 | 8 | public function rules($zip3) |
|
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 | ); |
||
92 | |||
93 | 13 | View Code Duplication | if (isset($zip3[$county]) === false) { |
94 | 13 | $zip3[$county] = substr($zipcode, 0, 1); |
|
95 | } |
||
96 | |||
97 | 13 | View Code Duplication | if (isset($zip3[$county.$district]) === false) { |
98 | 13 | $zip3[$county.$district] = substr($zipcode, 0, 3); |
|
99 | } |
||
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) |
|
121 | |||
122 | /** |
||
123 | * flush. |
||
124 | * |
||
125 | * @return $this |
||
126 | */ |
||
127 | 13 | public function flush() |
|
128 | { |
||
129 | 13 | static::$cached = [ |
|
130 | 13 | 'zip3' => null, |
|
131 | 'zip5' => null, |
||
132 | ]; |
||
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 | } 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 | '新竹縣寶山鄉' => '308', |
||
173 | '臺南市新市區' => '744', |
||
174 | ]; |
||
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 | 5 | ? $tickies[$county.$district] |
|
182 | 13 | : substr($zipcode, 0, 3); |
|
183 | 13 | $results[$county][$district][$zip3][] = $rule; |
|
184 | } |
||
185 | } |
||
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 | } |
||
203 | } |
||
204 | } |
||
205 | 13 | } |
|
206 | |||
207 | /** |
||
208 | * compress. |
||
209 | * |
||
210 | * @param \Recca0120\Lodash\JArray $plainText |
||
211 | * @return string |
||
212 | */ |
||
213 | 13 | protected function compress($plainText) |
|
217 | |||
218 | /** |
||
219 | * decompress. |
||
220 | * |
||
221 | * @param string $compressed |
||
222 | * @return mixed |
||
223 | */ |
||
224 | 10 | protected function decompress($compressed) |
|
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) |
|
245 | |||
246 | /** |
||
247 | * restore. |
||
248 | * |
||
249 | * @param string $filename |
||
250 | * @return mixed |
||
251 | */ |
||
252 | 10 | protected function restore($filename) |
|
266 | } |
||
267 |