Skip to content

Commit 6b811a9

Browse files
committed
feat: get a review, fix: approval system, chore: update docs
1 parent 7e0a2e3 commit 6b811a9

File tree

5 files changed

+285
-11
lines changed

5 files changed

+285
-11
lines changed

README.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,23 @@ This query will eager load the reviewer information for each received review.
142142

143143
**Note:** Consider using appropriate eager loading strategies based on your application's needs to optimize query performance.
144144

145+
#### Get a review received from a specified reviewer
146+
147+
To retrieve a review that a reviewer has given to reviewable:
148+
149+
```php
150+
$review = $mentor->getReceivedReview($mentee);
151+
```
152+
153+
This method returns a single `Review` instance or `null` if no review exists.
154+
155+
To include unapproved reviews in the search, pass `true` as the second parameter:
156+
157+
```php
158+
$includeUnapproved = true;
159+
$review = $mentor->getReceivedReview($mentee, $includeUnapproved);
160+
```
161+
145162
#### Get all given reviews
146163

147164
To get all reviews given by a model:
@@ -158,6 +175,59 @@ Mentee::with('givenReviews.reviewable')->paginate();
158175

159176
This will eager load the reviewable model for each review given by the model.
160177

178+
#### Get a review given from a specified reviewable model
179+
180+
To retrieve a given review that a reviewable has received from reviewer:
181+
182+
```php
183+
$review = $mentee->getGivenReview($mentor);
184+
```
185+
186+
This method returns a single `Review` instance or `null` if no review exists.
187+
188+
To include unapproved reviews in the search, pass `true` as the second parameter:
189+
190+
```php
191+
$includeUnapproved = true;
192+
$review = $mentor->getGivenReview($mentee, $includeUnapproved);
193+
```
194+
195+
### Checking for Reviews
196+
197+
#### Check if a reviewable model has received a review from a specific reviewer
198+
199+
```php
200+
if ($mentor->hasReceivedReview($mentee)) {
201+
// The mentor has received a review from the mentee
202+
}
203+
```
204+
205+
To include unapproved reviews in the check, pass `true` as the second parameter:
206+
207+
```php
208+
$includeUnapproved = true;
209+
if ($mentor->hasReceivedReview($mentee, $includeUnapproved)) {
210+
// The mentor has received a review from the mentee
211+
}
212+
```
213+
214+
#### Check if the current model has given a review to the specified model
215+
216+
```php
217+
if ($mentee->hasGivenReview($mentor)) {
218+
// The mentee has given a review to the mentor
219+
}
220+
```
221+
222+
To include unapproved reviews in the check, pass `true` as the second parameter:
223+
224+
```php
225+
$includeUnapproved = true;
226+
if ($mentee->hasGivenReview($mentor, $includeUnapproved)) {
227+
// The mentee has given a review to the mentor
228+
}
229+
```
230+
161231
### Review Model
162232

163233
The `Fajarwz\LaravelReview\Models\Review` model includes methods for managing and querying reviews:

src/Traits/CanBeReviewed.php

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,35 @@ public function receivedReviews(?Model $model = null): HasMany
3232
/**
3333
* Check if the current model has received a review from the specified model.
3434
*/
35-
public function hasReceivedReview(Model $model): bool
35+
public function hasReceivedReview(Model $model, bool $includeUnapproved = false): bool
3636
{
37-
return $this->receivedReviews()
37+
$query = $this->receivedReviews()
3838
->where('reviewer_type', get_class($model))
39-
->where('reviewer_id', $model->getKey())
40-
->exists();
39+
->where('reviewer_id', $model->getKey());
40+
41+
if ($includeUnapproved) {
42+
$query->withUnapproved();
43+
}
44+
45+
return $query->exists();
46+
}
47+
48+
/**
49+
* Get the current model received review of the specified model.
50+
*
51+
* @param \Illuminate\Database\Eloquent\Model|null $model
52+
*/
53+
public function getReceivedReview(Model $model, bool $includeUnapproved = false): ?Review
54+
{
55+
$query = $this->receivedReviews()
56+
->where('reviewer_type', get_class($model))
57+
->where('reviewer_id', $model->getKey());
58+
59+
if ($includeUnapproved) {
60+
$query->withUnapproved();
61+
}
62+
63+
return $query->first();
4164
}
4265

