ImageContentsFileBehaviorTrait   A
last analyzed

Complexity

Total Complexity 41

Size/Duplication

Total Lines 248
Duplicated Lines 10.08 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 41
lcom 1
cbo 1
dl 25
loc 248
rs 9.1199
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A imageResize() 0 14 2
B getImageInfo() 0 30 6
C imageSizeInfo() 25 52 12
C imageResizeMake() 0 78 15
B getPathInfo() 0 24 6

How to fix   Duplicated Code    Complexity   

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:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like ImageContentsFileBehaviorTrait often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ImageContentsFileBehaviorTrait, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace ContentsFile\Model\Behavior\Traits;
4
5
use Cake\Core\Configure;
6
7
/**
8
 * ImageContentsFileBehaviorTrait
9
 * 画像関係の処理
10
 */
11
trait ImageContentsFileBehaviorTrait
12
{
13
    private $tp;
14
15
    /**
16
     * imageResize
17
     * 画像のリサイズ処理(外からでもたたけるようにpublicにする
18
     * @author hagiwara
19
     * @param string $imagePath
20
     * @param array $baseSize
21
     * @return bool
22
     */
23
    public function imageResize(string $imagePath, array $baseSize): bool
24
    {
25
        $imageInfo = $this->getImageInfo($imagePath);
26
        $image = $imageInfo['image'];
27
        $imagetype = $imageInfo['imagetype'];
28
        if (!$image) {
29
            // 画像の読み込み失敗
30
            return false;
31
        }
32
        // // 画像の縦横サイズを取得
33
        $imageSizeInfo = $this->imageSizeInfo($image, $baseSize);
34
35
        return $this->imageResizeMake($image, $imagetype, $imagePath, $baseSize, $imageSizeInfo);
36
    }
37
38
    /**
39
     * getImageInfo
40
     * 画像情報の取得
41
     * @author hagiwara
42
     * @param string $imagePath
43
     * @return bool|array
44
     */
45
    private function getImageInfo(string $imagePath)
46
    {
47
        if (file_exists($imagePath) === false) {
48
            return false;
49
        }
50
51
        $imagetype = exif_imagetype($imagePath);
52
        if ($imagetype === false) {
53
            return false;
54
        }
55
56
        // 画像読み込み
57
        switch ($imagetype) {
58
            case IMAGETYPE_GIF:
59
                $image = ImageCreateFromGIF($imagePath);
60
                break;
61
            case IMAGETYPE_JPEG:
62
                $image = ImageCreateFromJPEG($imagePath);
63
                break;
64
            case IMAGETYPE_PNG:
65
                $image = ImageCreateFromPNG($imagePath);
66
                break;
67
            default:
68
                $image = false;
69
        }
70
        return [
71
            'image' => $image,
72
            'imagetype' => $imagetype,
73
        ];
74
    }
75
76
    /**
77
     * imageSizeInfo
78
     * 画像リサイズ情報の取得
79
     * @author hagiwara
80
     * @param resource $image
81
     * @param array $baseSize
82
     * @return array
83
     */
84
    private function imageSizeInfo($image, array $baseSize): array
85
    {
86
        // 画像の縦横サイズを取得
87
        $sizeX = ImageSX($image);
88
        $sizeY = ImageSY($image);
89
        // リサイズ後のサイズ
90
        if (!array_key_exists('height', $baseSize)) {
91
            $baseSize['height'] = 0;
92
        }
93
        if (!array_key_exists('width', $baseSize)) {
94
            $baseSize['width'] = 0;
95
        }
96
        // リサイズ種別
97
        if (!array_key_exists('type', $baseSize)) {
98
            $baseSize['type'] = 'normal';
99
        }
100
101
        if ($baseSize['type'] == 'normal_s' || $baseSize['type'] == 'scoop') {
102
            // 短い方基準もしくは、くりぬき
103 View Code Duplication
            if (empty($baseSize['width']) || !empty($baseSize['height']) && $sizeX * $baseSize['height'] < $sizeY * $baseSize['width']) {
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...
104
                // 縦基準
105
                $mag = $baseSize['width'] / $sizeX;
106
                $reSizeX = $baseSize['width'];
107
                $reSizeY = $sizeY * $mag;
108
            } else {
109
                // 横基準
110
                $mag = $baseSize['height'] / $sizeY;
111
                $reSizeY = $baseSize['height'];
112
                $reSizeX = $sizeX * $mag;
113
            }
114 View Code Duplication
        } else {
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...
115
            // 長い方基準
116
            if (empty($baseSize['width']) || !empty($baseSize['height']) && $sizeX * $baseSize['height'] < $sizeY * $baseSize['width']) {
117
                // 縦基準
118
                $mag = $baseSize['height'] / $sizeY;
119
                $reSizeY = $baseSize['height'];
120
                $reSizeX = $sizeX * $mag;
121
            } else {
122
                // 横基準
123
                $mag = $baseSize['width'] / $sizeX;
124
                $reSizeX = $baseSize['width'];
125
                $reSizeY = $sizeY * $mag;
126
            }
127
        }
128
        return [
129
            'sizeX' => $sizeX,
130
            'sizeY' => $sizeY,
131
            'reSizeX' => $reSizeX,
132
            'reSizeY' => $reSizeY,
133
            'type' => $baseSize['type'],
134
        ];
135
    }
136
137
    /**
138
     * imageResizeMake
139
     * 画像リサイズ情報の取得
140
     * @author hagiwara
141
     * @param resource $image
142
     * @param int $imagetype
143
     * @param string $imagePath
144
     * @param array $baseSize
145
     * @param array $imageSizeInfo
146
     */
147
    private function imageResizeMake($image, int $imagetype, string $imagePath, array $baseSize, array $imageSizeInfo): bool
148
    {
149
        // サイズ変更後の画像データを生成
150
        $campusX = $imageSizeInfo['reSizeX'];
151
        $campusY = $imageSizeInfo['reSizeY'];
152
        // くりぬきの場合(幅と高さが両方必要)
153
        if ($imageSizeInfo['type'] == 'scoop' && !empty($baseSize['width']) && !empty($baseSize['height'])) {
154
            $campusX = $baseSize['width'];
155
            $campusY = $baseSize['height'];
156
        }
157
        $outImage = ImageCreateTrueColor($campusX, $campusY);
158
        if (!$outImage) {
159
            // リサイズ後の画像作成失敗
160
            return false;
161
        }
162
163
        switch ($imagetype) {
164
            case IMAGETYPE_GIF:
165
                //透過GIF対策
166
                $alpha = imagecolortransparent($image);  // 元画像から透過色を取得する
167
                imagefill($outImage, 0, 0, $alpha);       // その色でキャンバスを塗りつぶす
168
                imagecolortransparent($outImage, $alpha); // 塗りつぶした色を透過色として指定する
169
                //!透過GIF対策
170
                break;
171
            case IMAGETYPE_PNG:
172
                //透過PNG対策
173
                //ブレンドモードを無効にする
174
                imagealphablending($outImage, false);
175
                //完全なアルファチャネル情報を保存するフラグをonにする
176
                imagesavealpha($outImage, true);
177
                //!透過PNG対策
178
                break;
179
            default:
180
                break;
181
        }
182
183
        $diffX = 0;
184
        $diffY = 0;
185
        // くりぬきの場合(幅と高さが両方必要)
186
        if ($imageSizeInfo['type'] == 'scoop' && !empty($baseSize['width']) && !empty($baseSize['height'])) {
187
            $diffX = ($imageSizeInfo['sizeX'] - ($baseSize['width'] * $imageSizeInfo['sizeX'] / $imageSizeInfo['reSizeX'])) / 2;
188
            $diffY = ($imageSizeInfo['sizeY'] - ($baseSize['height'] * $imageSizeInfo['sizeY'] / $imageSizeInfo['reSizeY'])) / 2;
189
        }
190
        $ret = imagecopyresampled($outImage, $image, 0, 0, $diffX, $diffY, $imageSizeInfo['reSizeX'], $imageSizeInfo['reSizeY'], $imageSizeInfo['sizeX'], $imageSizeInfo['sizeY']);
191
        if ($ret === false) {
192
            // リサイズ失敗
193
            return false;
194
        }
195
196
        ImageDestroy($image);
197
198
        // 画像保存
199
        $imagepathinfo = $this->getPathInfo($imagePath, $baseSize);
200
        //resizeファイルを格納するディレクトリを作成
201
        if (
202
            !$this->mkdir($imagepathinfo['resize_dir'], 0777, true)
0 ignored issues
show
Bug introduced by
It seems like mkdir() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
203
        ) {
204
            return false;
205
        }
206
207
        switch ($imagetype) {
208
            case IMAGETYPE_GIF:
209
                ImageGIF($outImage, $imagepathinfo['resize_filepath']);
210
                break;
211
            case IMAGETYPE_JPEG:
212
                ImageJPEG($outImage, $imagepathinfo['resize_filepath'], 100);
213
                break;
214
            case IMAGETYPE_PNG:
215
                ImagePNG($outImage, $imagepathinfo['resize_filepath']);
216
                break;
217
            default:
218
                return false;
219
        }
220
221
        ImageDestroy($outImage);
222
223
        return true;
224
    }
225
226
    /**
227
     * getPathInfo
228
     * 通常のpathinfoに加えてContentsFile独自のpathも一緒に設定する
229
     * @author hagiwara
230
     * @param string $imagePath
231
     * @param array $resize
232
     * @return array
233
     */
234
    public function getPathInfo(string $imagePath, array $resize = []): array
235
    {
236
        $pathinfo = pathinfo($imagePath);
237
        $pathinfo['resize_dir'] = $pathinfo['dirname'] . '/contents_file_resize_' . $pathinfo['filename'];
238
        //一旦ベースのパスを通しておく
239
        $pathinfo['resize_filepath'] = $imagePath;
240
        if (!empty($resize)) {
241
            if (!isset($resize['width'])) {
242
                $resize['width'] = 0;
243
            }
244
            if (!isset($resize['height'])) {
245
                $resize['height'] = 0;
246
            }
247
            if (!isset($resize['type'])) {
248
                $resize['type'] = 'normal';
249
            }
250
            $pathinfo['resize_filepath'] = $pathinfo['resize_dir'] . '/' . $resize['width'] . '_' . $resize['height'] . '_' . $resize['type'];
251
            if (Configure::read('ContentsFile.Setting.ext') === true) {
252
                $ext = (new \SplFileInfo($imagePath))->getExtension();
253
                $pathinfo['resize_filepath'] .= '.' . $ext;
254
            }
255
        }
256
        return $pathinfo;
257
    }
258
}
259