1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace SmartCNAB\Support; |
4
|
|
|
|
5
|
|
|
use DateTime; |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* Picture class. |
9
|
|
|
* A picture defines a format to convert from and to it. |
10
|
|
|
*/ |
11
|
|
|
class Picture |
12
|
|
|
{ |
13
|
|
|
/** |
14
|
|
|
* Constants for regex patterns of pictures contents. |
15
|
|
|
*/ |
16
|
|
|
const REGEX_INTEGER = '/^9\((\d+?)\)$/'; |
17
|
|
|
const REGEX_MONEY = '/^9\((\d+?)\)V9\((\d+?)\)$/'; |
18
|
|
|
const REGEX_STRING = '/^X\((\d+?)\)$/'; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* Format a value from a picture. |
22
|
|
|
* |
23
|
|
|
* @param string $picture |
24
|
|
|
* @param mixed $value |
25
|
|
|
* @param array $meta |
26
|
|
|
* @return mixed |
27
|
|
|
*/ |
28
|
|
|
public function from($picture, $value, array $meta = []) |
29
|
|
|
{ |
30
|
|
|
$parsed = $this->parse($picture, $meta); |
31
|
|
|
$method = 'fromType' . ucfirst($parsed['info-type']); |
32
|
|
|
$start = empty($parsed['pos']) ? 0 : $parsed['pos'][0] - 1; |
33
|
|
|
$value = substr($value, $start, $parsed['size']); |
34
|
|
|
|
35
|
|
View Code Duplication |
if (method_exists($this, $method)) { |
36
|
|
|
return call_user_func_array([$this, $method], [$value, $parsed]); |
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
$method = $parsed['data-type'] . 'Trim'; |
40
|
|
|
|
41
|
|
|
return call_user_func_array([$this, $method], [$value, $parsed['size']]); |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Execute a content limit or pad if is shorten then size. |
46
|
|
|
* |
47
|
|
|
* @param mixed $value |
48
|
|
|
* @param integer $size |
49
|
|
|
* @param array $meta |
50
|
|
|
* @return string |
51
|
|
|
*/ |
52
|
|
|
public function limit($value, $size, array $meta = []) |
53
|
|
|
{ |
54
|
|
|
if (strlen($value) > $size) { |
55
|
|
|
return mb_substr($value, 0, $size); |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
$method = $meta['data-type'] . 'Pad'; |
59
|
|
|
|
60
|
|
|
return call_user_func_array([$this, $method], [$value, $meta['size']]); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Execute a numeric pad (left with 0). |
65
|
|
|
* |
66
|
|
|
* @param mixed $number |
67
|
|
|
* @param integer $size |
68
|
|
|
* @return string |
69
|
|
|
*/ |
70
|
|
|
public function numericPad($number, $size) |
71
|
|
|
{ |
72
|
|
|
$number = str_replace(['.', ','], '', $number); |
73
|
|
|
|
74
|
|
|
return str_pad($number, $size, 0, STR_PAD_LEFT); |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Execute a numeric pad (left with no 0). |
79
|
|
|
* |
80
|
|
|
* @param mixed $number |
81
|
|
|
* @return integer |
82
|
|
|
*/ |
83
|
|
|
public function numericTrim($number) |
84
|
|
|
{ |
85
|
|
|
return (int) $number; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Parses a received picture to tokens. |
90
|
|
|
* |
91
|
|
|
* @param string $picture |
92
|
|
|
* @param array $meta |
93
|
|
|
* @return array |
94
|
|
|
*/ |
95
|
|
|
public function parse($picture, array $meta = []) |
96
|
|
|
{ |
97
|
|
|
$parsed = array_merge([ |
98
|
|
|
'data-type' => 'numeric', |
99
|
|
|
'info-type' => empty($meta['type'])? 'generic' : $meta['type'], |
100
|
|
|
'strict' => true, |
101
|
|
|
'translit' => true, |
102
|
|
|
], $meta); |
103
|
|
|
|
104
|
|
|
if (preg_match(self::REGEX_INTEGER, $picture, $match)) { |
105
|
|
|
$parsed['size'] = (int) $match[1]; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
if (preg_match(self::REGEX_MONEY, $picture, $match)) { |
109
|
|
|
$parsed['info-type'] = 'money'; |
110
|
|
|
$parsed['size'] = (int) $match[1] + (int) $match[2]; |
111
|
|
|
$parsed['first'] = (int) $match[1]; |
112
|
|
|
$parsed['last'] = (int) $match[2]; |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
if (preg_match(self::REGEX_STRING, $picture, $match)) { |
116
|
|
|
$parsed['data-type'] = 'string'; |
117
|
|
|
$parsed['size'] = (int) $match[1]; |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
return $parsed; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Execute a string pad (right with spaces). |
125
|
|
|
* |
126
|
|
|
* @param mixed $string |
127
|
|
|
* @param integer $size |
128
|
|
|
* @return string |
129
|
|
|
*/ |
130
|
|
|
public function stringPad($string, $size) |
131
|
|
|
{ |
132
|
|
|
return str_pad($string, $size, ' '); |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Execute a string trim (remove right with spaces). |
137
|
|
|
* |
138
|
|
|
* @param mixed $string |
139
|
|
|
* @return string |
140
|
|
|
*/ |
141
|
|
|
public function stringTrim($string) |
142
|
|
|
{ |
143
|
|
|
return trim($string); |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Format a value to picture. |
148
|
|
|
* |
149
|
|
|
* @param string $picture |
150
|
|
|
* @param mixed $value |
151
|
|
|
* @param array $meta |
152
|
|
|
* @return string |
153
|
|
|
*/ |
154
|
|
|
public function to($picture, $value, array $meta = []) |
155
|
|
|
{ |
156
|
|
|
$parsed = $this->parse($picture, $meta); |
157
|
|
|
$method = 'toType' . ucfirst($parsed['info-type']); |
158
|
|
|
$value = $this->toDefault($value, $parsed); |
159
|
|
|
|
160
|
|
|
if ($parsed['translit']) { |
161
|
|
|
$value = $this->transliterate($value); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
View Code Duplication |
if (method_exists($this, $method)) { |
165
|
|
|
return call_user_func_array([$this, $method], [$value, $parsed]); |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
return $this->limit($value, $parsed['size'], $parsed); |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
/** |
172
|
|
|
* Format a value from a date. |
173
|
|
|
* |
174
|
|
|
* @param mixed $value |
175
|
|
|
* @return \DateTime|false |
176
|
|
|
*/ |
177
|
|
|
protected function fromTypeDate($value) |
178
|
|
|
{ |
179
|
|
|
return DateTime::createFromFormat('dmy', $value); |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* Format a value from a money. |
184
|
|
|
* |
185
|
|
|
* @param numeric $value |
186
|
|
|
* @param array $meta |
187
|
|
|
* @return float |
188
|
|
|
*/ |
189
|
|
|
protected function fromTypeMoney($value, array $meta = []) |
190
|
|
|
{ |
191
|
|
|
$offset = -$meta['last']; |
192
|
|
|
$value = (int) $value; |
193
|
|
|
$value = substr($value, 0, $offset) . '.' . substr($value, $offset); |
194
|
|
|
|
195
|
|
|
return floatval($value); |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* Format a value to an auto date. |
200
|
|
|
* |
201
|
|
|
* @return \DateTime |
202
|
|
|
*/ |
203
|
|
|
protected function toAutoDate() |
204
|
|
|
{ |
205
|
|
|
return new DateTime(); |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
/** |
209
|
|
|
* Format a value to a default value. |
210
|
|
|
* |
211
|
|
|
* @param mixed $value |
212
|
|
|
* @param array $meta |
213
|
|
|
* @return mixed |
214
|
|
|
*/ |
215
|
|
|
protected function toDefault($value, array $meta = []) |
216
|
|
|
{ |
217
|
|
|
if ( ! empty($value)) return $value; |
218
|
|
|
|
219
|
|
|
if ( ! empty($meta['def'])) { |
220
|
|
|
$value = $meta['def']; |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
if ($value === '@auto') { |
224
|
|
|
$value = $this->toDefaultAuto($value, $meta); |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
return $value; |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
/** |
231
|
|
|
* Format a value to an automatic default value. |
232
|
|
|
* |
233
|
|
|
* @param mixed $value |
234
|
|
|
* @param array $meta |
235
|
|
|
* @return mixed |
236
|
|
|
*/ |
237
|
|
|
protected function toDefaultAuto($value, array $meta = []) |
238
|
|
|
{ |
239
|
|
|
$method = 'toAuto' . ucfirst($meta['type']); |
240
|
|
|
|
241
|
|
View Code Duplication |
if (method_exists($this, $method)) { |
|
|
|
|
242
|
|
|
$value = call_user_func([$this, $method], $value, $meta); |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
return $value; |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
/** |
249
|
|
|
* Format a value to a date. |
250
|
|
|
* |
251
|
|
|
* @param mixed $value |
252
|
|
|
* @param array $meta |
253
|
|
|
* @return string |
254
|
|
|
*/ |
255
|
|
|
protected function toTypeDate($value, array $meta = []) |
256
|
|
|
{ |
257
|
|
|
$isDate = $value instanceOf DateTime; |
258
|
|
|
|
259
|
|
|
if ($isDate) { |
260
|
|
|
$value = $value->format('dmy'); |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
if ( ! $isDate && $meta['strict']) { |
264
|
|
|
$value = null; |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
return $this->limit($value, $meta['size'], $meta); |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* Format a value to a money. |
272
|
|
|
* |
273
|
|
|
* @param numeric $value |
274
|
|
|
* @param array $meta |
275
|
|
|
* @return string |
276
|
|
|
*/ |
277
|
|
|
protected function toTypeMoney($value, array $meta = []) |
278
|
|
|
{ |
279
|
|
|
$value = number_format(floatval($value), $meta['last']); |
280
|
|
|
|
281
|
|
|
return $this->limit($value, $meta['size'], $meta); |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
/** |
285
|
|
|
* Transliterate from UTF-8 to ASCII |
286
|
|
|
* |
287
|
|
|
* @param string $value |
288
|
|
|
* @return string |
289
|
|
|
*/ |
290
|
|
|
protected function transliterate($value) |
291
|
|
|
{ |
292
|
|
|
return ! is_string($value) ? |
293
|
|
|
$value : iconv('UTF-8', 'ASCII//TRANSLIT', $value); |
294
|
|
|
} |
295
|
|
|
} |
296
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.