4366
/**

src/Traits/CanReview.php

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,36 @@ public function givenReviews(?Model $model = null): HasMany
3232

3333
/**
3434
* Check if the current model has given a review for the specified model.
35+
*/
36+
public function hasGivenReview(Model $model, bool $includeUnapproved = false): bool
37+
{
38+
$query = $this->givenReviews()
39+
->where('reviewable_type', get_class($model))
40+
->where('reviewable_id', $model->getKey());
41+
42+
if ($includeUnapproved) {
43+
$query->withUnapproved();
44+
}
45+
46+
return $query->exists();
47+
}
48+
49+
/**
50+
* Get the current model given review for the specified model.
3551
*
36-
* @param \Illuminate\Database\Eloquent\Model $model
52+
* @param \Illuminate\Database\Eloquent\Model|null $model
3753
*/
38-
public function hasGivenReview($model): bool
54+
public function getGivenReview(Model $model, bool $includeUnapproved = false): ?Review
3955
{
40-
return $this->givenReviews()
56+
$query = $this->givenReviews()
4157
->where('reviewable_type', get_class($model))
42-
->where('reviewable_id', $model->getKey())
43-
->exists();
58+
->where('reviewable_id', $model->getKey());
59+
60+
if ($includeUnapproved) {
61+
$query->withUnapproved();
62+
}
63+
64+
return $query->first();
4465
}
4566

