From 3dc507b61e0ee7a0a10a3c50300fd673d49d02fd Mon Sep 17 00:00:00 2001 From: Abraham Arango Date: Thu, 12 Dec 2019 22:52:40 -0500 Subject: [PATCH 1/6] Update GamifyServiceProvider.php Make the look up of Gamifying badges be directory recursive so that it finds them no matter how deep the folder structure is. This allows developers to place badges within the `Gamify/Badges` directory in a more structured way rather than all badges right in the root of that directory. --- src/GamifyServiceProvider.php | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/GamifyServiceProvider.php b/src/GamifyServiceProvider.php index af2335a..42897a1 100644 --- a/src/GamifyServiceProvider.php +++ b/src/GamifyServiceProvider.php @@ -10,6 +10,11 @@ use QCod\Gamify\Console\MakePointCommand; use QCod\Gamify\Events\ReputationChanged; +use \RecursiveDirectoryIterator; +use \RecursiveIteratorIterator; +use \RecursiveRegexIterator; +use \RegexIterator; + class GamifyServiceProvider extends ServiceProvider { /** @@ -77,10 +82,31 @@ protected function getBadges() $badges = []; - foreach (glob(app_path('/Gamify/Badges/') . '*.php') as $file) { - if (is_file($file)) { - $badges[] = app($badgeRootNamespace . '\\' . pathinfo($file, PATHINFO_FILENAME)); - } + // Get the first folder for the app. Normally App + $rootFolder = substr($badgeRootNamespace, 0, strpos($badgeRootNamespace, '\\')); + + // Create recursive searching classes + $directory = new RecursiveDirectoryIterator(app_path('Gamify/Badges/')); + $iterator = new RecursiveIteratorIterator($directory); + $files = new RegexIterator($iterator, '/^.+\.php$/i', RecursiveRegexIterator::GET_MATCH); + + // loop through each file found + foreach ($files as $file) { + + // grab the directory for the file + $fileDirectory = pathinfo($file[0], PATHINFO_DIRNAME); + + //remove full server path and prepend the rootfolder + $fileDirectory = $rootFolder.str_ireplace(app_path(), '', $fileDirectory); + + // convert the forward slashes to backslashes + $fileDirectory = str_ireplace('/', '\\', $fileDirectory); + + // get the file name + $fileName = pathinfo($file[0], PATHINFO_FILENAME); + + //append namespace file path to the badges array to return + $badges[] = $fileDirectory."\\".$fileName; } return collect($badges); From d9196099915e8d569b9a891a9997005fbc22679d Mon Sep 17 00:00:00 2001 From: Abraham Arango Date: Thu, 12 Dec 2019 22:54:21 -0500 Subject: [PATCH 2/6] Update GamifyServiceProvider.php --- src/GamifyServiceProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GamifyServiceProvider.php b/src/GamifyServiceProvider.php index 42897a1..ac88707 100644 --- a/src/GamifyServiceProvider.php +++ b/src/GamifyServiceProvider.php @@ -82,7 +82,7 @@ protected function getBadges() $badges = []; - // Get the first folder for the app. Normally App + // Get the first folder for the app. For the vast majority of all projects this is "App" $rootFolder = substr($badgeRootNamespace, 0, strpos($badgeRootNamespace, '\\')); // Create recursive searching classes From a2f43c307489aad19542975774e32f29e2d61a59 Mon Sep 17 00:00:00 2001 From: Abraham Arango Date: Sat, 5 Nov 2022 22:00:59 -0500 Subject: [PATCH 3/6] Ability to give or update the points to a reputation record --- src/HasReputations.php | 36 ++++++++++++++++++++++++++++ src/PointType.php | 14 +++++++++++ src/helpers.php | 20 ++++++++++++++++ tests/PointTest.php | 53 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+) diff --git a/src/HasReputations.php b/src/HasReputations.php index 8b46717..846785c 100644 --- a/src/HasReputations.php +++ b/src/HasReputations.php @@ -23,6 +23,26 @@ public function givePoint(PointType $pointType) } } + /** + * Give or update reputation points to payee + * + * @param PointType $pointType + * @return bool + */ + public function giveOrUpdatePoint(PointType $pointType) + { + if (!$pointType->qualifier()) { + return false; + } + + if ($pointType->reputationExists()) { + $originalPoints = $pointType->syncPointsChange(); + return $pointType->payee()->syncPointsChange($originalPoints, $pointType->getPoints()); + }else if ($this->storeReputation($pointType)) { + return $pointType->payee()->addPoint($pointType->getPoints()); + } + } + /** * Undo last given point for a subject model * @@ -82,6 +102,22 @@ public function addPoint($point = 1) return $this; } + /** + * Sync points changed for a reputation record to a payee + * + * @param int $point + * @return HasReputations|\Illuminate\Database\Eloquent\Model + */ + public function syncPointsChange($originalPoints, $newPoints = 1) + { + $this->decrement($this->getReputationField(), $originalPoints); + $this->increment($this->getReputationField(), $newPoints); + + ReputationChanged::dispatch($this, $newPoints, true); + + return $this; + } + /** * Reduce a user point * diff --git a/src/PointType.php b/src/PointType.php index 2ef2c49..75daaba 100644 --- a/src/PointType.php +++ b/src/PointType.php @@ -134,6 +134,20 @@ public function storeReputation($meta = []) ]); } + /** + * Sync updates to points to an existing reputation record + * @return int $originalPoints + */ + public function syncPointsChange() + { + $dbPointType = $this->firstReputation(); + $originalPoints = $dbPointType->point; + $dbPointType->update([ + 'point' => $this->getPoints() + ]); + return $originalPoints; + } + /** * Get reputation query for this point * diff --git a/src/helpers.php b/src/helpers.php index bcf390d..b482c02 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -22,6 +22,26 @@ function givePoint(PointType $pointType, $payee = null) } } +if (!function_exists('giveOrUpdatePoint')) { + + /** + * Give point to user + * + * @param PointType $pointType + * @param null $payee + */ + function giveOrUpdatePoint(PointType $pointType, $payee = null) + { + $payee = $payee ?? auth()->user(); + + if (!$payee) { + return; + } + + $payee->giveOrUpdatePoint($pointType); + } +} + if (!function_exists('undoPoint')) { /** diff --git a/tests/PointTest.php b/tests/PointTest.php index 13443e3..4c4c699 100644 --- a/tests/PointTest.php +++ b/tests/PointTest.php @@ -69,6 +69,41 @@ public function it_gives_point_to_a_user() ]); } + /** + * it gives point to a user, then updates it validating that that change + * + * @test + */ + public function it_gives_and_updates_points_to_a_user() + { + $user = $this->createUser(); + $post = $this->createPost(['user_id' => $user->id]); + + $user->giveOrUpdatePoint(new FakeUpdateablePostPoint($post)); + + $this->assertEquals(1, $user->fresh()->getPoints()); + $this->assertCount(1, $user->reputations); + $this->assertDatabaseHas('reputations', [ + 'payee_id' => $user->id, + 'subject_type' => $post->getMorphClass(), + 'subject_id' => $post->id, + 'point' => 1, + 'name' => 'FakeUpdateablePostPoint' + ]); + + $user->giveOrUpdatePoint(new FakeUpdateablePostPoint($post, 5)); + + $this->assertEquals(5, $user->fresh()->getPoints()); + $this->assertCount(1, $user->reputations); + $this->assertDatabaseHas('reputations', [ + 'payee_id' => $user->id, + 'subject_type' => $post->getMorphClass(), + 'subject_id' => $post->id, + 'point' => 5, + 'name' => 'FakeUpdateablePostPoint' + ]); + } + /** * it can access a reputation payee and subject * @@ -269,6 +304,24 @@ public function payee() } } +class FakeUpdateablePostPoint extends PointType +{ + protected $points = 1; + + public $allowDuplicates = false; + + public function __construct($subject, $points = 1) + { + $this->subject = $subject; + $this->points = $points; + } + + public function payee() + { + return $this->getSubject()->user; + } +} + class FakeWelcomeUserWithNamePoint extends PointType { protected $name = 'FakeName'; From e69281111ebed6f8bf81b7af6837f089e1970abc Mon Sep 17 00:00:00 2001 From: Abraham Arango Date: Sat, 5 Nov 2022 22:05:09 -0500 Subject: [PATCH 4/6] Revert "Ability to give or update the points to a reputation record" This reverts commit a2f43c307489aad19542975774e32f29e2d61a59. --- src/HasReputations.php | 36 ---------------------------- src/PointType.php | 14 ----------- src/helpers.php | 20 ---------------- tests/PointTest.php | 53 ------------------------------------------ 4 files changed, 123 deletions(-) diff --git a/src/HasReputations.php b/src/HasReputations.php index 846785c..8b46717 100644 --- a/src/HasReputations.php +++ b/src/HasReputations.php @@ -23,26 +23,6 @@ public function givePoint(PointType $pointType) } } - /** - * Give or update reputation points to payee - * - * @param PointType $pointType - * @return bool - */ - public function giveOrUpdatePoint(PointType $pointType) - { - if (!$pointType->qualifier()) { - return false; - } - - if ($pointType->reputationExists()) { - $originalPoints = $pointType->syncPointsChange(); - return $pointType->payee()->syncPointsChange($originalPoints, $pointType->getPoints()); - }else if ($this->storeReputation($pointType)) { - return $pointType->payee()->addPoint($pointType->getPoints()); - } - } - /** * Undo last given point for a subject model * @@ -102,22 +82,6 @@ public function addPoint($point = 1) return $this; } - /** - * Sync points changed for a reputation record to a payee - * - * @param int $point - * @return HasReputations|\Illuminate\Database\Eloquent\Model - */ - public function syncPointsChange($originalPoints, $newPoints = 1) - { - $this->decrement($this->getReputationField(), $originalPoints); - $this->increment($this->getReputationField(), $newPoints); - - ReputationChanged::dispatch($this, $newPoints, true); - - return $this; - } - /** * Reduce a user point * diff --git a/src/PointType.php b/src/PointType.php index 75daaba..2ef2c49 100644 --- a/src/PointType.php +++ b/src/PointType.php @@ -134,20 +134,6 @@ public function storeReputation($meta = []) ]); } - /** - * Sync updates to points to an existing reputation record - * @return int $originalPoints - */ - public function syncPointsChange() - { - $dbPointType = $this->firstReputation(); - $originalPoints = $dbPointType->point; - $dbPointType->update([ - 'point' => $this->getPoints() - ]); - return $originalPoints; - } - /** * Get reputation query for this point * diff --git a/src/helpers.php b/src/helpers.php index b482c02..bcf390d 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -22,26 +22,6 @@ function givePoint(PointType $pointType, $payee = null) } } -if (!function_exists('giveOrUpdatePoint')) { - - /** - * Give point to user - * - * @param PointType $pointType - * @param null $payee - */ - function giveOrUpdatePoint(PointType $pointType, $payee = null) - { - $payee = $payee ?? auth()->user(); - - if (!$payee) { - return; - } - - $payee->giveOrUpdatePoint($pointType); - } -} - if (!function_exists('undoPoint')) { /** diff --git a/tests/PointTest.php b/tests/PointTest.php index 4c4c699..13443e3 100644 --- a/tests/PointTest.php +++ b/tests/PointTest.php @@ -69,41 +69,6 @@ public function it_gives_point_to_a_user() ]); } - /** - * it gives point to a user, then updates it validating that that change - * - * @test - */ - public function it_gives_and_updates_points_to_a_user() - { - $user = $this->createUser(); - $post = $this->createPost(['user_id' => $user->id]); - - $user->giveOrUpdatePoint(new FakeUpdateablePostPoint($post)); - - $this->assertEquals(1, $user->fresh()->getPoints()); - $this->assertCount(1, $user->reputations); - $this->assertDatabaseHas('reputations', [ - 'payee_id' => $user->id, - 'subject_type' => $post->getMorphClass(), - 'subject_id' => $post->id, - 'point' => 1, - 'name' => 'FakeUpdateablePostPoint' - ]); - - $user->giveOrUpdatePoint(new FakeUpdateablePostPoint($post, 5)); - - $this->assertEquals(5, $user->fresh()->getPoints()); - $this->assertCount(1, $user->reputations); - $this->assertDatabaseHas('reputations', [ - 'payee_id' => $user->id, - 'subject_type' => $post->getMorphClass(), - 'subject_id' => $post->id, - 'point' => 5, - 'name' => 'FakeUpdateablePostPoint' - ]); - } - /** * it can access a reputation payee and subject * @@ -304,24 +269,6 @@ public function payee() } } -class FakeUpdateablePostPoint extends PointType -{ - protected $points = 1; - - public $allowDuplicates = false; - - public function __construct($subject, $points = 1) - { - $this->subject = $subject; - $this->points = $points; - } - - public function payee() - { - return $this->getSubject()->user; - } -} - class FakeWelcomeUserWithNamePoint extends PointType { protected $name = 'FakeName'; From b27190a6da12996d04f19f3d1aa66aeba2a5072c Mon Sep 17 00:00:00 2001 From: Abraham Arango Date: Sat, 5 Nov 2022 22:05:36 -0500 Subject: [PATCH 5/6] Revert "Revert "Ability to give or update the points to a reputation record"" This reverts commit e69281111ebed6f8bf81b7af6837f089e1970abc. --- src/HasReputations.php | 36 ++++++++++++++++++++++++++++ src/PointType.php | 14 +++++++++++ src/helpers.php | 20 ++++++++++++++++ tests/PointTest.php | 53 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+) diff --git a/src/HasReputations.php b/src/HasReputations.php index 8b46717..846785c 100644 --- a/src/HasReputations.php +++ b/src/HasReputations.php @@ -23,6 +23,26 @@ public function givePoint(PointType $pointType) } } + /** + * Give or update reputation points to payee + * + * @param PointType $pointType + * @return bool + */ + public function giveOrUpdatePoint(PointType $pointType) + { + if (!$pointType->qualifier()) { + return false; + } + + if ($pointType->reputationExists()) { + $originalPoints = $pointType->syncPointsChange(); + return $pointType->payee()->syncPointsChange($originalPoints, $pointType->getPoints()); + }else if ($this->storeReputation($pointType)) { + return $pointType->payee()->addPoint($pointType->getPoints()); + } + } + /** * Undo last given point for a subject model * @@ -82,6 +102,22 @@ public function addPoint($point = 1) return $this; } + /** + * Sync points changed for a reputation record to a payee + * + * @param int $point + * @return HasReputations|\Illuminate\Database\Eloquent\Model + */ + public function syncPointsChange($originalPoints, $newPoints = 1) + { + $this->decrement($this->getReputationField(), $originalPoints); + $this->increment($this->getReputationField(), $newPoints); + + ReputationChanged::dispatch($this, $newPoints, true); + + return $this; + } + /** * Reduce a user point * diff --git a/src/PointType.php b/src/PointType.php index 2ef2c49..75daaba 100644 --- a/src/PointType.php +++ b/src/PointType.php @@ -134,6 +134,20 @@ public function storeReputation($meta = []) ]); } + /** + * Sync updates to points to an existing reputation record + * @return int $originalPoints + */ + public function syncPointsChange() + { + $dbPointType = $this->firstReputation(); + $originalPoints = $dbPointType->point; + $dbPointType->update([ + 'point' => $this->getPoints() + ]); + return $originalPoints; + } + /** * Get reputation query for this point * diff --git a/src/helpers.php b/src/helpers.php index bcf390d..b482c02 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -22,6 +22,26 @@ function givePoint(PointType $pointType, $payee = null) } } +if (!function_exists('giveOrUpdatePoint')) { + + /** + * Give point to user + * + * @param PointType $pointType + * @param null $payee + */ + function giveOrUpdatePoint(PointType $pointType, $payee = null) + { + $payee = $payee ?? auth()->user(); + + if (!$payee) { + return; + } + + $payee->giveOrUpdatePoint($pointType); + } +} + if (!function_exists('undoPoint')) { /** diff --git a/tests/PointTest.php b/tests/PointTest.php index 13443e3..4c4c699 100644 --- a/tests/PointTest.php +++ b/tests/PointTest.php @@ -69,6 +69,41 @@ public function it_gives_point_to_a_user() ]); } + /** + * it gives point to a user, then updates it validating that that change + * + * @test + */ + public function it_gives_and_updates_points_to_a_user() + { + $user = $this->createUser(); + $post = $this->createPost(['user_id' => $user->id]); + + $user->giveOrUpdatePoint(new FakeUpdateablePostPoint($post)); + + $this->assertEquals(1, $user->fresh()->getPoints()); + $this->assertCount(1, $user->reputations); + $this->assertDatabaseHas('reputations', [ + 'payee_id' => $user->id, + 'subject_type' => $post->getMorphClass(), + 'subject_id' => $post->id, + 'point' => 1, + 'name' => 'FakeUpdateablePostPoint' + ]); + + $user->giveOrUpdatePoint(new FakeUpdateablePostPoint($post, 5)); + + $this->assertEquals(5, $user->fresh()->getPoints()); + $this->assertCount(1, $user->reputations); + $this->assertDatabaseHas('reputations', [ + 'payee_id' => $user->id, + 'subject_type' => $post->getMorphClass(), + 'subject_id' => $post->id, + 'point' => 5, + 'name' => 'FakeUpdateablePostPoint' + ]); + } + /** * it can access a reputation payee and subject * @@ -269,6 +304,24 @@ public function payee() } } +class FakeUpdateablePostPoint extends PointType +{ + protected $points = 1; + + public $allowDuplicates = false; + + public function __construct($subject, $points = 1) + { + $this->subject = $subject; + $this->points = $points; + } + + public function payee() + { + return $this->getSubject()->user; + } +} + class FakeWelcomeUserWithNamePoint extends PointType { protected $name = 'FakeName'; From 41bb05eba4dd1a91bd13f4e6467b5a42579ed4bd Mon Sep 17 00:00:00 2001 From: Abraham Arango Date: Sat, 5 Nov 2022 22:58:56 -0500 Subject: [PATCH 6/6] Update README.md --- README.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c1a4a8b..dfa786d 100644 --- a/README.md +++ b/README.md @@ -136,10 +136,24 @@ $user->undoPoint(new PostCreated($post)); $post->delete(); ``` -You can also pass second argument as $user in helper function `givePoint(new PostCreated($post, $user))`, default is auth()->user(). +You can also pass second argument as $user in helper function `givePoint(new PostCreated($post) $user)`, default is auth()->user(). **Pro Tip 👌** You could also hook into the Eloquent model event and give point on `created` event. Similarly, `deleted` event can be used to undo the point. +### Give or update points to User + +There may be a situation where the points given for a reputation record changes over time. For example, a comment to a post that can be up voted. Those votes are given to the commenter as they come in. + +For this situation you can use the `giveOrUpdatePoint` helper which will give the points or update them automatically to the user's reputation total + +``` php +// create initial reputation record with 5 points +giveOrUpdatePoint(new PostCommentVotes($postComment, 5), $user); + +// update reputation record to 20 points for the same $postComment db record +giveOrUpdatePoint(new PostCommentVotes($postComment, 20), $user); +``` + ### Get total reputation To get the total user reputation you have `$user->getPoints($formatted = false)` method available. Optioally you can pass `$formatted = true` to get reputation as 1K+, 2K+ etc.