diff --git a/app/Http/Controllers/Api/Forms/FormsController.php b/app/Http/Controllers/Api/Forms/FormsController.php index 1865dfe..f9172bb 100644 --- a/app/Http/Controllers/Api/Forms/FormsController.php +++ b/app/Http/Controllers/Api/Forms/FormsController.php @@ -54,6 +54,10 @@ class FormsController extends Controller { return FormsService::getService('feedback-form-support')->save($request->all()); } + public function saveQrCodeForm(Request $request): ?JsonResponse { + return FormsService::getService('QrCode')->save($request->all()); + } + public function filters(Request $request, $type) { diff --git a/app/Models/QrCodes/ColorType.php b/app/Models/QrCodes/ColorType.php new file mode 100644 index 0000000..3a2d541 --- /dev/null +++ b/app/Models/QrCodes/ColorType.php @@ -0,0 +1,14 @@ + 'Сплошной', + self::SVG => 'Градиент' + ]; +} \ No newline at end of file diff --git a/app/Models/QrCodes/QrCode.php b/app/Models/QrCodes/QrCode.php new file mode 100644 index 0000000..ff87237 --- /dev/null +++ b/app/Models/QrCodes/QrCode.php @@ -0,0 +1,56 @@ +belongsTo(Asset::class); + } + + public function document(): BelongsTo { + return $this->belongsTo(Asset::class); + } + + public function getParsedFormatAttribute(): array { + return ['name' => $this->format, 'title' => QrCodeFormat::TITLES[$this->format] ?? null]; + } + + public function setImage($val) { + $asset = Asset::byUuid($val)->first(); + $this->update(['image_id' => $asset->id ?? null]); + } + public function setDocument($val) { + $asset = Asset::byUuid($val)->first(); + $this->update(['document_id' => $asset->id ?? null]); + } +} \ No newline at end of file diff --git a/app/Models/QrCodes/QrCodeFormat.php b/app/Models/QrCodes/QrCodeFormat.php new file mode 100644 index 0000000..39d1238 --- /dev/null +++ b/app/Models/QrCodes/QrCodeFormat.php @@ -0,0 +1,16 @@ + '*.png', + self::EPS => '*.eps', + self::SVG => '*.svg' + ]; +} \ No newline at end of file diff --git a/app/Services/Forms/FormsService.php b/app/Services/Forms/FormsService.php index 4026b6d..56ba966 100644 --- a/app/Services/Forms/FormsService.php +++ b/app/Services/Forms/FormsService.php @@ -8,6 +8,7 @@ use App\Services\Forms\Companies\CompanyFormsServices; use App\Services\Forms\Feedback\FeedbackFormsServices; use App\Services\Forms\Pages\PageFormsServices; use App\Services\Forms\Publications\PublicationFormsServices; +use App\Services\Forms\QrCode\QrCodeFormsServices; use App\Services\Forms\Registries\RegistryFormsServices; use App\Services\Forms\Users\UserFormsServices; @@ -23,7 +24,8 @@ class FormsService { FeedbackFormsServices::class, AdvisoryFormsServices::class, CompanyFormsServices::class, - ApplicationFormsServices::class + ApplicationFormsServices::class, + QrCodeFormsServices::class ]; public function __construct() { diff --git a/app/Services/Forms/QrCode/QrCodeForms.php b/app/Services/Forms/QrCode/QrCodeForms.php new file mode 100644 index 0000000..6f9de55 --- /dev/null +++ b/app/Services/Forms/QrCode/QrCodeForms.php @@ -0,0 +1,140 @@ + '', 'update' => '']; + + public function form(?string $id = null, array $data = []): array { + $model = QrCode::byUuid($id)->first(); + $groups = [ + ['name' => 'common', 'fields' => $this->commonGroupFields($model)] + ]; + return ['title' => $this->formTitle($model), 'data' => $groups]; + } + + public function commonGroupFields(?QrCode $model): array { + $fields = [ + [ + 'name' => 'format', + 'title' => 'Формат документа', + 'type' => FieldType::RELATION, + 'appearance' => 'radio', + 'options' => $this->getRelationItems(QrCodeFormat::TITLES), + ], + [ + 'name' => 'color_type', + 'title' => 'Тип заливки', + 'type' => FieldType::RELATION, + 'appearance' => 'radio', + 'options' => $this->getRelationItems(ColorType::TITLES), + ], + [ + 'name' => 'custom_eye_color', + 'title' => 'Цвет меток', + 'type' => FieldType::BOOLEAN, + ], + [ + 'name' => 'text', + 'title' => 'Текст', + 'type' => FieldType::TEXT, + 'required' => true, + ], + [ + 'name' => 'size', + 'title' => 'Размер', + 'type' => FieldType::INTEGER, + ], + [ + 'name' => 'red', + 'title' => 'Красный', + 'type' => FieldType::INTEGER, + ], [ + 'name' => 'green', + 'title' => 'Зеленый', + 'type' => FieldType::INTEGER, + ], [ + 'name' => 'blue', + 'title' => 'Синий', + 'type' => FieldType::INTEGER, + ], + [ + 'name' => 'bg_red', + 'title' => 'Фон красный', + 'type' => FieldType::INTEGER, + ], + [ + 'name' => 'bg_green', + 'title' => 'Фон зеленый', + 'type' => FieldType::INTEGER, + ], [ + 'name' => 'bg_blue', + 'title' => 'Фон синий', + 'type' => FieldType::INTEGER, + ], + [ + 'name' => 'margin', + 'title' => 'Отступы', + 'type' => FieldType::INTEGER, + 'value' => $model->margin ?? null + ], + [ + 'name' => 'image', + 'title' => 'Изображение', + 'type' => FieldType::IMAGE, + 'value' => ($model->image ?? null) ? fractal($model->image, new AssetTransformer()) : null + ], + + ]; + return ['data' => $fields]; + } + + public function store(array $data): JsonResponse { + $model = QrCode::create(); + $this->updateData($model, $data); + return fractal($model, new QrCodeTransformer())->respond(201); + } + + public function updateData(QrCode $model, $data) { + $model->update(collect($data)->only('text', 'format', 'size', 'color', 'bg_color', 'margin')->all()); + $data['document'] = $this->generate($data); + $model->setImage($data['image'] ?? null); + $model->setDocument($data['document'] ?? null); + } + + public function generate($data){ + $path = Storage::path((new QrCodeService)->makeFilePath($data['format'])); + $QrCode = QR::errorCorrection('H')->format($data['format'])->size($data['size'])->backgroundColor($data['bg_red'], $data['bg_green'], $data['bg_blue']); + if ($data['image'] != null) $QrCode->merge(Storage::path($data['image']->path), .27, true); + if ($data['color_type'] == 'gradient'){ + $QrCode->gradient($data['red'], $data['green'], $data['blue'], 255,255,255, 'vertical'); + } + if ($data['color_type'] == 'gradient'){ + $QrCode->gradient($data['red'], $data['green'], $data['blue'], 255,255,255, 'vertical'); + } + else $QrCode->color($data['red'],$data['green'],$data['blue']); + if ($data['custom_eye_color']) { + $QrCode->eyeColor(0, $data['red'], $data['green'], $data['blue'], $data['red'], $data['green'], $data['blue']); + $QrCode->eyeColor(1, $data['red'], $data['green'], $data['blue'], $data['red'], $data['green'], $data['blue']); + $QrCode->eyeColor(2, $data['red'], $data['green'], $data['blue'], $data['red'], $data['green'], $data['blue']); + } + $QrCode->style('square'); + $QrCode->eye('square'); + $QrCode->generate($data['text'],$path); + return (new QrCodeService)->makeAsset($path,null); + } +} \ No newline at end of file diff --git a/app/Services/Forms/QrCode/QrCodeFormsServices.php b/app/Services/Forms/QrCode/QrCodeFormsServices.php new file mode 100644 index 0000000..4bae3a0 --- /dev/null +++ b/app/Services/Forms/QrCode/QrCodeFormsServices.php @@ -0,0 +1,10 @@ + QrCodeForms::class + ]; +} \ No newline at end of file diff --git a/app/Services/QrCodeService.php b/app/Services/QrCodeService.php new file mode 100644 index 0000000..ca852eb --- /dev/null +++ b/app/Services/QrCodeService.php @@ -0,0 +1,22 @@ +makeAsset($path, $name); + } +} \ No newline at end of file diff --git a/app/Transformers/QrCodes/QrCodeTransformer.php b/app/Transformers/QrCodes/QrCodeTransformer.php new file mode 100644 index 0000000..7e1e857 --- /dev/null +++ b/app/Transformers/QrCodes/QrCodeTransformer.php @@ -0,0 +1,36 @@ + $model->uuid, + 'format' => $model->parsedFormat, + 'text' => $model->text, + 'size' => $model->size, + 'color' => $model->color, + 'bg_color' => $model->bg_color, + 'margin' => $model->phone + ]; + } + + public function includeImage(QrCode $model): ?Item { + return $model->image ? $this->item($model->image, new AssetTransformer()) : null; + } + + public function includeDocument(QrCode $model): ?Item { + return $model->document ? $this->item($model->document, new AssetTransformer()) : null; + } +} \ No newline at end of file diff --git a/composer.json b/composer.json index 2954d8c..2bcec97 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,8 @@ "seyyedam7/laravel-html-parser": "^3.1", "spatie/laravel-fractal": "^5.8", "spatie/laravel-permission": "^3.17", - "tomlerendu/laravel-convert-case-middleware": "^1.1" + "tomlerendu/laravel-convert-case-middleware": "^1.1", + "simplesoftwareio/simple-qrcode": "~4" }, "require-dev": { "brianium/paratest": "^6.2", diff --git a/config/app.php b/config/app.php index 9db439b..46fecd3 100644 --- a/config/app.php +++ b/config/app.php @@ -151,6 +151,7 @@ return [ App\Providers\MessengerServiceProvider::class, App\Providers\RouteServiceProvider::class, Barryvdh\DomPDF\ServiceProvider::class, + SimpleSoftwareIO\QrCode\QrCodeServiceProvider::class ], /* |-------------------------------------------------------------------------- @@ -199,5 +200,6 @@ return [ 'Validator' => Illuminate\Support\Facades\Validator::class, 'View' => Illuminate\Support\Facades\View::class, 'PDF' => Barryvdh\DomPDF\Facade::class, + 'QrCode' => SimpleSoftwareIO\QrCode\Facades\QrCode::class ], ]; diff --git a/database/migrations/2024_07_18_120607_create_qr_codes_table.php b/database/migrations/2024_07_18_120607_create_qr_codes_table.php new file mode 100644 index 0000000..c2fe98d --- /dev/null +++ b/database/migrations/2024_07_18_120607_create_qr_codes_table.php @@ -0,0 +1,41 @@ +id(); + $table->char('uuid', 36)->index()->unique(); + $table->string('text')->nullable()->index(); + $table->string('format')->nullable()->index(); + $table->integer('size')->nullable()->index(); + $table->string('color')->nullable()->index(); + $table->string('bg_color')->nullable()->index(); + $table->integer('margin')->nullable()->index(); + $table->integer('image_id')->nullable(); + $table->integer('document_id')->nullable(); + $table->timestamps(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('qr_codes'); + } +} diff --git a/routes/api.php b/routes/api.php index daa7f14..3c45187 100644 --- a/routes/api.php +++ b/routes/api.php @@ -78,6 +78,7 @@ Route::group(['prefix' => 'registries'], function() { Route::group(['prefix' => 'forms'], function() { Route::get('/object/feedback-form-support', 'Api\Forms\FormsController@getFeedbackFormSupport'); Route::post('/model/feedback-form-support', 'Api\Forms\FormsController@saveFeedbackFormSupport'); + Route::post('/model/QrCode', 'Api\Forms\FormsController@saveQrCodeForm'); Route::group(['middleware' => ['auth:api']], function() { Route::get('/{target}/{type?}/{id?}', 'Api\Forms\FormsController@get'); Route::post('/{target}/{type?}/{id?}', 'Api\Forms\FormsController@save');