4667
/**
@@ -50,7 +71,7 @@ public function hasGivenReview($model): bool
5071
*/
5172
public function review($model, float $rating, ?string $reviewContent = null, bool $isApproved = true): Review
5273
{
53-
if ($this->hasGivenReview($model)) {
74+
if ($this->hasGivenReview($model, true)) {
5475
throw new DuplicateReviewException;
5576
}
5677

@@ -93,7 +114,7 @@ public function updateReview($model, float $newRating, ?string $newReview = null
93114
*/
94115
public function unreview($model): bool
95116
{
96-
if (! $this->hasGivenReview($model)) {
117+
if (! $this->hasGivenReview($model, true)) {
97118
throw new ReviewNotFoundException;
98119
}
99120

tests/CanBeReviewedTest.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Fajarwz\LaravelReview\Tests;
44

55
use DB;
6+
use Fajarwz\LaravelReview\Models\Review;
67
use Fajarwz\LaravelReview\Tests\Models\Mentee;
78
use Fajarwz\LaravelReview\Tests\Models\Mentor;
89

@@ -68,6 +69,85 @@ public function test_hasReceivedReview_returns_false_if_a_reviewable_has_not_bee
6869
$this->assertFalse($this->mentor->hasReceivedReview($otherMentee));
6970
}
7071

72+
public function test_hasReceivedReview_returns_true_with_includeUnapproved_true_if_a_reviewable_has_unapproved_review_by_the_given_model()
73+
{
74+
$otherMentee = Mentee::factory()->create();
75+
76+
DB::table('reviews')->insert([
77+
'reviewer_id' => $otherMentee->id,
78+
'reviewer_type' => get_class($otherMentee),
79+
'reviewable_id' => $this->mentor->id,
80+
'reviewable_type' => get_class($this->mentor),
81+
'rating' => 3,
82+
'approved_at' => null,
83+
]);
84+
85+
$this->assertTrue($this->mentor->hasReceivedReview($otherMentee, true));
86+
}
87+
88+
public function test_hasReceivedReview_returns_false_with_includeUnapproved_false_if_a_reviewable_has_unapproved_review_by_the_given_model()
89+
{
90+
$otherMentee = Mentee::factory()->create();
91+
92+
DB::table('reviews')->insert([
93+
'reviewer_id' => $otherMentee->id,
94+
'reviewer_type' => get_class($otherMentee),
95+
'reviewable_id' => $this->mentor->id,
96+
'reviewable_type' => get_class($this->mentor),
97+
'rating' => 3,
98+
'approved_at' => null,
99+
]);
100+
101+
$this->assertFalse($this->mentor->hasReceivedReview($otherMentee));
102+
}
103+
104+
public function test_getReceivedReview_retrieves_only_approved_review_by_default()
105+
{
106+
$review = $this->mentor->getReceivedReview($this->mentee);
107+
108+
$this->assertInstanceOf(Review::class, $review);
109+
$this->assertEquals($this->mentee->id, $review->reviewer_id);
110+
$this->assertEquals(4.5, $review->rating);
111+
}
112+
113+
public function test_getReceivedReview_returns_null_for_unapproved_review_by_default()
114+
{
115+
$newMentee = Mentor::factory()->create();
116+
117+
DB::table('reviews')->insert([
118+
'reviewer_id' => $newMentee->id,
119+
'reviewer_type' => get_class($newMentee),
120+
'reviewable_id' => $this->mentor->id,
121+
'reviewable_type' => get_class($this->mentor),
122+
'rating' => 3,
123+
'approved_at' => null,
124+
]);
125+
126+
$review = $this->mentor->getReceivedReview($newMentee);
127+
128+
$this->assertNull($review);
129+
}
130+
131+
public function test_getReceivedReview_can_retrieve_unapproved_review_when_includeUnapproved_is_true()
132+
{
133+
$newMentee = Mentee::factory()->create();
134+
135+
DB::table('reviews')->insert([
136+
'reviewer_id' => $newMentee->id,
137+
'reviewer_type' => get_class($newMentee),
138+
'reviewable_id' => $this->mentor->id,
139+
'reviewable_type' => get_class($this->mentor),
140+
'rating' => 3,
141+
'approved_at' => null,
142+
]);
143+
144+
$review = $this->mentor->getReceivedReview($newMentee, true);
145+
146+
$this->assertInstanceOf(Review::class, $review);
147+
$this->assertEquals($newMentee->id, $review->reviewer_id);
148+
$this->assertEquals(3, $review->rating);
149+
}
150+
71151
public function test_a_reviewable_can_display_its_review_summary()
72152
{
73153
$this->assertTrue($this->mentor->reviewSummary->exists());

tests/CanReviewTest.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use DB;
66
use Fajarwz\LaravelReview\Exceptions\DuplicateReviewException;
77
use Fajarwz\LaravelReview\Exceptions\ReviewNotFoundException;
8+
use Fajarwz\LaravelReview\Models\Review;
89
use Fajarwz\LaravelReview\Models\ReviewSummary;
910
use Fajarwz\LaravelReview\Tests\Models\Mentee;
1011
use Fajarwz\LaravelReview\Tests\Models\Mentor;
@@ -70,6 +71,85 @@ public function test_hasGivenReview_returns_false_if_a_reviewer_has_not_reviewed
7071
$this->assertFalse($this->mentee->hasGivenReview($otherMentor));
7172
}
7273

74+
public function test_hasGivenReview_returns_true_with_includeUnapproved_true_if_a_reviewer_has_unapproved_review_for_the_given_model()
75+
{
76+
$otherMentor = Mentor::factory()->create();
77+
78+
DB::table('reviews')->insert([
79+
'reviewer_id' => $this->mentee->id,
80+
'reviewer_type' => get_class($this->mentee),
81+
'reviewable_id' => $otherMentor->id,
82+
'reviewable_type' => get_class($otherMentor),
83+
'rating' => 3,
84+
'approved_at' => null,
85+
]);
86+
87+
$this->assertTrue($this->mentee->hasGivenReview($otherMentor, true));
88+
}
89+
90+
public function test_hasGivenReview_returns_false_with_includeUnapproved_false_if_a_reviewer_has_unapproved_review_for_the_given_model()
91+
{
92+
$otherMentor = Mentor::factory()->create();
93+
94+
DB::table('reviews')->insert([
95+
'reviewer_id' => $this->mentee->id,
96+
'reviewer_type' => get_class($this->mentee),
97+
'reviewable_id' => $this->mentor->id,
98+
'reviewable_type' => get_class($this->mentor),
99+
'rating' => 3,
100+
'approved_at' => null,
101+
]);
102+
103+
$this->assertFalse($this->mentee->hasGivenReview($otherMentor));
104+
}
105+
106+
public function test_getGivenReview_retrieves_only_approved_review_by_default()
107+
{
108+
$review = $this->mentee->getGivenReview($this->mentor);
109+
110+
$this->assertInstanceOf(Review::class, $review);
111+
$this->assertEquals($this->mentor->id, $review->reviewable_id);
112+
$this->assertEquals(4.5, $review->rating);
113+
}
114+
115+
public function test_getGivenReview_returns_null_for_unapproved_review_by_default()
116+
{
117+
$newMentor = Mentor::factory()->create();
118+
119+
DB::table('reviews')->insert([
120+
'reviewer_id' => $this->mentee->id,
121+
'reviewer_type' => get_class($this->mentee),
122+
'reviewable_id' => $newMentor->id,
123+
'reviewable_type' => get_class($newMentor),
124+
'rating' => 3,
125+
'approved_at' => null,
126+
]);
127+
128+
$review = $this->mentee->getGivenReview($newMentor);
129+
130+
$this->assertNull($review);
131+
}
132+
133+
public function test_getGivenReview_can_retrieve_unapproved_review_when_includeUnapproved_is_true()
134+
{
135+
$newMentor = Mentor::factory()->create();
136+
137+
DB::table('reviews')->insert([
138+
'reviewer_id' => $this->mentee->id,
139+
'reviewer_type' => get_class($this->mentee),
140+
'reviewable_id' => $newMentor->id,
141+
'reviewable_type' => get_class($newMentor),
142+
'rating' => 3,
143+
'approved_at' => null,
144+
]);
145+
146+
$review = $this->mentee->getGivenReview($newMentor, true);
147+
148+
$this->assertInstanceOf(Review::class, $review);
149+
$this->assertEquals($newMentor->id, $review->reviewable_id);
150+
$this->assertEquals(3, $review->rating);
151+
}
152+
73153
public function test_a_reviewer_can_review_the_given_model()
74154
{
75155
$newMentor = Mentor::factory()->create();

0 commit comments

Comments
 (0)