commit f23aee6dcb86a6c4892ff9dd1ac08e12b4b6a364 Author: Sasha Rybkin Date: Wed Nov 20 15:56:54 2024 +0300 init diff --git a/Config.php b/Config.php new file mode 100644 index 0000000..01980c7 --- /dev/null +++ b/Config.php @@ -0,0 +1,193 @@ + 50], + [['name'], 'string', 'max' => 500], + [['fileId'], 'formatImg'], + ]; + } + public function formatImg($attribute, $params) + { + File::validateFormat($this, $attribute, ['extensions' => 'png, jpg']); + } + + /** + * {@inheritdoc} + */ + /*public function attributeLabels() + { + return [ + 'id' => Module::t('app', 'ID'), + 'module' => Module::t('app', 'Module'), + 'type' => Module::t('app', 'Type'), + 'height' => Module::t('app', 'Height'), + 'width' => Module::t('app', 'Width'), + 'name' => Module::t('app', 'Name'), + 'crop' => Module::t('app', 'Crop'), + 'cut' => Module::t('app', 'Cut'), + 'addBorder' => Module::t('app', 'Add Border'), + 'fileId' => Module::t('app', 'File'), + 'border_right' => Module::t('app', 'Border Right'), + 'border_top' => Module::t('app', 'Border Top'), + 'border_left' => Module::t('app', 'Border Left'), + 'border_bottom' => Module::t('app', 'Border Bottom'), + 'quality' => Module::t('app', 'Quality'), + ]; + }*/ + + /*public function beforeSave($insert) + { + $this->fileId = File::formSave('config', $this->fileId); + return parent::beforeSave($insert); + }*/ + + public function getFile() + { + return $this->hasOne(File::className(), ['id' => 'fileId']); + } + + public static function getData($params, $root) + { + $query = self::find(); + $root->andWhere($query, $params, ['id', 'module', 'type']); + $root->andWhereLike($query, $params, ['name']); + + $root->setMetaByQuery($query); + $root->orderBy($query, $params, ['id', 'module', 'type', 'height', 'width', 'name', 'crop', 'cut', 'addBorder']); + return $root->getItemsByPage($query); + } + + public function beforeDelete() + { + if($this->file) + { + $this->file->delete(); + } + return parent::beforeDelete(); + } + + public function customSave($args) + { + if((isset($args['fileDelete']) && $args['fileDelete']) || (isset($args['file'], $args['fileName']) && !empty($args['file']))) + { + if($this->file) + { + $this->file->delete(); + } + } + foreach(['name', 'module', 'type', 'height', 'width', 'cut', 'crop', 'addBorder', 'border_top', 'border_right', 'border_left', 'border_bottom', 'quality'] as $item) + { + if(isset($args[$item])) + { + $this->$item = is_bool($args[$item]) ? (int) $args[$item] : $args[$item]; + } + } + + if((isset($args['file'], $args['fileName']) && !empty($args['file']))) + { + $this->fileId = File::saveBase64File('file', $args['file'], $args['fileName'], '', false); + } + $this->fileId = (int)$this->fileId; + $this->save(); + return $this->id; + } + + public function resize($args) + { + $time = time() + 5; + $all = isset($args['all']) && $args['all']; + $fileId = isset($args['fileId']) ? $args['fileId'] : 0; + $files = File::find()->andWhere(['module'=> $this->module])->andWhere(['>', 'id', $fileId])->limit(200)->all(); + $output = ['count' => 0]; + $fileTemplate = $this->file ? [ + 'filePatch' => $this->file->getFilePath(false, true), + 'border_top' => $this->border_top, + 'border_right' => $this->border_right, + 'border_left' => $this->border_left, + 'border_bottom' => $this->border_bottom, + ] : []; + if($this->file) + { + $this->file->downloadOriginal(); + } + + + if(!empty($files)) + { + $output['step'] = 'procccess'; + foreach ($files as $file) + { + try{ + $file->downloadOriginal(); + $file->resize($this->type, $this->height, $this->width, $this->crop, $this->cut, $this->addBorder, $all, $fileTemplate, $this->quality); + if($file->cropFile) + { + @unlink($file->cropFile); + } + if(\Yii::$app->has('s3')) + { + $s3 = \Yii::$app->get('s3'); + if(file_exists($file->getFilePath($this->type, true))) + { + $s3->upload($file->getFilePath($this->type), $file->getFilePath($this->type, true)); + @unlink($file->getFilePath($this->type, true)); + } + } + } + catch (\Exception $ex) + { + } + $output['fileId'] = $file->id; + $output['count'] ++; + if($time < time()) + { + break; + } + } + } + else + { + $output['step'] = 'finish'; + } + return $output; + + } +} diff --git a/File.php b/File.php new file mode 100644 index 0000000..40b539e --- /dev/null +++ b/File.php @@ -0,0 +1,659 @@ + 500], + [['md5', 'ext'], 'string', 'max' => 50], + ]; + } + + /** + * {@inheritdoc} + */ + /*public function attributeLabels() + { + return [ + 'id' => Module::t('app', 'ID'), + 'date' => Module::t('app', 'Date'), + 'module' => Module::t('app', 'Module'), + 'height' => Module::t('app', 'Height'), + 'width' => Module::t('app', 'Width'), + 'fileSize' => Module::t('app', 'File Size'), + 'md5' => Module::t('app', 'Md5'), + 'ext' => Module::t('app', 'Ext'), + 'description' => Module::t('app', 'Description'), + 'originalName' => Module::t('app', 'Original Name'), + 'name' => Module::t('app', 'Name'), + ]; + }*/ + + public static function validateFormat($model, $attribute, $params, $fileName = 'file') + { + $fileModel = new File; + + $fileModel->file = UploadedFile::getInstance($fileModel, $fileName); + if ($fileModel->file && $fileModel->file->tempName) + { + \yii\validators\Validator::createValidator('file', $fileModel, 'file', $params)->validateAttribute($fileModel, 'file'); + if ($fileModel->hasErrors()) + { + $model->addError($attribute, 'Не верный формат файла'); + } + } + } + + /** + * Папка с файлом + * @param boolian $full + * @return type + */ + public function getDir($full = false, $resize = false) + { + $dir = $resize ? 'file_resize' : 'file'; + $output = ''; + // $full = $full && !Yii::$app->has('s3'); + if($full) + { + $output = Yii::getAlias('@app/web'); + } + $output .= '/data/' . $dir . '/' . $this->module . '/' . wordwrap(mb_substr($this->md5, 0, 6), 2, '/', true) . '/'; + if(Yii::$app->has('s3') && $full && $resize) + { + //если работаем с облаком не плодим папки миниатюр + $output = Yii::getAlias('@app/web/data/file_cache/'); + } + if ($full && !file_exists($output)) + { + mkdir($output, 0755, true); + } + if(Yii::$app->has('s3') && $full && $resize) + { + //если работаем с облаком не плодим папки миниатюр + $output .= $this->md5.'-'; + } + return $output; + } + + /** + * Путь к папке кеша + * @return string + */ + public function getDirCache() + { + $dir = Yii::getAlias('@app/web/data/file_cache/'); + if (!file_exists($dir)) + { + mkdir($dir, 0755, true); + } + return $dir; + } + + public function getFilePath($type = false, $full = false) + { + $pref = $type ? ($type . '-') : ''; + return $this->getDir($full, $type != false) . $pref . $this->name . '.' . $this->ext; + } + + public function getFilePathCache() + { + $this->cropFile = $this->cropFile ? $this->cropFile :$this->getDirCache() . rand(1000, 999999); + return $this->cropFile; + } + + public function getIsImage() + { + return in_array($this->ext, ['jpg', 'png', 'jpeg']); + } + + public function getShowImage() + { + return in_array($this->ext, ['jpg', 'png', 'jpeg', 'svg']); + } + + protected function getFileName() + { + $defaultName = empty($this->name) ? $this->md5 : $this->name; + $name = $defaultName; + $i = 0; + while(($model = File::find()->andWhere(['ext' => $this->ext, 'name'=>$name])->andWhere('md5 like "'. mb_substr($this->md5, 0, 6).'%"')->one()) !== null) + { + $i++; + $name = $defaultName . '-' .$i; + } + return $name; + } + + /** + * {@inheritdoc} + */ + public function beforeSave($insert) + { + if ($this->file) + { + $this->ext = $this->file->extension; + $this->md5 = md5_file($this->file->tempName); + $patch = $this->getDir(true); + if ($this->isImage) + { + $this->ext = $this->convertJpg ? 'jpg' : $this->ext; + $this->name = $this->getFileName(); + $fileName = $this->name . '.' . $this->ext; + + $image = Image::getImagine()->open($this->file->tempName); + $size = $image->getSize(); + $this->width = $size->getWidth(); + $this->height = $size->getHeight(); + + $box = new Box($this->width, $this->height); + $palette = new \Imagine\Image\Palette\RGB(); + $color = $palette->color(Image::$thumbnailBackgroundColor, Image::$thumbnailBackgroundAlpha); + $thumb = Image::getImagine()->create($box, $color); + $thumb->paste($image, new \Imagine\Image\Point(0, 0)); + // var_dump($thumb); die(); + $thumb->save($patch . $fileName); + $this->fileSize = filesize($patch . $fileName); + } + else + { + $this->name = $this->getFileName(); + $this->fileSize = $this->file->size; + $fileName = $this->name . '.' . $this->ext; + if (is_uploaded_file($this->file->tempName)) + { + $this->file->saveAs($patch . $fileName); + } + else + { + rename($this->file->tempName, $patch . $fileName); + } + } + $this->originalName = $this->file->name; + $this->date = date('Y-m-d H:i:s'); + } + return parent::beforeSave($insert); + } + + public function afterSave($insert, $changedAttributes) + { + if (isset($this->file)) + { + $configs = Config::find()->andWhere(['module' => $this->module])->all(); + foreach ($configs as $config) + { + $fileTemplate = $config->file ? [ + 'filePatch' => $config->file->getFilePath(false, true), + 'border_top' => $config->border_top, + 'border_right' => $config->border_right, + 'border_left' => $config->border_left, + 'border_bottom' => $config->border_bottom, + ] : []; + if($config->file) + { + $config->file->downloadOriginal(); + } + $quality = isset($config->quality) ? $config->quality : 90; + $this->resize($config->type, $config->height, $config->width, $config->crop, $config->cut, $config->addBorder, true, $fileTemplate, $quality); + } + if($this->cropFile) + { + @unlink($this->cropFile); + } + $this->moveToS3(); + } + return parent::afterSave($insert, $changedAttributes); + } + + /** + * Возврашает путь к изображению + * @param type $id + * @return string + */ + public static function getPath($id, $type = false) + { + $output = ''; + if ($id > 0 && ($model = File::findOne($id)) !== null) + { + $output = $model->getFilePath($type); + } + return $output; + } + + /** + * Возврашает путь к изображению + * @param type $id + * @return string + */ + public static function getPathFull($id, $type = false, $default = false) + { + $img = File::getPath($id, $type); + $fileUrlDomen = isset(Yii::$app->params['fileUrlDomen']) ? Yii::$app->params['fileUrlDomen'] : ''; + $img = empty($img) ? $default : $img; + return empty($img) ? false : (preg_replace("#/$#", "", $fileUrlDomen) . $img); + + } + + public static function getPathsFull($id, $types = []) + { + $fileUrlDomen = isset(Yii::$app->params['fileUrlDomen']) ? Yii::$app->params['fileUrlDomen'] : ''; + return self::getPaths($id, $types, $fileUrlDomen); + } + + /** + * Возврашает пути к изображениям + * @param type $id + * @return array + */ + public static function getPaths($id, $types = [], $prefix = '') + { + $output = []; + if ($id > 0 && ($model = File::findOne($id)) !== null) + { + foreach($types as $type) + { + $output[$type] = $prefix. $model->getFilePath($type); + } + } + return $output; + } + + protected function deleteDisckFile($deleteOriginal = false) + { + if($deleteOriginal) + { + //удаляем оригинал + $file = $this->getFilePath(false, true); + if(file_exists($file)) + { + unlink($file); + $files = array_diff(scandir($this->getDir(true)), array('.', '..')); + if(empty($files)) + { + Helper::delFolder($this->getDir(true)); + } + } + } + //удаляем миниатюры + $dir = $this->getDir(true, true); + if(file_exists($dir)) + { + $files = array_diff(scandir($dir), array('.', '..')); + foreach ($files as $key => $value) + { + if(stripos($value, $this->md5 . '.' . $this->ext) !== false) + { + unlink("$dir/$value"); + unset($files[$key]); + } + } + if(empty($files)) + { + Helper::delFolder($this->getDir(true, true)); + } + } + } + protected function deleteS3File() + { + if(Yii::$app->has('s3')) + { + $s3 = Yii::$app->get('s3'); + $s3->delete($this->getFilePath()); + $configs = Config::find()->andWhere(['module' => $this->module])->all(); + foreach ($configs as $config) + { + $s3->delete($this->getFilePath($config->type)); + } + } + } + + public function delete() + { + $this->deleteDisckFile(true); + $this->deleteS3File(); + return parent::delete(); + } + + /** + * Создание миниатюр + * @param string $type + * @param int $height + * @param int $width + * @param boolian $crop обрезать белую рамку + * @param boolian $cut обрезать по расмеру без соблюдения пропорций сторон + * @param boolian $addBorder добавить белую рамку + * @param boolian $all обновить изображение если уже оно создано + * @param array $fileTemplate Вписать в шаблон + * @param int $quality качество (степень сжатия) + * + */ + public function resize($type, $height, $width, $crop = false, $cut = false, $addBorder = false, $all = false, $fileTemplate = [], $quality = 90) + { + $patch = $this->getDir(true); + $fileName = $this->name . '.' . $this->ext; + $filePatch = $patch . $fileName; + $quality = $quality > 100 || $quality <= 0 ? 90 : $quality; + if (file_exists($filePatch) && in_array(exif_imagetype($filePatch), [IMAGETYPE_JPEG, IMAGETYPE_PNG])) + { + $resizePatch = $this->getDir(true, true); + $resizeFileName = $type . '-' . $fileName; + + if ($all || !file_exists($resizePatch . $resizeFileName)) + { + if ($crop) + { + $filePatch = $this->cropFile ? $this->cropFile : $this->deleteBorder($filePatch); + } + + if(!empty($fileTemplate) && isset($fileTemplate['filePatch'], $fileTemplate['border_top'], $fileTemplate['border_right'], $fileTemplate['border_left'], $fileTemplate['border_bottom'])) + { + \dominion\file\Image::thumbnailFileTemplate($filePatch, $width, $height, $fileTemplate)->save($resizePatch . $resizeFileName, ['quality' => $quality]); + } + elseif ($cut || $addBorder) + { + $class = $addBorder ? '\dominion\file\Image' : '\yii\imagine\Image'; + $mode = $addBorder ? ImageInterface::THUMBNAIL_INSET : ImageInterface::THUMBNAIL_OUTBOUND; + $class::thumbnail($filePatch, $width, $height, $mode)->save($resizePatch . $resizeFileName, ['quality' => $quality]); + } + else + { + Image::getImagine()->open($filePatch)->thumbnail(new Box($width, $height))->save($resizePatch . $resizeFileName, ['quality' => $quality]); + } + } + } + } + + /** + * Обрезает белую рамку + * @param type $filePatch + * @return type + */ + protected function deleteBorder($filePatch) + { + $img = imagecreatefromjpeg($filePatch); + + $this->width = $this->width > 0 ? $this->width : imagesx($img); + $this->height = $this->height > 0 ? $this->height : imagesy($img); + + $border = array( + 'left' => $this->getBorderSize($img, $this->width, $this->height, 'r'), + 'right' => $this->getBorderSize($img, $this->width, $this->height, 'l'), + 'top' => $this->getBorderSize($img, $this->height, $this->width, 'b'), + 'bottom' => $this->getBorderSize($img, $this->height, $this->width, 't'), + ); + + $x = $border['left']; + $y = $border['top']; + $newWidth = $this->width - ($border['left'] + $border['right']); + $newHeight = $this->height - ($border['top'] + $border['bottom']); + + if($newWidth == 0 || $newHeight == 0) + { + return $filePatch; + } + + // create the working image + $workingImage = function_exists('imagecreatetruecolor') ? imagecreatetruecolor($newWidth, $newHeight) : imagecreate($newWidth, $newHeight); + + // and create the newly sized image + imagecopy( + $workingImage, + $img, + 0, + 0, + $x, + $y, + $newWidth, + $newHeight + ); + + $temp = $this->getFilePathCache(); + imagejpeg($workingImage, $temp, 100); + return $temp; + } + + /** + * Возвращает позицию первого не белого пикселя + * @param type $image + * @param type $width + * @param type $height + * @param type $direction + * @return int + * @throws Exception + */ + protected function getBorderSize($image, $width, $height, $direction) + { + $border = 0; + $realWidth = imagesx($image); + $realHeight = imagesy($image); + for ($i = 0; $i < $width; $i++) + { + $isWhite = true; + $errors = round($height / 100); + for ($j = 0; $j < $height; $j++) + { + switch ($direction) + { + case 'l': + $x = $width - $i - 1; + $y = $j; + break; + case 'b': + $x = $j; + $y = $i; + break; + case 't': + $x = $j; + $y = $width - $i - 1; + break; + default: + $x = $i; + $y = $j; + break; + } + if ($x > $realWidth || $y > $realHeight || $x < 0 || $y < 0) + { + throw new Exception('Не верные координаты изображения'); + } + // Получаем RGB пикселя по координате + $color = imageColorAt($image, $x, $y); + // Разбиваем RGB на Red,Green,Blue и записываем каждую составляющую в свою переменную + $pixel = imageColorsForIndex($image, $color); + list($r, $g, $b) = array_values($pixel); + //Сравнение белого ли цвета пиксель + if ($r > 241 && $g > 241 && $b > 241) + { + // белый + } + else + { + // не белый + $errors--; + if ($errors <= 0) + { + $isWhite = false; + break; + } + } + } + if ($isWhite) + { + $border++; + } + else + { + break; + } + } + return $border; + } + + public function loadFile($module, $url, $id = false) + { + $file = @file_get_contents($url); + if ($file !== false) + { + $temp = $this->getFilePathCache(); + file_put_contents($temp, $file); + unset($file); + if (!$id || ($model = File::findOne($id)) === null) + { + $model = new File(); + $model->module = $module; + } + $arName = explode('/', $url); + $model->file = new UploadedFile( + [ + 'name' => array_pop($arName), + 'tempName' => $temp, + 'type' => mime_content_type($temp), + 'size' => filesize($temp), + 'error' => UPLOAD_ERR_OK, + ] + ); + $model->save(); + return $model->id; + } + } + + /** + * Сохранение файла из строки Base64 + * @param type $module + * @param type $fileBase64 + * @param type $fileName + * @param type $id + * @return type + */ + public static function saveBase64File($module, $fileBase64, $fileName, $id = false, $convertJpg = true) + { + if (!$id || ($model = File::findOne($id)) === null) + { + $model = new File(); + $model->module = $module; + } + $temp = $model->getFilePathCache(); + file_put_contents($temp, base64_decode($fileBase64)); + $model->file = new UploadedFile( + [ + 'name' => $fileName, + 'tempName' => $temp, + 'type' => mime_content_type($temp), + 'size' => filesize($temp), + 'error' => UPLOAD_ERR_OK, + ] + ); + $model->convertJpg = $convertJpg; + $model->save(); + + return $model->id; + } + + public function getSize() + { + $fix = array(' B', ' KB', ' MB', ' GB', ' TB'); + $round = 2; + + $mult = 1E3; + $range = 0; + while (1 < $this->fileSize / pow($mult, $range)) + { + $range++; + } + $mult = pow($mult, $range - 1); + $postfix = $fix[$range - 1]; + return round($this->fileSize / $mult, $round) . $postfix; + } + + public function moveToS3() + { + if(Yii::$app->has('s3')) + { + $s3 = Yii::$app->get('s3'); + if(file_exists($this->getFilePath(false, true))) + { + $s3->upload($this->getFilePath(), $this->getFilePath(false, true)); + $configs = Config::find()->andWhere(['module' => $this->module])->all(); + foreach ($configs as $config) + { + if(file_exists($this->getFilePath($config->type, true))) + { + $s3->upload($this->getFilePath($config->type), $this->getFilePath($config->type, true)); + } + } + } + } + //var_dump($this->getFilePath()); + } + + public function downloadOriginal() + { + if(Yii::$app->has('s3')) + { + $filePatch = $this->getFilePath(false, true); + if (!file_exists($filePatch) && isset(Yii::$app->params['fileUrlDomen'])) + { + $file = @file_get_contents(Yii::$app->params['fileUrlDomen']. $this->getFilePath()); + if($file) + { + @file_put_contents($filePatch, $file); + } + } + } + } + + public static function upload($oldFile, $newFile) + { + if(Yii::$app->has('s3')) + { + $s3 = Yii::$app->get('s3'); + if(file_exists($oldFile)) + { + $s3->upload($newFile, $oldFile); + } + } + } + +} \ No newline at end of file diff --git a/Helper.php b/Helper.php new file mode 100644 index 0000000..39283ce --- /dev/null +++ b/Helper.php @@ -0,0 +1,24 @@ +getSize(); + $thumbnailBox = static::getThumbnailBox($sourceBox, $width, $height); + + $img = $img->thumbnail($thumbnailBox, $mode); + + $size = $img->getSize(); + + $palette = new RGB(); + $color = $palette->color(static::$thumbnailBackgroundColor, static::$thumbnailBackgroundAlpha); + + // create empty image to preserve aspect ratio of thumbnail + $thumb = static::getImagine()->create($thumbnailBox, $color); + + // calculate points + $startX = 0; + $startY = 0; + if ($size->getWidth() < $width) { + $startX = ceil(($width - $size->getWidth()) / 2); + } + if ($size->getHeight() < $height) { + $startY = ceil(($height - $size->getHeight()) / 2); + } + + $thumb->paste($img, new Point($startX, $startY)); + + return $thumb; + } + + public static function thumbnailFileTemplate($image, $width, $height, $fileTemplate, $mode = ImageInterface::THUMBNAIL_INSET) + { + $newWidth = $width - $fileTemplate['border_right'] - $fileTemplate['border_left']; + $newHeight = $height - $fileTemplate['border_top'] - $fileTemplate['border_bottom']; + + $img = self::ensureImageInterfaceInstance($image); + /** @var BoxInterface $sourceBox */ + $sourceBox = $img->getSize(); + $thumbnailBox = static::getThumbnailBox($sourceBox, $newWidth, $newHeight); + + $img = $img->thumbnail($thumbnailBox, $mode); + $size = $img->getSize(); + + // calculate points + $startX = 0; + $startY = 0; + if ($size->getWidth() < $newWidth) { + $startX = ceil(($newWidth - $size->getWidth()) / 2); + } + if ($size->getHeight() < $newHeight) { + $startY = ceil(($newHeight - $size->getHeight()) / 2); + } + $startX += $fileTemplate['border_right']; + $startY += $fileTemplate['border_top']; + + // create empty image to preserve aspect ratio of thumbnail + $thumb = static::getImagine()->open($fileTemplate['filePatch']); + $thumb->paste($img, new Point($startX, $startY)); + + return $thumb; + } + +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..a890f91 --- /dev/null +++ b/composer.json @@ -0,0 +1,21 @@ +{ + "name": "dominion/file", + "description": "Функционал для работы с file", + "type": "yii2-extension", + "keywords": ["yii2","extension"], + "license": "MIT", + "authors": [ + { + "name": "Rybkin Sasha", + "email": "ribkin@dominion.ru" + } + ], + "require": { + "yiisoft/yii2": "~2.0.0" + }, + "autoload": { + "psr-4": { + "dominion\\file\\": "" + } + } +} \ No newline at end of file diff --git a/console/MoveController.php b/console/MoveController.php new file mode 100644 index 0000000..9a0743d --- /dev/null +++ b/console/MoveController.php @@ -0,0 +1,48 @@ + + * @since 0.1 + */ +class MoveController extends Controller +{ + + /** + * переносим данные с диска в s3 + * @return int Exit code + */ + public function actionIndex() + { + $flag = true; + $limit = 100; + $offset = 0; + while ($flag) + { + $models = File::find()->limit($limit)->offset($offset)->all(); + foreach ($models as $model) + { + $model->moveToS3(false); + } + $flag = count($models) == $limit; + $offset += $limit; + echo "перенесено: {$offset} \n"; + } + return ExitCode::OK; + } + +} diff --git a/console/ResizeController.php b/console/ResizeController.php new file mode 100644 index 0000000..11322c4 --- /dev/null +++ b/console/ResizeController.php @@ -0,0 +1,129 @@ + $id]); + if ($config) + { + $fileTemplate = $config->file ? [ + 'filePatch' => $config->file->getFilePath(false, true), + 'border_top' => $config->border_top, + 'border_right' => $config->border_right, + 'border_left' => $config->border_left, + 'border_bottom' => $config->border_bottom, + ] : []; + if ($config->file) + { + $config->file->downloadOriginal(); + } + + $flag = true; + $offset = $this->beginFrom; + $limit = 100;//000; + while ($flag) + { + $query = File::find()->andWhere(['module' => $config->module])->orderBy(['id'=>SORT_ASC])->offset($offset)->limit($limit); + if(!empty($this->onlyFile)) + { + $query->andWhere(['id' => explode(',', $this->onlyFile)]); + } + $files = (array) $query->all(); + $offset = $offset + count($files); + $flag = empty($files) || count($files) < $limit ? false :true; + $fileDelete = []; + + foreach ($files as $file) + { + try + { + $file->downloadOriginal(); + $file->resize($config->type, $config->height, $config->width, $config->crop, $config->cut, $config->addBorder, true, $fileTemplate, $config->quality); + if ($file->cropFile) + { + try + { + unlink($file->cropFile); + } + catch (\Exception $ex) + { + $fileDelete[] = $file->cropFile; + } + } + if (\Yii::$app->has('s3')) + { + $s3 = \Yii::$app->get('s3'); + if (file_exists($file->getFilePath($config->type, true))) + { + $s3->upload($file->getFilePath($config->type), $file->getFilePath($config->type, true)); + try + { + unlink($file->getFilePath($config->type, true)); + } + catch (\Exception $ex) + { + + $fileDelete[] = $file->getFilePath($config->type, true); + } + } + } + } catch (\Exception | \ValueError $ex) + { + echo "fileId {$file->id}; Exception: {$ex->getMessage()} \n"; + } + } + echo "обработано: {$offset} \n"; + foreach ($fileDelete as $value) + { + @unlink($value); + } + } + } + + + return ExitCode::OK; + } +} diff --git a/schema/FileConfigMutationType.php b/schema/FileConfigMutationType.php new file mode 100644 index 0000000..13937f7 --- /dev/null +++ b/schema/FileConfigMutationType.php @@ -0,0 +1,66 @@ + function() { + return [ + 'save' => [ + 'type' => Type::int(), + 'description' => 'Сохранение наклейки', + 'args' => [ + 'module' => Type::nonNull(Type::string()), + 'type' => Type::nonNull(Type::string()), + 'height' => Type::nonNull(Type::int()), + 'width' => Type::nonNull(Type::int()), + 'name' => Type::string(), + 'crop' => Type::boolean(), + 'cut' => Type::boolean(), + 'addBorder' => Type::boolean(), + 'border_top' => Type::int(), + 'border_right' => Type::int(), + 'border_left' => Type::int(), + 'border_bottom' => Type::int(), + 'quality' => Type::int(), + 'file' => Type::string(), + 'fileName' => Type::string(), + 'fileDelete' => Type::boolean(), + ], + 'resolve' => function(Config $root, $args) { + return $root->customSave($args); + }, + ], + 'delete' => [ + 'type' => Type::int(), + 'description' => 'Удаление', + 'resolve' => function(Config $root, $args) { + return $root->delete(); + }, + ], + 'resize' => [ + 'type' => Types::fileConfigResizeStep(), + 'description' => 'Сохранение наклейки', + 'args' => [ + 'all' => Type::boolean(), + 'fileId' => Type::int() + ], + 'resolve' => function(Config $root, $args) { + return $root->resize($args); + }, + ], + ]; + } + ]; + + parent::__construct($config); + } +} \ No newline at end of file diff --git a/schema/FileConfigPaginationType.php b/schema/FileConfigPaginationType.php new file mode 100644 index 0000000..581686d --- /dev/null +++ b/schema/FileConfigPaginationType.php @@ -0,0 +1,42 @@ + function(){ + $output = $this->getCustomFields(); + $output['data'] = [ + 'type' => Type::listOf(Types::fileConfig()), + 'description' => 'Конфигурация миниатюр', + 'args' => GraphQLPagination::argumentModify([ + 'id' => [ + 'type' => Type::int(), + 'description' => 'Id конфига', + ], + 'sort' => [ + 'type' => Type::string(), + 'description' => 'Сортировка (пример "isNew_asc" или "isVisible_desc")', + ], + ]), + 'resolve' => function($root, $args){ + return Config::getData($args, $root); + } + ]; + return $output; + } + ]; + parent::__construct($config); + } + +} diff --git a/schema/FileConfigResizeStepType.php b/schema/FileConfigResizeStepType.php new file mode 100644 index 0000000..8f3923c --- /dev/null +++ b/schema/FileConfigResizeStepType.php @@ -0,0 +1,33 @@ + function() { + return [ + 'fileId' => [ + 'type' => Type::int(), + 'description' => 'последний обработтанный файл', + ], + 'count' => [ + 'type' => Type::int(), + ], + 'step' => [ + 'type' => Type::string(), + 'description' => 'type', + ], + ]; + } + ]; + + parent::__construct($config); + } + +} \ No newline at end of file diff --git a/schema/FileConfigType.php b/schema/FileConfigType.php new file mode 100644 index 0000000..f2e0734 --- /dev/null +++ b/schema/FileConfigType.php @@ -0,0 +1,89 @@ + function() { + return [ + 'id' => [ + 'type' => Type::int(), + 'description' => 'Id', + ], + 'module' => [ + 'type' => Type::string(), + 'description' => 'module', + ], + 'type' => [ + 'type' => Type::string(), + 'description' => 'type', + ], + 'height' => [ + 'type' => Type::int(), + 'description' => 'height', + ], + 'width' => [ + 'type' => Type::int(), + 'description' => 'width', + ], + 'name' => [ + 'type' => Type::string(), + 'description' => 'name', + ], + 'cut' => [ + 'type' => Type::boolean(), + 'description' => 'cut', + ], + 'crop' => [ + 'type' => Type::boolean(), + 'description' => 'crop', + ], + 'addBorder' => [ + 'type' => Type::boolean(), + 'description' => 'addBorder', + ], + 'fileId' => [ + 'type' => Type::int(), + 'description' => 'Шаблон изображения', + ], + 'border_top' => [ + 'type' => Type::int(), + 'description' => 'отступы для окна внутри шаблона (сверху)', + ], + 'border_right' => [ + 'type' => Type::int(), + 'description' => 'тступы для окна внутри шаблона (справа)', + ], + 'border_left' => [ + 'type' => Type::int(), + 'description' => 'отступы для окна внутри шаблона (слева)', + ], + 'border_bottom' => [ + 'type' => Type::int(), + 'description' => 'отступы для окна внутри шаблона (снизу)', + ], + 'quality' => [ + 'type' => Type::int(), + 'description' => 'качество (степень сжатия)', + ], + 'fileObj' => [ + 'type' => Types::fileTemplate(), + 'description' => 'объект файла', + 'resolve' => function($root, $args) { + return $root->file; + } + ], + ]; + } + ]; + + parent::__construct($config); + } + +} \ No newline at end of file diff --git a/schema/FileTemplateType.php b/schema/FileTemplateType.php new file mode 100644 index 0000000..56519be --- /dev/null +++ b/schema/FileTemplateType.php @@ -0,0 +1,57 @@ + function() { + return [ + 'id' => [ + 'type' => Type::int(), + 'description' => 'Id', + ], + 'description' => [ + 'type' => Type::string(), + 'description' => 'Описание', + ], + 'originalName' => [ + 'type' => Type::string(), + 'description' => 'Название файла при загрузке', + ], + 'ext' => [ + 'type' => Type::string(), + 'description' => 'ext', + ], + 'fileSize' => [ + 'type' => Type::int(), + 'description' => 'fileSize', + ], + 'file' => [ + 'type' => Type::string(), + 'description' => 'Путь к файлу', + 'resolve' => function($root, $args) { + return File::getPathFull($root->id); + } + ], + 'size' => [ + 'type' => Type::string(), + 'description' => 'Размер файла', + 'resolve' => function($root, $args) { + return $root->size; + } + ], + ]; + } + ]; + + parent::__construct($config); + } + +} \ No newline at end of file diff --git a/schema/FileType.php b/schema/FileType.php new file mode 100644 index 0000000..550b136 --- /dev/null +++ b/schema/FileType.php @@ -0,0 +1,64 @@ + function() { + return [ + 'id' => [ + 'type' => Type::int(), + 'description' => 'Id', + ], + 'description' => [ + 'type' => Type::string(), + 'description' => 'Описание', + ], + 'originalName' => [ + 'type' => Type::string(), + 'description' => 'Название файла при загрузке', + ], + 'ext' => [ + 'type' => Type::string(), + 'description' => 'ext', + ], + 'fileSize' => [ + 'type' => Type::int(), + 'description' => 'fileSize', + ], + 'file' => [ + 'type' => Type::string(), + 'description' => 'Путь к файлу', + 'args' => [ + 'type' => [ + 'type' => Type::string(), + 'description' => "Тип миниатюры ('snippet', 'small', 'medium', 'large', 'landing', 'adv1080') по умолчанию нет", + ], + ], + 'resolve' => function($root, $args) { + $type = isset($args['type']) ? $args['type'] : null; + return File::getPathFull($root->id, $type); + } + ], + 'size' => [ + 'type' => Type::string(), + 'description' => 'Размер файла', + 'resolve' => function($root, $args) { + return $root->size; + } + ], + ]; + } + ]; + + parent::__construct($config); + } + +} \ No newline at end of file diff --git a/schema/FileTypes.php b/schema/FileTypes.php new file mode 100644 index 0000000..6c8cf75 --- /dev/null +++ b/schema/FileTypes.php @@ -0,0 +1,36 @@ +