From c7b75404698462a4080ffd08591ac7ebc5e6b139 Mon Sep 17 00:00:00 2001 From: Jack Kara Date: Thu, 3 Oct 2019 18:17:18 +0300 Subject: [PATCH 1/3] Test Commit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c1a4a8b..c30441d 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Use `qcod/laravel-gamify` to quickly add reputation point & badges in your L $ composer require qcod/laravel-gamify ``` -**2** - If you are installing on Laravel 5.4 or lower you will be needed to manually register Service Provider by adding it in `config/app.php` providers array. +**2** - If you are installing on Laravel 5.4 or lower you will be needed to manually register Service Provider by adding it in `config/app.php` providers array.... ```php 'providers' => [ From 9aca31fb7a1af4b4ab5131a8523ef7e74145adf1 Mon Sep 17 00:00:00 2001 From: Jack Kara Date: Fri, 4 Oct 2019 17:38:50 +0300 Subject: [PATCH 2/3] New way of badge is added --- README.md | 6 ++-- src/Badge.php | 8 ++++- src/BadgeType.php | 55 ++++++++++++++++++++++++------ src/Console/stubs/badge.stub | 2 +- src/Events/BadgeGivenEvent.php | 55 ++++++++++++++++++++++++++++++ src/Events/BadgeRemovedEvent.php | 55 ++++++++++++++++++++++++++++++ src/GamifyServiceProvider.php | 14 +++----- src/HasBadges.php | 37 ++++++++++++++------ src/Listeners/SyncBadges.php | 19 ----------- src/config/gamify.php | 5 +++ src/helpers.php | 13 +++++-- tests/Badges/FirstContribution.php | 2 +- 12 files changed, 214 insertions(+), 57 deletions(-) create mode 100644 src/Events/BadgeGivenEvent.php create mode 100644 src/Events/BadgeRemovedEvent.php delete mode 100644 src/Listeners/SyncBadges.php diff --git a/README.md b/README.md index c30441d..d1ae376 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Use `qcod/laravel-gamify` to quickly add reputation point & badges in your L $ composer require qcod/laravel-gamify ``` -**2** - If you are installing on Laravel 5.4 or lower you will be needed to manually register Service Provider by adding it in `config/app.php` providers array.... +**2** - If you are installing on Laravel 5.4 or lower you will be needed to manually register Service Provider by adding it in `config/app.php` providers array. ```php 'providers' => [ @@ -310,14 +310,14 @@ class FirstContribution extends BadgeType * @param $user * @return bool */ - public function qualifier($user) + public function islevelArchived($user) { return $user->getPoints() >= 1000; } } ``` -As you can see this badge has a `$description` field and a `qualifier($user)` method. +As you can see this badge has a `$description` field and a `islevelArchived($user)` method. Gamify package will listen for any change in reputation point and it will run the user against all the available badges and assign all the badges user is qualified. #### Change badge name diff --git a/src/Badge.php b/src/Badge.php index 36177ff..e1b95a7 100644 --- a/src/Badge.php +++ b/src/Badge.php @@ -3,6 +3,8 @@ namespace QCod\Gamify; use Illuminate\Database\Eloquent\Model; +use QCod\Gamify\Events\BadgeGivenEvent; +use QCod\Gamify\Events\BadgeRemovedEvent; class Badge extends Model { @@ -24,7 +26,9 @@ public function users() */ public function awardTo($user) { - $this->users()->attach($user); + $event = config('gamify.events.badgeGiven', 'QCod\Gamify\Events\BadgeGivenEvent'); + event(new $event($this, $user)); + $this->users()->syncWithoutDetaching($user); } /** @@ -34,6 +38,8 @@ public function awardTo($user) */ public function removeFrom($user) { + $event = config('gamify.events.badgeRemoved', 'QCod\Gamify\Events\BadgeGivenEvent'); + event(new $event($this, $user)); $this->users()->detach($user); } } diff --git a/src/BadgeType.php b/src/BadgeType.php index 9acd022..367517c 100644 --- a/src/BadgeType.php +++ b/src/BadgeType.php @@ -5,6 +5,7 @@ use Illuminate\Support\Str; use Illuminate\Support\Arr; use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Facades\Auth; abstract class BadgeType { @@ -13,11 +14,18 @@ abstract class BadgeType */ protected $model; + + /** + * @var Array + */ + public $_extraVariablesForQualify; + /** * BadgeType constructor. */ - public function __construct() + public function __construct(...$extraVariablesForQualify) { + $this->_extraVariablesForQualify = $extraVariablesForQualify; $this->model = $this->storeBadge(); } @@ -27,7 +35,7 @@ public function __construct() * @param $user * @return bool */ - abstract public function qualifier($user); + abstract public function islevelArchived($user); /** * Get name of badge @@ -65,6 +73,20 @@ public function getIcon() : $this->getDefaultIcon(); } + + /** + * Get the model for badge + * + * @return Model + */ + public function getModel($level = null) + { + if ($level) { + return $this->model[$level]; + } + return $this->model; + } + /** * Get the level for badge * @@ -92,9 +114,12 @@ public function getLevel() * * @return mixed */ - public function getBadgeId() + public function getBadgeId($level = false) { - return $this->model->getKey(); + if (!$level) { + $level = $this->getLevel(); + } + return $this->model[$level]->getKey(); } /** @@ -129,16 +154,24 @@ protected function getDefaultIcon() */ protected function storeBadge() { - $badge = app(config('gamify.badge_model')) - ->firstOrNew(['name' => $this->getName()]) + $badgeName = get_class($this); + + return cache()->tags('laravel-gamify')->rememberForever('gamify.badges.' . $badgeName, function () { + $levels = (property_exists($this, 'levels')) ? $this->levels : [$this->getLevel() => $this->getDescription()]; + $return = []; + foreach ($levels as $levelKey => $levelDescription) { + $badge = app(config('gamify.badge_model')) + ->firstOrNew(['name' => $this->getName(), 'level' => $levelKey]) ->forceFill([ - 'level' => $this->getLevel(), - 'description' => $this->getDescription(), + 'level' => $levelKey, + 'description' => $levelDescription, 'icon' => $this->getIcon() ]); - $badge->save(); - - return $badge; + $badge->save(); + $return[$levelKey] = $badge; + } + return $return; + }); } } diff --git a/src/Console/stubs/badge.stub b/src/Console/stubs/badge.stub index c21857d..4461c40 100644 --- a/src/Console/stubs/badge.stub +++ b/src/Console/stubs/badge.stub @@ -19,7 +19,7 @@ class DummyClass extends BadgeType * @param $user * @return bool */ - public function qualifier($user) + public function islevelArchived($user) { return $user->getPoints() >= 1000; } diff --git a/src/Events/BadgeGivenEvent.php b/src/Events/BadgeGivenEvent.php new file mode 100644 index 0000000..7ed8b4e --- /dev/null +++ b/src/Events/BadgeGivenEvent.php @@ -0,0 +1,55 @@ +user = $user; + $this->badge = $badge; + } + + /** + * Get the channels the event should broadcast on. + * + * @return \Illuminate\Broadcasting\Channel|\Illuminate\Broadcasting\Channel[] + */ + public function broadcastOn() + { + $channelName = config('gamify.channel_name') . $this->user->getKey(); + + if (config('gamify.broadcast_on_private_channel')) { + return new PrivateChannel($channelName); + } + + return new Channel($channelName); + } +} diff --git a/src/Events/BadgeRemovedEvent.php b/src/Events/BadgeRemovedEvent.php new file mode 100644 index 0000000..b5fc754 --- /dev/null +++ b/src/Events/BadgeRemovedEvent.php @@ -0,0 +1,55 @@ +user = $user; + $this->badge = $badge; + } + + /** + * Get the channels the event should broadcast on. + * + * @return \Illuminate\Broadcasting\Channel|\Illuminate\Broadcasting\Channel[] + */ + public function broadcastOn() + { + $channelName = config('gamify.channel_name') . $this->user->getKey(); + + if (config('gamify.broadcast_on_private_channel')) { + return new PrivateChannel($channelName); + } + + return new Channel($channelName); + } +} diff --git a/src/GamifyServiceProvider.php b/src/GamifyServiceProvider.php index af2335a..37a4342 100644 --- a/src/GamifyServiceProvider.php +++ b/src/GamifyServiceProvider.php @@ -4,7 +4,6 @@ use Illuminate\Support\Collection; use Illuminate\Support\Facades\Event; -use QCod\Gamify\Listeners\SyncBadges; use Illuminate\Support\ServiceProvider; use QCod\Gamify\Console\MakeBadgeCommand; use QCod\Gamify\Console\MakePointCommand; @@ -42,9 +41,6 @@ public function boot() MakeBadgeCommand::class, ]); } - - // register event listener - Event::listen(ReputationChanged::class, SyncBadges::class); } /** @@ -55,11 +51,11 @@ public function boot() public function register() { $this->app->singleton('badges', function () { - return cache()->rememberForever('gamify.badges.all', function () { - return $this->getBadges()->map(function ($badge) { - return new $badge; - }); + //return cache()->rememberForever('gamify.badges.all', function () { + return $this->getBadges()->map(function ($badge) { + return new $badge; }); + //}); }); } @@ -79,7 +75,7 @@ protected function getBadges() foreach (glob(app_path('/Gamify/Badges/') . '*.php') as $file) { if (is_file($file)) { - $badges[] = app($badgeRootNamespace . '\\' . pathinfo($file, PATHINFO_FILENAME)); + $badges[] = $badgeRootNamespace . '\\' . pathinfo($file, PATHINFO_FILENAME); // this was cousing double construct becouse of singleton construct again. } } diff --git a/src/HasBadges.php b/src/HasBadges.php index 6cdd50f..946553d 100644 --- a/src/HasBadges.php +++ b/src/HasBadges.php @@ -16,18 +16,35 @@ public function badges() } /** - * Sync badges for qiven user - * - * @param $user - */ - public function syncBadges($user = null) + * Give badge to user + * + * @param BadgeType $badge + * @param $preDefinedBadgeLevel int + * @return bool + */ + public function giveBadge(BadgeType $badge, $forceLevel = null) { - $user = is_null($user) ? $this : $user; + if (!is_null($forceLevel)) { + return $badge->getModel($forceLevel)->awardTo($this); + } - $badgeIds = app('badges')->filter - ->qualifier($user) - ->map->getBadgeId(); - $user->badges()->sync($badgeIds); + if (!($level = $badge->islevelArchived($this, $badge->_extraVariablesForQualify))) { + return false; + } + if (!is_numeric($level)) { + $level = config('gamify.badge_default_level', 1); + } + + return $badge->getModel($level)->awardTo($this); + } + + public function removeBadge(BadgeType $badge) + { + if (!($level = $badge->islevelArchived($this, $badge->_extraVariablesForQualify))) { + return false; + } + + return $this->model[$level]->removeBadge($this); } } diff --git a/src/Listeners/SyncBadges.php b/src/Listeners/SyncBadges.php deleted file mode 100644 index 0e38112..0000000 --- a/src/Listeners/SyncBadges.php +++ /dev/null @@ -1,19 +0,0 @@ -user->syncBadges(); - } -} diff --git a/src/config/gamify.php b/src/config/gamify.php index b40050a..355d465 100644 --- a/src/config/gamify.php +++ b/src/config/gamify.php @@ -7,6 +7,11 @@ // Reputation model 'reputation_model' => '\QCod\Gamify\Reputation', + // Event models + 'gamify.events.badgeGive' => 'QCod\Gamify\Events\BadgeGivenEvent', + 'gamify.events.removeBadge' => 'QCod\Gamify\Events\RemovedEvent', + 'gamify.events.reputationChanged' => 'QCod\Gamify\Events\ReputationChanged', + // Allow duplicate reputation points 'allow_reputation_duplicate' => true, diff --git a/src/helpers.php b/src/helpers.php index bcf390d..cba88ce 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -1,5 +1,6 @@ user(); + } + return $user->giveBadge($badge, $forceLevel = null); + } + if (!function_exists('undoPoint')) { /** @@ -55,10 +64,10 @@ function short_number($n) if ($n >= 0 && $n < 1000) { $n_format = floor($n); $suffix = ''; - } else if ($n >= 1000 && $n < 1000000) { + } elseif ($n >= 1000 && $n < 1000000) { $n_format = floor($n / 1000); $suffix = 'K+'; - } else if ($n >= 1000000 && $n < 1000000000) { + } elseif ($n >= 1000000 && $n < 1000000000) { $n_format = floor($n / 1000000); $suffix = 'M+'; } else { diff --git a/tests/Badges/FirstContribution.php b/tests/Badges/FirstContribution.php index bbbba16..a22d51c 100644 --- a/tests/Badges/FirstContribution.php +++ b/tests/Badges/FirstContribution.php @@ -20,7 +20,7 @@ class FirstContribution extends BadgeType * @param User $user * @return bool */ - public function qualifier($user) + public function islevelArchived($user) { return $user->posts()->count() == 1; } From 333108ce6658aa9badfb773ad2b0fd224cab1c62 Mon Sep 17 00:00:00 2001 From: GoldSteam Date: Thu, 5 Dec 2019 15:59:53 +0300 Subject: [PATCH 3/3] Payee Level Support --- src/PointType.php | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/PointType.php b/src/PointType.php index 2ef2c49..7ecf538 100644 --- a/src/PointType.php +++ b/src/PointType.php @@ -11,6 +11,7 @@ abstract class PointType { + /** * Subject for reputation * @@ -79,6 +80,11 @@ public function getPoints() if (!isset($this->points)) { throw new PointsNotDefined(); } + $rates = config('gamify.user_level_xp_rate', [0 => 1]); + + if (is_integer($this->payee()->level) && isset($rates[$this->payee()->level])) { + return $this->points * $rates[$this->payee()->level]; + } return $this->points; } @@ -86,7 +92,7 @@ public function getPoints() /** * Set a subject * - * @param mixed $subject + * @param mixed $subject */ public function setSubject($subject) { @@ -118,19 +124,19 @@ public function firstReputation() /** * Store a reputation in the database * - * @param array $meta + * @param array $meta * @return mixed * @throws InvalidPayeeModel */ public function storeReputation($meta = []) { return $this->payeeReputations()->create([ - 'payee_id' => $this->payee()->id, + 'payee_id' => $this->payee()->id, 'subject_type' => $this->getSubject()->getMorphClass(), - 'subject_id' => $this->getSubject()->getKey(), - 'name' => $this->getName(), - 'meta' => json_encode($meta), - 'point' => $this->getPoints() + 'subject_id' => $this->getSubject()->getKey(), + 'name' => $this->getName(), + 'meta' => json_encode($meta), + 'point' => $this->getPoints(), ]); } @@ -146,7 +152,7 @@ public function reputationQuery() ['payee_id', $this->payee()->id], ['subject_type', $this->getSubject()->getMorphClass()], ['subject_id', $this->getSubject()->getKey()], - ['name', $this->getName()] + ['name', $this->getName()], ]); }