Skip to content

feat: init badges modules #352

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 2 commits into from
May 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ runs:
- name: 🐘 Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.2"
php-version: "8.3"
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_mysql, bcmath, soap, intl, gd, exif, iconv, imagick
tools: composer:v2
coverage: none
Expand All @@ -21,7 +21,7 @@ runs:
shell: sh
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache dependencies
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }}
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/update-changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ on:
jobs:
update:
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- name: Checkout code
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ composer.phar
/public/hot
/public/storage
/public/media
public/css/
public/js/
/public/**/*.xml
/storage/*.key
/storage/framework/cache
Expand Down
37 changes: 37 additions & 0 deletions app-modules/gamify/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "laravelcm/gamify",
"description": "Module laravelcm/gamify for Laravel.cm",
"type": "library",
"version": "1.1.0",
"license": "proprietary",
"require": {
"filament/filament": "^3.2"
},
"require-dev": {
"pestphp/pest": "^2.32",
"pestphp/pest-plugin-laravel": "^2.1"
},
"autoload": {
"psr-4": {
"Laravelcm\\Gamify\\": "src/",
"Laravelcm\\Gamify\\Database\\Factories\\": "database/factories/",
"Laravelcm\\Gamify\\Database\\Seeders\\": "database/seeders/"
},
"files": [
"src/helpers.php"
]
},
"autoload-dev": {
"psr-4": {
"Laravelcm\\Gamify\\Tests\\": "tests/"
}
},
"minimum-stability": "stable",
"extra": {
"laravel": {
"providers": [
"Laravelcm\\Gamify\\Providers\\GamifyServiceProvider"
]
}
}
}
20 changes: 20 additions & 0 deletions app-modules/gamify/config/gamify.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

use App\Models\User;
use Laravelcm\Gamify\Models\Reputation;

return [

'payee_model' => User::class,

'reputation_model' => Reputation::class,

'allow_reputation_duplicate' => true,

'broadcast_on_private_channel' => true,

'channel_name' => 'user.reputation.',

];
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,10 @@ public function up(): void
$table->text('meta')->nullable();
$table->timestamps();
});

Schema::create('badges', function (Blueprint $table): void {
$table->id();
$table->string('name');
$table->string('description')->nullable();
$table->string('icon')->nullable();
$table->tinyInteger('level')->default(config('gamify.badge_default_level', 1));
$table->timestamps();
});

// user_badges pivot
Schema::create('user_badges', function (Blueprint $table): void {
$table->primary(['user_id', 'badge_id']);
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('badge_id');
$table->timestamps();
});
}

public function down(): void
{
Schema::dropIfExists('user_badges');
Schema::dropIfExists('badges');
Schema::dropIfExists('reputations');
}
}
Empty file.
49 changes: 49 additions & 0 deletions app-modules/gamify/src/Console/MakePointCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace Laravelcm\Gamify\Console;

use Illuminate\Console\GeneratorCommand;

final class MakePointCommand extends GeneratorCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'gamify:point {name}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Create a Gamify point type class.';

/**
* The type of class being generated.
*
* @var string
*/
protected $type = 'Point';

/**
* Get the stub file for the generator.
*/
protected function getStub(): string
{
return __DIR__.'/stubs/point.stub';
}

/**
* Get the default namespace for the class.
*
* @param string $rootNamespace The root namespace
*/
protected function getDefaultNamespace($rootNamespace): string
{
return $rootNamespace.'\Gamify\Points';
}
}
38 changes: 38 additions & 0 deletions app-modules/gamify/src/Console/stubs/point.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace DummyNamespace;

use App\Models\User;
use Laravelcm\Gamify\PointType;

final class DummyClass extends PointType
{
/**
* Number of points
*
* @var int
*/
public int $points = 20;

/**
* Point constructor
*
* @param mixed $subject
*/
public function __construct(mixed $subject)
{
$this->subject = $subject;
}

/**
* User who will be receive points
*
* @return mixed
*/
public function payee(): ?User
{
return $this->getSubject()->user;
}
}
13 changes: 13 additions & 0 deletions app-modules/gamify/src/Exceptions/InvalidPayeeModelException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Laravelcm\Gamify\Exceptions;

final class InvalidPayeeModelException extends \Exception
{
public function __construct()
{
parent::__construct('payee() method must return a model which will get the points.');
}
}
15 changes: 15 additions & 0 deletions app-modules/gamify/src/Exceptions/PointSubjectNotSetException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Laravelcm\Gamify\Exceptions;

use Exception;

final class PointSubjectNotSetException extends Exception
{
public function __construct()
{
parent::__construct('Initialize $subject field in constructor.');
}
}
15 changes: 15 additions & 0 deletions app-modules/gamify/src/Exceptions/PointsNotDefinedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Laravelcm\Gamify\Exceptions;

use Exception;

final class PointsNotDefinedException extends Exception
{
public function __construct()
{
parent::__construct('You must define a $points field or a getPoints() method.');
}
}
52 changes: 52 additions & 0 deletions app-modules/gamify/src/Models/Reputation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace Laravelcm\Gamify\Models;

use App\Models\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;

/**
* @property-read int $id
* @property-read int $point
* @property-read User payee
* @property-read Carbon $created_at
* @property-read Carbon $updated_at
*/
final class Reputation extends Model
{
protected $guarded = [];

/**
* @return BelongsTo<User, $this>
*/
public function payee(): BelongsTo
{
return $this->belongsTo(config('gamify.payee_model'), 'payee_id');
}

/**
* Get the owning subject model
*/
public function subject(): MorphTo
{
return $this->morphTo();
}

/**
* Undo last point
*
* @throws \Exception
*/
public function undo(): void
{
if ($this->exists) {
$this->payee->reducePoint($this->point);
$this->delete();
}
}
}
Loading
Loading