to('/' . $route . '/' . $this->filename); } protected static function boot() { parent::boot(); static::creating(function (Image $model) { if (empty($model->content)) { throw new InvalidContent("Content must be defined to save image"); } if (!($model->content instanceof InterventionImage)) { throw new InvalidContent("Content must be an instance of Intervention\Image"); } $model->savePicture(); }); static::updating(function (Image $model) { $model->savePicture(); }); static::deleted(function (Image $model) { $model->deletePicture(); }); } public function getPath() { if (empty($this->filename)) { return null; } return self::getAbsolutePath($this->filename); } static function getAbsolutePath($filename) { $basePath = config('image.path'); if (empty($basePath)) { throw new \Exception('You must defined config image.path'); } $parts = array_slice(str_split(mb_strtolower(str_slug($filename, '')), 2), 0, 2); $path = $basePath . '/' . implode('/', $parts) . '/' . $filename; return $path; } static function generateRandomFilename() { return mb_strtolower(str_random(60)); } static function sanitizeFilename($filename) { return str_slug($filename, '-'); } public function setFilenameAttribute($value) { $pattern = '/[^a-z_\-\.0-9]/i'; $patternLetter = '/[a-z0-9]+/i'; if (preg_match($pattern, $value) || !preg_match($patternLetter, $value)) { throw new \InvalidArgumentException("Invalid filename. Must be only composed only with a-z, A-Z, 0-9 and dot minus underscore"); } $this->attributes['filename'] = $value; } public function fileExist() { return is_file($this->getPath()); } public function generateFilename($force = false) { if ($this->filename && !$force) { return; } $this->filename = self::generateRandomFilename(); } public function setContentAttribute($content) { $this->_content = app('image')->make($content); } public function getHashAttribute() { if (empty($this->content)) { return null; } if (empty($this->content->getEncoded())) { $this->content->encode(); } return sha1($this->content->getEncoded()); } public function getExtensionAttribute() { $mime = $this->content->mime(); if (empty($mime)) { return null; } return str_replace('image/', '', $mime); } public function getMimeAttribute() { if (empty($this->content)) { return null; } return $this->content->mime(); } public function same(Image $image) { $hash1 = $this->hash; $hash2 = $image->hash; return !empty($hash1) && !empty($hash2) && $hash1 === $hash2; } public function getContentAttribute($value) { if (empty($this->_content)) { try { $this->_content = app('image')->make($this->getPath()); } catch (NotReadableException $e) { return null; } } return $this->_content; } protected function savePicture() { if (empty($this->content)) { return true; } $this->generateFilename(); return $this->saveContent(); } protected function saveContent() { if (empty($this->content)) { throw new \InvalidArgumentException("Content is Empty"); } $path = $this->getPath(); $dir = dirname($path); if (!is_dir($dir)) { mkdir($dir, 0775, true); } $res = $this->content->save($path); app(OptimizerChain::class)->optimize($path); return $res; } protected function deletePicture() { $path = $this->getPath(); if (is_file($path)) { return unlink($path); } return true; } /** * @param Model $class * @param $relationName * @return MorphToMany */ public static function createRelation(Model $class, $relationName) { $instance = $class->newRelatedInstance(static::class); $foreignPivotKey = 'relation_id'; $relatedPivotKey = 'image_id'; $table = 'associate_images'; $name = 'relation'; $morph = new MorphToMany( $instance->newQuery(), $class, $name, $table, $foreignPivotKey, $relatedPivotKey, $class->getKeyName(), $instance->getKeyName(), $relationName, false ); $morph->withPivot('position'); return $morph; } public function toArray() { $attributes = parent::toArray(); return $attributes; } }