satthi /
Contents-file
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | namespace ContentsFile\Model\Entity; |
||
| 4 | |||
| 5 | use Cake\Core\Configure; |
||
| 6 | use Cake\Filesystem\File; |
||
| 7 | use Cake\Http\Exception\InternalErrorException; |
||
| 8 | use Cake\I18n\Time; |
||
| 9 | use Cake\ORM\TableRegistry; |
||
| 10 | use Cake\Utility\Security; |
||
| 11 | use ContentsFile\Aws\S3; |
||
| 12 | use Laminas\Diactoros\UploadedFile; |
||
| 13 | |||
| 14 | trait ContentsFileTrait |
||
| 15 | { |
||
| 16 | private $contentsFileSettings = []; |
||
| 17 | |||
| 18 | /** |
||
| 19 | * contentsFileSettings |
||
| 20 | * 設定値のセッティング |
||
| 21 | * |
||
| 22 | * @author hagiwara |
||
| 23 | * @return void |
||
| 24 | */ |
||
| 25 | private function contentsFileSettings(): void |
||
| 26 | { |
||
| 27 | $default = []; |
||
| 28 | //設定値はまとめる |
||
| 29 | $settings = $this->contentsFileConfig; |
||
|
0 ignored issues
–
show
|
|||
| 30 | $this->contentsFileSettings = array_merge($default, $settings); |
||
| 31 | } |
||
| 32 | |||
| 33 | /** |
||
| 34 | * getContentsFileSettings |
||
| 35 | * 設定値のセッティングの取得 |
||
| 36 | * |
||
| 37 | * @author hagiwara |
||
| 38 | * @return array |
||
| 39 | */ |
||
| 40 | public function getContentsFileSettings(): array |
||
| 41 | { |
||
| 42 | if (empty($this->contentsFileSettings)) { |
||
| 43 | $this->contentsFileSettings(); |
||
| 44 | } |
||
| 45 | return $this->contentsFileSettings; |
||
| 46 | } |
||
| 47 | |||
| 48 | /** |
||
| 49 | * getContentsFile |
||
| 50 | * ファイルのgetterのセッティング |
||
| 51 | * |
||
| 52 | * @author hagiwara |
||
| 53 | * @param string $property |
||
| 54 | * @param mixed $value |
||
| 55 | * @return mixed |
||
| 56 | */ |
||
| 57 | public function getContentsFile(string $property, $value) |
||
| 58 | { |
||
| 59 | $this->contentsFileSettings(); |
||
| 60 | if ( |
||
| 61 | //attachmentにデータが登録時のみ |
||
| 62 | !empty($this->id) && |
||
| 63 | //設定値に設定されているとき |
||
| 64 | preg_match('/^contents_file_(.*)$/', $property, $match) && |
||
| 65 | array_key_exists($match[1], $this->contentsFileSettings['fields']) |
||
| 66 | ) { |
||
| 67 | //何もセットされていないとき |
||
| 68 | if (empty($this->_fields[$property])) { |
||
| 69 | //attachmentからデータを探しに行く |
||
| 70 | $attachmentModel = TableRegistry::getTableLocator()->get('Attachments'); |
||
| 71 | $attachmentData = $attachmentModel->find('all') |
||
| 72 | ->where(['model' => $this->getSource()]) |
||
|
0 ignored issues
–
show
It seems like
getSource() 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 Adding the Loading history...
|
|||
| 73 | ->where(['model_id' => $this->id]) |
||
|
0 ignored issues
–
show
The property
id does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
Loading history...
|
|||
| 74 | ->where(['field_name' => $match[1]]) |
||
| 75 | ->first() |
||
| 76 | ; |
||
| 77 | if (!empty($attachmentData)) { |
||
| 78 | $value = [ |
||
| 79 | 'model' => $attachmentData->model, |
||
| 80 | 'model_id' => $attachmentData->model_id, |
||
| 81 | 'field_name' => $attachmentData->field_name, |
||
| 82 | 'file_name' => $attachmentData->file_name, |
||
| 83 | 'file_content_type' => $attachmentData->file_content_type, |
||
| 84 | 'file_size' => $attachmentData->file_size, |
||
| 85 | 'file_random_path' => $attachmentData->file_random_path, |
||
| 86 | ]; |
||
| 87 | } |
||
| 88 | } else { |
||
| 89 | //それ以外はpropertiesの値を取得(setterで値を編集している場合はそれを反映するために必要) |
||
| 90 | $value = $this->_fields[$property]; |
||
|
0 ignored issues
–
show
The property
_fields does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
Loading history...
|
|||
| 91 | } |
||
| 92 | } |
||
| 93 | return $value; |
||
| 94 | } |
||
| 95 | |||
| 96 | /** |
||
| 97 | * setContentsFile |
||
| 98 | * ファイルのsetterのセッティング |
||
| 99 | * |
||
| 100 | * @author hagiwara |
||
| 101 | */ |
||
| 102 | public function setContentsFile() |
||
| 103 | { |
||
| 104 | $this->contentsFileSettings(); |
||
| 105 | foreach ($this->contentsFileSettings['fields'] as $field => $fieldSetting) { |
||
| 106 | // 通常のパターン |
||
| 107 | if (!array_key_exists('type', $fieldSetting) || $fieldSetting['type'] == 'normal') { |
||
| 108 | $this->normalSetContentsFile($field, $fieldSetting); |
||
| 109 | } else { |
||
| 110 | $this->ddSetContentsFile($field, $fieldSetting); |
||
| 111 | } |
||
| 112 | } |
||
| 113 | return $this; |
||
| 114 | } |
||
| 115 | |||
| 116 | /** |
||
| 117 | * normalSetContentsFile |
||
| 118 | * ファイルのsetterのセッティング |
||
| 119 | * |
||
| 120 | * @param string $field |
||
| 121 | * @param array $fieldSetting |
||
| 122 | * @return void |
||
| 123 | * @author hagiwara |
||
| 124 | */ |
||
| 125 | private function normalSetContentsFile(string $field, array $fieldSetting): void |
||
| 126 | { |
||
| 127 | $fileInfo = $this->{$field}; |
||
| 128 | if ( |
||
| 129 | //ファイルの情報がある |
||
| 130 | is_object($fileInfo) && |
||
| 131 | //空アップロード時は通さない(もともとのデータを活かす) |
||
| 132 | $fileInfo->getError() != UPLOAD_ERR_NO_FILE |
||
| 133 | ) { |
||
| 134 | $fileSet = [ |
||
| 135 | 'model' => $this->getSource(), |
||
|
0 ignored issues
–
show
It seems like
getSource() 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 Adding the Loading history...
|
|||
| 136 | 'model_id' => $this->id, |
||
| 137 | 'field_name' => $field, |
||
| 138 | 'file_name' => $fileInfo->getClientFilename(), |
||
| 139 | 'file_content_type' => Configure::read('ContentsFile.Setting.type'), |
||
| 140 | 'file_size' => $fileInfo->getSize(), |
||
| 141 | 'file_error' => $fileInfo->getError(), |
||
| 142 | ]; |
||
| 143 | |||
| 144 | //$fileInfoにtmp_nameがいるときはtmpディレクトリへのファイルのコピーを行う |
||
| 145 | // if (!empty($fileInfo['tmp_name'])) { |
||
| 146 | $tmpFileName = Security::hash(rand() . Time::now()->i18nFormat('YYYY/MM/dd HH:ii:ss') . $fileInfo->getClientFilename()); |
||
| 147 | |||
| 148 | if ($this->getExt($fileInfo->getClientFilename()) !== null) { |
||
| 149 | $tmpFileName .= '.' . $this->getExt($fileInfo->getClientFilename()); |
||
| 150 | } |
||
| 151 | |||
| 152 | // tmpディレクトリへのアップロードのエラー(パーミッションなど) |
||
| 153 | if (!$this->tmpUpload($fileInfo, $fieldSetting, $tmpFileName)) { |
||
| 154 | throw new InternalErrorException('tmp upload error'); |
||
| 155 | } |
||
| 156 | $fileSet['tmp_file_name'] = $tmpFileName; |
||
| 157 | // } |
||
| 158 | //これを残して次に引き渡したくないので |
||
| 159 | unset($this->{$field}); |
||
| 160 | |||
| 161 | $nowNew = $this->isNew(); |
||
|
0 ignored issues
–
show
It seems like
isNew() 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 Adding the Loading history...
$nowNew is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the Loading history...
|
|||
| 162 | |||
| 163 | $this->set('contents_file_' . $field, $fileSet); |
||
|
0 ignored issues
–
show
It seems like
set() 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 Adding the Loading history...
|
|||
| 164 | $this->set('contents_file_' . $field . '_filename', $fileInfo->getClientFilename()); |
||
|
0 ignored issues
–
show
It seems like
set() 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 Adding the Loading history...
|
|||
| 165 | } |
||
| 166 | } |
||
| 167 | |||
| 168 | /** |
||
| 169 | * ddSetContentsFile |
||
| 170 | * ファイルのsetterのセッティング |
||
| 171 | * |
||
| 172 | * @param string $field |
||
| 173 | * @param array $fieldSetting |
||
| 174 | * @return void |
||
| 175 | * @author hagiwara |
||
| 176 | */ |
||
| 177 | private function ddSetContentsFile(string $field, array $fieldSetting): void |
||
| 178 | { |
||
| 179 | |||
| 180 | $fileInfo = $this->{$field}; |
||
| 181 | if (!empty($fileInfo)) { |
||
| 182 | if (!preg_match('/^data:([^;]+);base64,(.+)$/', $fileInfo, $fileMatch)) { |
||
| 183 | // ちゃんとファイルアップがないのでエラー |
||
| 184 | throw new InternalErrorException('tmp upload erroar'); |
||
| 185 | } |
||
| 186 | $filename = $this->{'contents_file_' . $field . '_filename'}; |
||
| 187 | |||
| 188 | $filebody = base64_decode($fileMatch[2]); |
||
| 189 | $filesize = strlen($filebody); |
||
| 190 | |||
| 191 | $tmpFileName = Security::hash(rand() . Time::now()->i18nFormat('YYYY/MM/dd HH:ii:ss') . $filename); |
||
| 192 | |||
| 193 | if ($this->getExt($filename) !== null) { |
||
| 194 | $tmpFileName .= '.' . $this->getExt($filename); |
||
| 195 | } |
||
| 196 | // まずは一時的にファイルを書き出す |
||
| 197 | $ddTmpFileName = TMP . Security::hash(rand() . Time::now()->i18nFormat('YYYY/MM/dd HH:ii:ss') . $filename); |
||
| 198 | $fp = new File($ddTmpFileName); |
||
|
0 ignored issues
–
show
The class
Cake\Filesystem\File has been deprecated with message: 4.0.0 Will be removed in 5.0.
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead. Loading history...
|
|||
| 199 | $fp->write($filebody); |
||
| 200 | |||
| 201 | // tmpディレクトリへのアップロードのエラー(パーミッションなど) |
||
| 202 | if (!$this->tmpUpload($ddTmpFileName, $fieldSetting, $tmpFileName)) { |
||
|
0 ignored issues
–
show
$ddTmpFileName is of type string, but the function expects a object<Laminas\Diactoros\UploadedFile>.
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
Loading history...
|
|||
| 203 | throw new InternalErrorException('tmp upload error'); |
||
| 204 | } |
||
| 205 | $fp->delete(); |
||
| 206 | $fp->close(); |
||
| 207 | |||
| 208 | $fileSet = [ |
||
| 209 | 'model' => $this->getSource(), |
||
|
0 ignored issues
–
show
It seems like
getSource() 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 Adding the Loading history...
|
|||
| 210 | 'model_id' => $this->id, |
||
| 211 | 'field_name' => $field, |
||
| 212 | 'file_name' => $filename, |
||
| 213 | 'file_content_type' => Configure::read('ContentsFile.Setting.type'), |
||
| 214 | 'file_size' => $filesize, |
||
| 215 | 'file_error' => 0, |
||
| 216 | ]; |
||
| 217 | |||
| 218 | $fileSet['tmp_file_name'] = $tmpFileName; |
||
| 219 | |||
| 220 | //これを残して次に引き渡したくないので |
||
| 221 | unset($this->{$field}); |
||
| 222 | |||
| 223 | $this->{'contents_file_' . $field} = $fileSet; |
||
| 224 | $this->{'contents_file_' . $field . '_filename'} = $filename; |
||
| 225 | } |
||
| 226 | } |
||
| 227 | |||
| 228 | /** |
||
| 229 | * getExt |
||
| 230 | * 拡張子の取得 |
||
| 231 | * |
||
| 232 | * @author hagiwara |
||
| 233 | * @param string $file |
||
| 234 | * @return string|null |
||
| 235 | */ |
||
| 236 | private function getExt(string $file): ?string |
||
| 237 | { |
||
| 238 | $fileExplode = explode('.', $file); |
||
| 239 | //この場合拡張子なし |
||
| 240 | if (count($fileExplode) == 1) { |
||
| 241 | return null; |
||
| 242 | } |
||
| 243 | return $fileExplode[(count($fileExplode) - 1)]; |
||
| 244 | } |
||
| 245 | |||
| 246 | /** |
||
| 247 | * tmpUpload |
||
| 248 | * tmpディレクトリへのアップロード |
||
| 249 | * |
||
| 250 | * @author hagiwara |
||
| 251 | * @param \Laminas\Diactoros\UploadedFile $fileInfo |
||
| 252 | * @param array $fieldSetting |
||
| 253 | * @param string $tmpFileName |
||
| 254 | * @return mixed |
||
| 255 | */ |
||
| 256 | private function tmpUpload(UploadedFile $fileInfo, array $fieldSetting, string $tmpFileName) |
||
|
0 ignored issues
–
show
|
|||
| 257 | { |
||
| 258 | // すでにtraitのため、ここはif文での分岐処理 |
||
| 259 | if (Configure::read('ContentsFile.Setting.type') == 'normal') { |
||
| 260 | $fileInfo->moveTo(Configure::read('ContentsFile.Setting.Normal.tmpDir') . $tmpFileName); |
||
| 261 | // 向きの調整をする場合 |
||
| 262 | if (Configure::read('ContentsFile.Setting.exifRotate') == true) { |
||
| 263 | $this->orientationFixedImage($tmpFileName, $tmpFileName); |
||
| 264 | } |
||
| 265 | |||
| 266 | return true; |
||
| 267 | |||
| 268 | } elseif (Configure::read('ContentsFile.Setting.type') == 's3') { |
||
| 269 | $tmpName = Configure::read('ContentsFile.Setting.S3.workingDir') . $tmpFileName; |
||
| 270 | $fileInfo->moveTo($tmpName); |
||
| 271 | $uploadFileName = Configure::read('ContentsFile.Setting.S3.tmpDir') . $tmpFileName; |
||
| 272 | |||
| 273 | $S3 = new S3(); |
||
| 274 | return $S3->upload($tmpName, $uploadFileName); |
||
| 275 | } else { |
||
| 276 | throw new InternalErrorException('contentsFileConfig type illegal'); |
||
| 277 | } |
||
| 278 | } |
||
| 279 | |||
| 280 | /** |
||
| 281 | * orientationFixedImage |
||
| 282 | * http://www.glic.co.jp/blog/archives/88 よりコピペ |
||
| 283 | * 画像の方向を正す |
||
| 284 | * 向きだけロジックが逆そうなので調整 |
||
| 285 | * |
||
| 286 | * @param string $input |
||
| 287 | * @param string $output |
||
| 288 | * @return void |
||
| 289 | * @author hagiwara |
||
| 290 | */ |
||
| 291 | private function orientationFixedImage(string $input, string $output): void |
||
| 292 | { |
||
| 293 | $imagetype = exif_imagetype($input); |
||
| 294 | // 何も取れない場合何もしない |
||
| 295 | if ($imagetype === false) { |
||
| 296 | return; |
||
| 297 | } |
||
| 298 | // exif情報の取得 |
||
| 299 | $exif_datas = []; |
||
| 300 | // 画像読み込み |
||
| 301 | switch ($imagetype) { |
||
| 302 | case IMAGETYPE_GIF: |
||
| 303 | $image = ImageCreateFromGIF($input); |
||
| 304 | break; |
||
| 305 | case IMAGETYPE_JPEG: |
||
| 306 | $image = ImageCreateFromJPEG($input); |
||
| 307 | // exif情報の取得(jpegのみ |
||
| 308 | $exif_datas = @exif_read_data($input); |
||
| 309 | break; |
||
| 310 | case IMAGETYPE_PNG: |
||
| 311 | $image = ImageCreateFromPNG($input); |
||
| 312 | break; |
||
| 313 | default: |
||
| 314 | $image = false; |
||
| 315 | } |
||
| 316 | |||
| 317 | // 画像以外は何もしない |
||
| 318 | if (!$image) { |
||
| 319 | return; |
||
| 320 | } |
||
| 321 | |||
| 322 | // 向き補正 |
||
| 323 | if(isset($exif_datas['Orientation'])){ |
||
| 324 | $orientation = $exif_datas['Orientation']; |
||
| 325 | if($image){ |
||
| 326 | // 未定義 |
||
| 327 | if($orientation == 0) { |
||
| 328 | // 通常 |
||
| 329 | }else if($orientation == 1) { |
||
| 330 | // 左右反転 |
||
| 331 | }else if($orientation == 2) { |
||
| 332 | $image = $this->imageFlop($image); |
||
| 333 | // 180°回転 |
||
| 334 | }else if($orientation == 3) { |
||
| 335 | $image = $this->imageRotate($image,180, 0); |
||
| 336 | // 上下反転 |
||
| 337 | }else if($orientation == 4) { |
||
| 338 | $image = $this->imageFlip($image); |
||
| 339 | // 反時計回りに90°回転 上下反転 |
||
| 340 | }else if($orientation == 5) { |
||
| 341 | $image = $this->imageRotate($image,90, 0); |
||
| 342 | $image = $this->imageFlip($image); |
||
| 343 | // 時計回りに90°回転 |
||
| 344 | }else if($orientation == 6) { |
||
| 345 | $image = $this->imageRotate($image,-90, 0); |
||
| 346 | // 時計回りに90°回転 上下反転 |
||
| 347 | }else if($orientation == 7) { |
||
| 348 | $image = $this->imageRotate($image,-90, 0); |
||
| 349 | $image = $this->imageFlip($image); |
||
| 350 | // 反時計回りに90°回転 |
||
| 351 | }else if($orientation == 8) { |
||
| 352 | $image = $this->imageRotate($image,90, 0); |
||
| 353 | } |
||
| 354 | } |
||
| 355 | } |
||
| 356 | |||
| 357 | switch ($imagetype) { |
||
| 358 | case IMAGETYPE_GIF: |
||
| 359 | ImageGIF($image ,$output); |
||
| 360 | break; |
||
| 361 | case IMAGETYPE_JPEG: |
||
| 362 | ImageJPEG($image ,$output, 100); |
||
| 363 | break; |
||
| 364 | case IMAGETYPE_PNG: |
||
| 365 | ImagePNG($image ,$output); |
||
| 366 | break; |
||
| 367 | default: |
||
| 368 | return; |
||
| 369 | } |
||
| 370 | } |
||
| 371 | |||
| 372 | /** |
||
| 373 | * imageFlop |
||
| 374 | * http://www.glic.co.jp/blog/archives/88 よりコピペ |
||
| 375 | * 画像の左右反転 |
||
| 376 | * |
||
| 377 | * @param resource $image |
||
| 378 | * @return resource |
||
| 379 | * @author hagiwara |
||
| 380 | */ |
||
| 381 | private function imageFlop($image) |
||
| 382 | { |
||
| 383 | // 画像の幅を取得 |
||
| 384 | $w = imagesx($image); |
||
| 385 | // 画像の高さを取得 |
||
| 386 | $h = imagesy($image); |
||
| 387 | // 変換後の画像の生成(元の画像と同じサイズ) |
||
| 388 | $destImage = @imagecreatetruecolor($w,$h); |
||
| 389 | // 逆側から色を取得 |
||
| 390 | for($i=($w-1);$i>=0;$i--){ |
||
| 391 | for($j=0;$j<$h;$j++){ |
||
| 392 | $color_index = imagecolorat($image,$i,$j); |
||
| 393 | $colors = imagecolorsforindex($image,$color_index); |
||
| 394 | imagesetpixel($destImage,abs($i-$w+1),$j,imagecolorallocate($destImage,$colors["red"],$colors["green"],$colors["blue"])); |
||
| 395 | } |
||
| 396 | } |
||
| 397 | return $destImage; |
||
| 398 | } |
||
| 399 | |||
| 400 | /** |
||
| 401 | * imageFlip |
||
| 402 | * http://www.glic.co.jp/blog/archives/88 よりコピペ |
||
| 403 | * 上下反転 |
||
| 404 | * @param resource $image |
||
| 405 | * @return resource |
||
| 406 | * |
||
| 407 | * @author hagiwara |
||
| 408 | */ |
||
| 409 | private function imageFlip($image) |
||
| 410 | { |
||
| 411 | // 画像の幅を取得 |
||
| 412 | $w = imagesx($image); |
||
| 413 | // 画像の高さを取得 |
||
| 414 | $h = imagesy($image); |
||
| 415 | // 変換後の画像の生成(元の画像と同じサイズ) |
||
| 416 | $destImage = @imagecreatetruecolor($w,$h); |
||
| 417 | // 逆側から色を取得 |
||
| 418 | for($i=0;$i<$w;$i++){ |
||
| 419 | for($j=($h-1);$j>=0;$j--){ |
||
| 420 | $color_index = imagecolorat($image,$i,$j); |
||
| 421 | $colors = imagecolorsforindex($image,$color_index); |
||
| 422 | imagesetpixel($destImage,$i,abs($j-$h+1),imagecolorallocate($destImage,$colors["red"],$colors["green"],$colors["blue"])); |
||
| 423 | } |
||
| 424 | } |
||
| 425 | return $destImage; |
||
| 426 | } |
||
| 427 | |||
| 428 | |||
| 429 | /** |
||
| 430 | * imageRotate |
||
| 431 | * http://www.glic.co.jp/blog/archives/88 よりコピペ |
||
| 432 | * 画像を回転 |
||
| 433 | * @param resouce $image |
||
| 434 | * @param integer $angle |
||
| 435 | * @param integer $bgd_color |
||
| 436 | * @return resource |
||
| 437 | * |
||
| 438 | * @author hagiwara |
||
| 439 | */ |
||
| 440 | private function imageRotate($image, int $angle, int $bgd_color) |
||
| 441 | { |
||
| 442 | return imagerotate($image, $angle, $bgd_color, 0); |
||
| 443 | } |
||
| 444 | } |
||
| 445 |
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: