Skip to content

Commit 5cb1a51

Browse files
committed
transfer
1 parent 73fdeda commit 5cb1a51

36 files changed

+849
-127
lines changed

composer.json

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
{
2-
"name": "yuges-code/laravel-package-template",
3-
"description": "🚀 Starter template for all Yuges Laravel packages",
2+
"name": "yuges-code/laravel-reactable",
3+
"description": "👍 Package for easily attaching reactions to Laravel eloquent models",
44
"keywords": [
55
"php",
66
"yuges",
77
"laravel",
88
"package",
9-
"template"
9+
"template",
10+
"reaction",
11+
"reactable"
1012
],
11-
"homepage": "https://yuges-code.github.io/laravel-package-template",
13+
"homepage": "https://yuges-code.github.io/laravel-reactable",
1214
"support": {
13-
"source": "https://github.com/yuges-code/laravel-package-template",
14-
"issues": "https://github.com/yuges-code/laravel-package-template/issues"
15+
"source": "https://github.com/yuges-code/laravel-reactable",
16+
"issues": "https://github.com/yuges-code/laravel-reactable/issues"
1517
},
1618
"license": "MIT",
1719
"authors": [
@@ -30,14 +32,14 @@
3032
},
3133
"autoload": {
3234
"psr-4": {
33-
"Yuges\\LaravelPackageTemplate\\": "src",
34-
"Yuges\\LaravelPackageTemplate\\Database\\Seeders\\": "database/seeders/",
35-
"Yuges\\LaravelPackageTemplate\\Database\\Factories\\": "database/factories/"
35+
"Yuges\\Reactable\\": "src",
36+
"Yuges\\Reactable\\Database\\Seeders\\": "database/seeders/",
37+
"Yuges\\Reactable\\Database\\Factories\\": "database/factories/"
3638
}
3739
},
3840
"autoload-dev": {
3941
"psr-4": {
40-
"Yuges\\Package\\Tests\\": "tests/src"
42+
"Yuges\\Reactable\\Tests\\": "tests/src"
4143
}
4244
},
4345
"scripts": {
@@ -46,7 +48,7 @@
4648
"extra": {
4749
"laravel": {
4850
"providers": [
49-
"Yuges\\LaravelPackageTemplate\\Providers\\TemplateServiceProvider"
51+
"Yuges\\Reactable\\Providers\\ReactableServiceProvider"
5052
]
5153
}
5254
},

config/reactable.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
return [
4+
/*
5+
* FQCN (Fully Qualified Class Name) of the models to use for comments
6+
*/
7+
'models' => [
8+
'reaction' => [
9+
'default' => Yuges\Reactable\Models\Reaction::class,
10+
'type' => Yuges\Reactable\Models\ReactionType::class,
11+
],
12+
'reactor' => [
13+
'default' => \App\Models\User::class,
14+
'allowed' => [
15+
\App\Models\User::class,
16+
],
17+
],
18+
],
19+
20+
'types' => Yuges\Reactable\Enums\ReactionType::class,
21+
'icons' => Yuges\Reactable\Enums\ReactionIcon::class,
22+
'weights' => Yuges\Reactable\Enums\ReactionWeight::class,
23+
24+
'permissions' => [
25+
'anonymous' => false,
26+
'duplicate' => false,
27+
],
28+
29+
'actions' => [
30+
'create' => Yuges\Reactable\Actions\CreateReactionAction::class,
31+
'toggle' => Yuges\Reactable\Actions\ToggleReactionAction::class,
32+
],
33+
];

config/template.php

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
use Yuges\Reactable\Config\Config;
4+
use Illuminate\Support\Facades\Schema;
5+
use Yuges\Reactable\Models\ReactionType;
6+
use Illuminate\Database\Schema\Blueprint;
7+
use Illuminate\Database\Migrations\Migration;
8+
9+
return new class extends Migration
10+
{
11+
public function __construct(protected string $table = 'reaction_types')
12+
{
13+
$this->$table = Config::getReactionTypeClass(ReactionType::class)::getTableName();
14+
}
15+
16+
public function up(): void
17+
{
18+
if (Schema::hasTable($this->table)) {
19+
return;
20+
}
21+
22+
Schema::create($this->table, function (Blueprint $table) {
23+
$table->id();
24+
25+
$table->string('name')->unique();
26+
$table->string('icon')->unique();
27+
$table->integer('weight');
28+
29+
$table->timestamps();
30+
});
31+
}
32+
33+
public function down(): void
34+
{
35+
Schema::dropIfExists($this->table);
36+
}
37+
};
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
use Yuges\Reactable\Config\Config;
4+
use Yuges\Reactable\Models\Reaction;
5+
use Illuminate\Support\Facades\Schema;
6+
use Yuges\Reactable\Models\ReactionType;
7+
use Illuminate\Database\Schema\Blueprint;
8+
use Illuminate\Database\Migrations\Migration;
9+
10+
return new class extends Migration
11+
{
12+
public function __construct(protected string $table = 'reactions')
13+
{
14+
$this->$table = Config::getReactionClass(Reaction::class)::getTableName();
15+
}
16+
17+
public function up(): void
18+
{
19+
if (Schema::hasTable($this->table)) {
20+
return;
21+
}
22+
23+
Schema::create($this->table, function (Blueprint $table) {
24+
$table->ulid('id')->primary();
25+
26+
Config::getPermissionsAnonymous(false)
27+
? $table->nullableMorphs('reactor')
28+
: $table->morphs('reactor');
29+
30+
$table->morphs('reactable');
31+
$table
32+
->foreignIdFor(Config::getReactionTypeClass(ReactionType::class))
33+
->constrained()
34+
->cascadeOnUpdate()
35+
->cascadeOnDelete();
36+
37+
$table->timestamps();
38+
39+
if (! Config::getPermissionsDuplicate(false)) {
40+
$table->unique([
41+
'reactor_id',
42+
'reactor_type',
43+
'reactable_id',
44+
'reactable_type',
45+
]);
46+
}
47+
});
48+
}
49+
50+
public function down(): void
51+
{
52+
Schema::dropIfExists($this->table);
53+
}
54+
};

database/migrations/create_template_table.php

Lines changed: 0 additions & 19 deletions
This file was deleted.

database/seeders/DatabaseSeeder.php

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace Database\Seeders;
4+
5+
use Illuminate\Database\Seeder;
6+
use Yuges\Reactable\Config\Config;
7+
use Yuges\Reactable\Models\ReactionType;
8+
use Yuges\Reactable\Interfaces\ReactionType as ReactionTypeEnum;
9+
10+
class ReactionTypeSeeder extends Seeder
11+
{
12+
public function run(): void
13+
{
14+
foreach (Config::getReactionTypeEnumClass()::cases() as $type) {
15+
$this->create($type);
16+
}
17+
}
18+
19+
protected function create(ReactionTypeEnum $type): ReactionType
20+
{
21+
return Config::getReactionTypeClass(ReactionType::class)::query()->updateOrCreate([
22+
'id' => $type->value,
23+
'name' => strtolower($type->name),
24+
], [
25+
'icon' => $type->icon()->value,
26+
'weight' => $type->weight()->value,
27+
]);
28+
}
29+
}

src/Actions/.gitkeep

Whitespace-only changes.
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
namespace Yuges\Reactable\Actions;
4+
5+
use Exception;
6+
use Yuges\Reactable\Config\Config;
7+
use Yuges\Reactable\Models\Reaction;
8+
use Yuges\Reactable\Interfaces\Reactor;
9+
use Illuminate\Database\Eloquent\Model;
10+
use Yuges\Reactable\Models\ReactionType;
11+
use Yuges\Reactable\Interfaces\Reactable;
12+
use Yuges\Reactable\Exceptions\InvalidReactor;
13+
use Yuges\Reactable\Interfaces\ReactionType as ReactionTypeEnum;
14+
15+
class CreateReactionAction
16+
{
17+
public function __construct(
18+
protected Reactable $reactable
19+
) {
20+
}
21+
22+
public static function create(Reactable $reactable): self
23+
{
24+
return new static($reactable);
25+
}
26+
27+
public function execute(int|string|ReactionType|ReactionTypeEnum $type, Reactor $reactor = null): Reaction
28+
{
29+
$reactor ??= $this->getDefaultReactor();
30+
31+
$this->validateReactor($reactor);
32+
33+
if (! $reactor instanceof Model) {
34+
throw new Exception('Reactor is not eloquent model');
35+
}
36+
37+
$type = $this->reactable->getReactionType($type);
38+
39+
if (! $type) {
40+
throw new Exception('Type of reaction not found');
41+
}
42+
43+
$attributes = [
44+
'reactor_id' => $reactor?->getKey() ?? null,
45+
'reactor_type' => $reactor?->getMorphClass() ?? null,
46+
'reaction_type_id' => $type->getKey(),
47+
];
48+
49+
if (Config::getPermissionsDuplicate()) {
50+
return $this->reactable->reactions()->create($attributes);
51+
}
52+
53+
$reaction = $this->reactable->reactions()->getQuery()->whereMorphedTo('reactor', $reactor)->first();
54+
55+
return $reaction ?? $this->reactable->reactions()->create($attributes);
56+
}
57+
58+
public function validateReactor(Reactor $reactor = null): void
59+
{
60+
if (! $reactor) {
61+
return;
62+
}
63+
64+
$class = get_class($reactor);
65+
$allowed = Config::getReactorAllowedClasses()->push(Config::getReactorDefaultClass());
66+
67+
if (! $allowed->contains($class)) {
68+
throw InvalidReactor::doesNotContainInAllowedConfig($class);
69+
}
70+
}
71+
72+
public function getDefaultReactor(): ?Reactor
73+
{
74+
$reactor = $this->reactable->defaultReactor();
75+
76+
if (! $reactor) {
77+
return null;
78+
}
79+
80+
$class = get_class($reactor);
81+
82+
if (Config::getReactorDefaultClass() !== $class) {
83+
throw InvalidReactor::doesNotContainInDefaultConfig($class);
84+
}
85+
86+
return $reactor;
87+
}
88+
}

0 commit comments

Comments
 (0)