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 1 commit
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