Picture   A
last analyzed

Complexity

Total Complexity 33

Size/Duplication

Total Lines 285
Duplicated Lines 3.16 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
wmc 33
c 0
b 0
f 0
lcom 1
cbo 0
dl 9
loc 285
rs 9.3999

16 Methods

Rating   Name   Duplication   Size   Complexity  
A from() 3 15 3
A limit() 0 10 2
A numericPad() 0 6 1
A numericTrim() 0 4 1
B parse() 0 27 5
A stringPad() 0 4 1
A stringTrim() 0 4 1
A to() 3 16 3
A fromTypeDate() 0 4 1
A fromTypeMoney() 0 8 1
A toAutoDate() 0 4 1
A toDefault() 0 14 4
A toDefaultAuto() 3 10 2
A toTypeDate() 0 14 4
A toTypeMoney() 0 6 1
A transliterate() 0 5 2

How to fix   Duplicated Code   

Duplicated Code

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
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)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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