Skip to content

Commit d67b20b

Browse files
authored
Merge pull request laravel#14 from Artisans-PXM/templates
Templates
2 parents df98494 + 7ea0fb8 commit d67b20b

14 files changed

+441
-39
lines changed

app/Enums/PermissionEnum.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ enum PermissionEnum: int
1717
case CURRENCIES = 3;
1818
case HIERARCHIES = 4;
1919
case PRICE_BOOKS = 5;
20+
case TEMPLATES = 6;
2021

2122
public static function getFeatureGates(): Collection
2223
{
@@ -52,7 +53,7 @@ private static function generateAction(string $action, string $for): string
5253

5354
// Ref: if action is create, update or delete then the return value is `create-locale`, `delete-locale` or `update-locale`
5455
return Str::of($action)
55-
->append('-', Str::of($for)->title()->value())
56+
->append('-', Str::title($for))
5657
->slug()
5758
->value();
5859
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Http\Controllers\Api;
6+
7+
use App\Http\Controllers\Controller;
8+
use App\Http\Requests\Api\TemplateRequest;
9+
use App\Http\Resources\Api\TemplateResource;
10+
use App\Queries\TemplateQueries;
11+
use Illuminate\Http\JsonResponse;
12+
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
13+
14+
class TemplateController extends Controller
15+
{
16+
public function __construct(
17+
protected TemplateQueries $templateQueries
18+
) {
19+
20+
}
21+
22+
public function fetch(): AnonymousResourceCollection
23+
{
24+
$templates = $this->templateQueries->listQuery();
25+
26+
return TemplateResource::collection($templates->getCollection());
27+
}
28+
29+
public function create(TemplateRequest $request): JsonResponse
30+
{
31+
$validatedData = $request->validated();
32+
33+
$this->templateQueries->create($validatedData);
34+
35+
return response()->json([
36+
'success' => __('Template created successfully.'),
37+
]);
38+
}
39+
40+
public function delete(string $id): JsonResponse
41+
{
42+
$this->templateQueries->delete($id);
43+
44+
return response()->json([
45+
'success' => __('Template deleted successfully.'),
46+
]);
47+
}
48+
49+
public function update(TemplateRequest $request, string $id): JsonResponse
50+
{
51+
$validatedData = $request->validated();
52+
53+
$this->templateQueries->update($validatedData, $id);
54+
55+
return response()->json([
56+
'success' => __('Template updated successfully.'),
57+
]);
58+
}
59+
}
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Http\Requests\Api;
6+
7+
use Illuminate\Contracts\Validation\ValidationRule;
8+
use Illuminate\Foundation\Http\FormRequest;
9+
use Illuminate\Support\Str;
10+
11+
class TemplateRequest extends FormRequest
12+
{
13+
/**
14+
* Get the validation rules that apply to the request.
15+
*
16+
* @return array<string, (ValidationRule | array<int, string> | string)>
17+
*/
18+
public function rules(): array
19+
{
20+
return [
21+
'name' => ['required', 'string'],
22+
'description' => ['nullable', 'string'],
23+
'slug' => ['sometimes'],
24+
];
25+
}
26+
27+
/**
28+
* @param array<int, string>|int|string|null $key
29+
* @return array<string, mixed>
30+
*/
31+
public function validated($key = null, $default = null): array
32+
{
33+
return array_merge(parent::validated(), [
34+
'slug' => Str::slug($this->slug),
35+
]);
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Http\Resources\Api;
6+
7+
use Illuminate\Http\Request;
8+
use Illuminate\Http\Resources\Json\JsonResource;
9+
10+
class TemplateResource extends JsonResource
11+
{
12+
/**
13+
* Transform the resource into an array.
14+
*
15+
* @return array<string, mixed>
16+
*/
17+
public function toArray(Request $request): array
18+
{
19+
$template = $this->resource;
20+
21+
return [
22+
'id' => $template->id,
23+
'name' => $template->name,
24+
'description' => $template->description,
25+
];
26+
}
27+
}

app/Models/Template.php

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Models;
6+
7+
use Illuminate\Database\Eloquent\Concerns\HasUuids;
8+
use Illuminate\Database\Eloquent\Factories\HasFactory;
9+
use Illuminate\Database\Eloquent\Model;
10+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
11+
use Spatie\Sluggable\HasSlug;
12+
use Spatie\Sluggable\SlugOptions;
13+
14+
class Template extends Model
15+
{
16+
use HasFactory;
17+
use HasUuids;
18+
use HasSlug;
19+
20+
/**
21+
* The attributes that are mass assignable.
22+
*
23+
* @var array<int, string>
24+
*/
25+
protected $fillable = ['company_id', 'name', 'description', 'slug'];
26+
27+
/**
28+
* Get the options for generating the slug.
29+
*/
30+
public function getSlugOptions(): SlugOptions
31+
{
32+
return SlugOptions::create()
33+
->generateSlugsFrom('name')
34+
->saveSlugsTo('slug')
35+
->preventOverwrite();
36+
}
37+
38+
public function company(): BelongsTo
39+
{
40+
return $this->belongsTo(Company::class);
41+
}
42+
}

app/Queries/TemplateQueries.php

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Queries;
6+
7+
use App\Models\Template;
8+
use Illuminate\Pagination\LengthAwarePaginator;
9+
use Spatie\QueryBuilder\QueryBuilder;
10+
11+
class TemplateQueries
12+
{
13+
public function listQuery(): LengthAwarePaginator
14+
{
15+
return QueryBuilder::for(Template::class)
16+
->allowedFields(['id', 'name', 'description'])
17+
->defaultSort('-id')
18+
->allowedSorts(['id', 'name'])
19+
->jsonPaginate();
20+
}
21+
22+
/**
23+
* @param array<string, string> $data
24+
*/
25+
public function create(array $data): void
26+
{
27+
$data['company_id'] ??= app('company_id');
28+
29+
Template::create($data);
30+
}
31+
32+
public function delete(string $id): void
33+
{
34+
Template::query()
35+
->where('company_id', app('company_id'))
36+
->where('id', $id)
37+
->delete();
38+
}
39+
40+
/**
41+
* @param array<string, string> $data
42+
*/
43+
public function update(array $data, string $id): void
44+
{
45+
$data['company_id'] ??= app('company_id');
46+
47+
Template::query()
48+
->where('company_id', app('company_id'))
49+
->where('id', $id)
50+
->update($data);
51+
}
52+
}
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Database\Factories;
6+
7+
use App\Models\Template;
8+
use Illuminate\Database\Eloquent\Collection;
9+
use Illuminate\Database\Eloquent\Model;
10+
use App\Models\Company;
11+
use Illuminate\Database\Eloquent\Factories\Factory;
12+
13+
/**
14+
* @extends Factory<Template>
15+
*/
16+
class TemplateFactory extends Factory
17+
{
18+
/**
19+
* Define the model's default state.
20+
*
21+
* @return array<string, mixed>
22+
*/
23+
public function definition(): array
24+
{
25+
return [
26+
'company_id' => fn (): Collection|Model => Company::factory()->create(),
27+
'name' => fake()->word(),
28+
'description' => fake()->sentence(),
29+
];
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use App\Models\Company;
6+
use Illuminate\Database\Migrations\Migration;
7+
use Illuminate\Database\Schema\Blueprint;
8+
use Illuminate\Support\Facades\Schema;
9+
10+
return new class extends Migration {
11+
/**
12+
* Run the migrations.
13+
*/
14+
public function up(): void
15+
{
16+
Schema::create('templates', function (Blueprint $table): void {
17+
$table->uuid('id')->primary();
18+
$table->foreignIdFor(Company::class, 'company_id')->constrained('companies');
19+
$table->string('name');
20+
$table->longText('description')->nullable();
21+
$table->string('slug');
22+
$table->timestamps();
23+
});
24+
}
25+
26+
/**
27+
* Reverse the migrations.
28+
*/
29+
public function down(): void
30+
{
31+
Schema::dropIfExists('templates');
32+
}
33+
};

database/seeders/DatabaseSeeder.php

+28-36
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66

77
use App\Models\Company;
88
use App\Models\User;
9-
use Illuminate\Console\Command;
9+
use Database\Factories\CompanyFactory;
1010
use Illuminate\Console\View\Components\Factory;
11+
use Illuminate\Console\View\Components\TwoColumnDetail;
1112

1213
class DatabaseSeeder extends GenerateCsvDataSeeder
1314
{
@@ -18,53 +19,44 @@ public function run(): void
1819
{
1920
$time = microtime(true);
2021

21-
$this->command->warn('Creating companies...');
22-
Company::factory(2)->create();
23-
$this->command->info('Companies created.');
22+
$this->fakerCompanySeeding();
2423

2524
$companyMinimumId = Company::min('id');
2625

27-
$this->command->warn(PHP_EOL.'Creating users...');
28-
29-
$success = $this->seedDataFromCsvFile(database_path('/seeders/csv/users.csv'));
30-
if ($success === Command::SUCCESS) {
31-
$this->command->info('Users created.');
32-
}
26+
$this->seedDataFromCsvFile(database_path('/seeders/csv/users.csv'));
3327

34-
$this->command->warn(PHP_EOL.'Creating roles');
35-
$success = $this->seedDataFromCsvFile(database_path('/seeders/csv/roles.csv'));
36-
if ($success === Command::SUCCESS) {
37-
$this->command->info('Roles created.');
38-
}
28+
$this->seedDataFromCsvFile(database_path('/seeders/csv/roles.csv'));
3929

4030
User::cursor()->each(function (User $user): void {
4131
$user->assignRole(['Super Admin']);
4232
$user->companies()->attach(Company::min('id'), ['created_at' => now(), 'updated_at' => now()]);
4333
});
4434

45-
$this->command->warn(PHP_EOL.'Creating Locales...');
46-
$success = $this->seedDataFromCsvFile(database_path('/seeders/csv/locales.csv'), companyId: $companyMinimumId);
47-
if ($success === Command::SUCCESS) {
48-
$this->command->info('Locales created.');
49-
}
50-
51-
$this->command->warn(PHP_EOL.'Creating Currencies...');
52-
$success = $this->seedDataFromCsvFile(database_path('/seeders/csv/currencies.csv'), companyId: $companyMinimumId);
53-
if ($success === Command::SUCCESS) {
54-
$this->command->info('Currencies created.');
55-
}
56-
57-
$this->command->warn(PHP_EOL.'Creating Price books...');
58-
$success = $this->seedDataFromCsvFile(database_path('/seeders/csv/price_books.csv'), companyId: $companyMinimumId);
59-
if ($success === Command::SUCCESS) {
60-
$this->command->info('Currencies created.');
61-
}
62-
63-
$this->command->newLine();
35+
$this->seedDataFromCsvFile(database_path('/seeders/csv/locales.csv'), companyId: $companyMinimumId);
36+
37+
$this->seedDataFromCsvFile(database_path('/seeders/csv/currencies.csv'), companyId: $companyMinimumId);
38+
39+
$this->seedDataFromCsvFile(database_path('/seeders/csv/price_books.csv'), companyId: $companyMinimumId);
40+
6441
$this->call(HierarchySeeder::class, parameters: ['companyId' => $companyMinimumId]);
6542

66-
$secs = microtime(true) - $time;
43+
$this->seedDataFromCsvFile(database_path('/seeders/csv/templates.csv'), companyId: $companyMinimumId);
44+
6745
app()->make(Factory::class, ['output' => $this->command->getOutput()])
68-
->info('All this took '.round($secs * 1000).'ms');
46+
->info('All this took '.number_format((microtime(true) - $time) * 1000, 2).' ms');
47+
}
48+
49+
private function fakerCompanySeeding(): void
50+
{
51+
with(new TwoColumnDetail($this->command->getOutput()))->render(CompanyFactory::class, '<fg=yellow;options=bold>RUNNING</>');
52+
53+
$startTime = microtime(true);
54+
55+
Company::factory(2)->create();
56+
57+
$runTime = number_format((microtime(true) - $startTime) * 1000, 2);
58+
59+
with(new TwoColumnDetail($this->command->getOutput()))->render(CompanyFactory::class, sprintf('<fg=gray>%s ms</> <fg=green;options=bold>DONE</>', $runTime));
60+
$this->command->getOutput()->writeln('');
6961
}
7062
}

0 commit comments

Comments
 (0)