1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* ImageWrapper.php |
4
|
|
|
* @author Revin Roman http://phptime.ru |
5
|
|
|
*/ |
6
|
|
|
|
7
|
|
|
namespace rmrevin\yii\module\File; |
8
|
|
|
|
9
|
|
|
use Imagine\Image\ImageInterface; |
10
|
|
|
use Imagine\Image\ManipulatorInterface; |
11
|
|
|
use rmrevin\yii\module\File\component\Image; |
12
|
|
|
use rmrevin\yii\module\File\models\File; |
13
|
|
|
use yii\helpers\FileHelper; |
14
|
|
|
use yii\helpers\Json; |
15
|
|
|
use yii\helpers\StringHelper; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Class ImageWrapper |
19
|
|
|
* @package rmrevin\yii\module\File |
20
|
|
|
*/ |
21
|
|
|
class ImageWrapper extends \yii\base\Object |
22
|
|
|
{ |
23
|
|
|
|
24
|
|
|
/** @var \rmrevin\yii\module\File\models\File */ |
25
|
|
|
public $File = null; |
26
|
|
|
|
27
|
|
|
/** @var array */ |
28
|
|
|
public $result = [null, null]; |
29
|
|
|
|
30
|
|
|
/** @var array */ |
31
|
|
|
private $mark = []; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @param \rmrevin\yii\module\File\models\File $File |
35
|
|
|
* @return self |
36
|
|
|
*/ |
37
|
4 |
|
public static function load(File $File) |
38
|
|
|
{ |
39
|
4 |
|
return new self(['File' => $File]); |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* @return string |
44
|
|
|
*/ |
45
|
1 |
|
public function __toString() |
46
|
|
|
{ |
47
|
1 |
|
return (string)$this->result[1]; |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @param callable $handler |
52
|
|
|
*/ |
53
|
1 |
|
public function save($handler) |
54
|
|
|
{ |
55
|
1 |
|
$mark = $this->calculateMark(); |
56
|
|
|
|
57
|
1 |
|
$this->result = $this->getMarkedFilePath($mark); |
58
|
|
|
|
59
|
1 |
|
if (!file_exists($this->result[0])) { |
60
|
1 |
|
\Yii::trace('create new file cache:' . $this->File->id, __METHOD__); |
61
|
1 |
|
$this->createMarkedFile($handler(), $mark); |
62
|
1 |
|
} else { |
63
|
1 |
|
\Yii::trace('file already cached:' . $this->File->id . ' (' . Json::encode($this->mark) . ')', __METHOD__); |
64
|
|
|
} |
65
|
|
|
|
66
|
1 |
|
\Yii::endProfile('manipulating with file `' . $this->File->id . '`', 'services\File\models\File'); |
67
|
1 |
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* @param integer $width |
71
|
|
|
* @param integer $height |
72
|
|
|
* @param string $filter |
73
|
|
|
* @return self |
74
|
|
|
*/ |
75
|
1 |
View Code Duplication |
public function resize($width, $height, $filter = ImageInterface::FILTER_UNDEFINED) |
|
|
|
|
76
|
|
|
{ |
77
|
1 |
|
\Yii::trace('resize file', __METHOD__); |
78
|
|
|
|
79
|
1 |
|
$this->mark(__METHOD__, func_get_args()); |
80
|
|
|
$this->save(function () use ($width, $height, $filter) { |
81
|
1 |
|
return Image::resize($this->File->getAbsolutePath(), $width, $height, $filter); |
82
|
1 |
|
}); |
83
|
|
|
|
84
|
1 |
|
return $this; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* @param integer $width |
89
|
|
|
* @param string $filter |
90
|
|
|
* @return self |
91
|
|
|
*/ |
92
|
1 |
View Code Duplication |
public function resizeByWidth($width, $filter = ImageInterface::FILTER_UNDEFINED) |
|
|
|
|
93
|
|
|
{ |
94
|
1 |
|
\Yii::trace('resizeByWidth file', __METHOD__); |
95
|
|
|
|
96
|
1 |
|
$this->mark(__METHOD__, func_get_args()); |
97
|
|
|
$this->save(function () use ($width, $filter) { |
98
|
1 |
|
return Image::resizeByWidth($this->File->getAbsolutePath(), $width, $filter); |
99
|
1 |
|
}); |
100
|
|
|
|
101
|
1 |
|
return $this; |
102
|
|
|
|
103
|
1 |
|
} |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* @param integer $height |
107
|
|
|
* @param string $filter |
108
|
|
|
* @return self |
109
|
|
|
*/ |
110
|
1 |
View Code Duplication |
public function resizeByHeight($height, $filter = ImageInterface::FILTER_UNDEFINED) |
|
|
|
|
111
|
|
|
{ |
112
|
1 |
|
\Yii::trace('resizeByHeight file', __METHOD__); |
113
|
|
|
|
114
|
1 |
|
$this->mark(__METHOD__, func_get_args()); |
115
|
|
|
$this->save(function () use ($height, $filter) { |
116
|
1 |
|
return Image::resizeByHeight($this->File->getAbsolutePath(), $height, $filter); |
117
|
1 |
|
}); |
118
|
|
|
|
119
|
1 |
|
return $this; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* @param integer $width |
124
|
|
|
* @param integer $height |
125
|
|
|
* @param array $start |
126
|
|
|
* @return self |
127
|
|
|
*/ |
128
|
1 |
View Code Duplication |
public function crop($width, $height, array $start = [0, 0]) |
|
|
|
|
129
|
|
|
{ |
130
|
1 |
|
\Yii::trace('crop file', __METHOD__); |
131
|
|
|
|
132
|
1 |
|
$this->mark(__METHOD__, func_get_args()); |
133
|
|
|
$this->save(function () use ($width, $height, $start) { |
134
|
1 |
|
return Image::crop($this->File->getAbsolutePath(), $width, $height, $start); |
135
|
1 |
|
}); |
136
|
|
|
|
137
|
1 |
|
return $this; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* @param integer $width |
142
|
|
|
* @param integer $height |
143
|
|
|
* @param string $mode |
144
|
|
|
* @return self |
145
|
|
|
*/ |
146
|
1 |
View Code Duplication |
public function thumbnail($width, $height, $mode = ManipulatorInterface::THUMBNAIL_OUTBOUND) |
|
|
|
|
147
|
|
|
{ |
148
|
1 |
|
\Yii::trace('thumbnail file', __METHOD__); |
149
|
|
|
|
150
|
1 |
|
$this->mark(__METHOD__, func_get_args()); |
151
|
|
|
$this->save(function () use ($width, $height, $mode) { |
152
|
1 |
|
return Image::thumbnail($this->File->getAbsolutePath(), $width, $height, $mode); |
153
|
1 |
|
}); |
154
|
|
|
|
155
|
1 |
|
return $this; |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* @param string $watermarkFilename |
160
|
|
|
* @param array $start |
161
|
|
|
* @return self |
162
|
|
|
*/ |
163
|
1 |
|
public function watermark($watermarkFilename, array $start = [0, 0]) |
164
|
|
|
{ |
165
|
1 |
|
\Yii::trace('watermark file', __METHOD__); |
166
|
|
|
|
167
|
1 |
|
$this->mark(__METHOD__, func_get_args()); |
168
|
|
|
$this->save(function () use ($watermarkFilename, $start) { |
169
|
1 |
|
return Image::watermark($this->File->getAbsolutePath(), $watermarkFilename, $start); |
170
|
1 |
|
}); |
171
|
|
|
|
172
|
1 |
|
return $this; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* @param string $text |
177
|
|
|
* @param string $fontFile |
178
|
|
|
* @param array $start |
179
|
|
|
* @param array $fontOptions |
180
|
|
|
* @return self |
181
|
|
|
*/ |
182
|
1 |
View Code Duplication |
public function text($text, $fontFile, array $start = [0, 0], array $fontOptions = []) |
|
|
|
|
183
|
|
|
{ |
184
|
1 |
|
\Yii::trace('text file', __METHOD__); |
185
|
|
|
|
186
|
1 |
|
$this->mark(__METHOD__, func_get_args()); |
187
|
|
|
$this->save(function () use ($text, $fontFile, $start, $fontOptions) { |
188
|
1 |
|
return Image::text($this->File->getAbsolutePath(), $text, $fontFile, $start, $fontOptions); |
189
|
1 |
|
}); |
190
|
|
|
|
191
|
1 |
|
return $this; |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* @param int $margin |
196
|
|
|
* @param string $color |
197
|
|
|
* @param int $alpha |
198
|
|
|
* @return self |
199
|
|
|
*/ |
200
|
1 |
|
public function frame($margin = 20, $color = '666', $alpha = 100) |
201
|
|
|
{ |
202
|
1 |
|
\Yii::trace('frame file', __METHOD__); |
203
|
|
|
|
204
|
1 |
|
$this->mark(__METHOD__, func_get_args()); |
205
|
1 |
|
$this->save(function () use ($margin, $color, $alpha) { |
206
|
1 |
|
return Image::frame($this->File->getAbsolutePath(), $margin, $color, $alpha); |
207
|
1 |
|
}); |
208
|
|
|
|
209
|
1 |
|
return $this; |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* @return string[] |
214
|
|
|
*/ |
215
|
1 |
|
private function getPath() |
216
|
|
|
{ |
217
|
1 |
|
$filename = basename($this->File->name); |
218
|
1 |
|
$p1 = StringHelper::byteSubstr($filename, 0, 2); |
219
|
1 |
|
$p2 = StringHelper::byteSubstr($filename, 2, 2); |
220
|
1 |
|
$p = DIRECTORY_SEPARATOR . $p1 . DIRECTORY_SEPARATOR . $p2; |
221
|
|
|
|
222
|
|
|
return [ |
223
|
1 |
|
Module::module()->storage_path . $p, |
224
|
1 |
|
Module::module()->storage_web_path . $p |
225
|
1 |
|
]; |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* @param string $mark |
230
|
|
|
* @return string[] |
231
|
|
|
*/ |
232
|
1 |
|
private function getMarkedFilePath($mark) |
233
|
|
|
{ |
234
|
1 |
|
\Yii::trace('calculate mark file path', __METHOD__); |
235
|
|
|
|
236
|
1 |
|
$ext = pathinfo($this->File->name, PATHINFO_EXTENSION); |
237
|
|
|
|
238
|
1 |
|
list($path, $web_path) = $this->getPath(); |
239
|
1 |
|
$mark_file_path = $path . DIRECTORY_SEPARATOR . $mark . '.' . $ext; |
240
|
1 |
|
$mark_file_web_path = $web_path . '/' . $mark . '.' . $ext; |
241
|
|
|
|
242
|
1 |
|
return [$mark_file_path, $mark_file_web_path]; |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* @param \Imagine\Image\ImageInterface $Image |
247
|
|
|
* @param string $mark |
248
|
|
|
*/ |
249
|
1 |
|
private function createMarkedFile(ImageInterface $Image, $mark) |
250
|
|
|
{ |
251
|
1 |
|
\Yii::beginProfile('create cache file:' . $this->File->id, __METHOD__); |
252
|
|
|
|
253
|
1 |
|
list($mark_file_path, $mark_file_web_path) = $this->getMarkedFilePath($mark); |
|
|
|
|
254
|
|
|
|
255
|
1 |
|
$mark_dir_path = dirname($mark_file_path); |
256
|
1 |
|
if (!file_exists($mark_dir_path) || !is_dir($mark_dir_path)) { |
257
|
1 |
|
FileHelper::createDirectory($mark_dir_path); |
258
|
1 |
|
} |
259
|
|
|
|
260
|
1 |
|
$Image->save($mark_file_path, ['quality' => 90]); |
261
|
1 |
|
@chmod($mark_file_path, 0664); |
|
|
|
|
262
|
|
|
|
263
|
1 |
|
\Yii::endProfile('create cache file:' . $this->File->id, __METHOD__); |
264
|
1 |
|
} |
265
|
|
|
|
266
|
|
|
|
267
|
|
|
/** |
268
|
|
|
* @param string $method |
269
|
|
|
* @param array $data |
270
|
|
|
*/ |
271
|
1 |
|
private function mark($method, array $data) |
|
|
|
|
272
|
|
|
{ |
273
|
1 |
|
$this->mark = func_get_args(); |
274
|
1 |
|
} |
275
|
|
|
|
276
|
|
|
/** |
277
|
|
|
* @return string |
278
|
|
|
*/ |
279
|
1 |
|
private function calculateMark() |
280
|
|
|
{ |
281
|
1 |
|
return sha1(Json::encode($this->mark)); |
282
|
|
|
} |
283
|
|
|
} |
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.