Skip to content

Commit 773a44a

Browse files
committed
Basic query for community done.
1 parent 89d47d7 commit 773a44a

7 files changed

Lines changed: 122 additions & 26 deletions

File tree

app/Http/Controllers/CommentController.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ public function store(StoreCommentRequest $request)
4141

4242
$commentableType = $this->modelResolver->getModelClass($validatedData['commentable_key']);
4343
$commentableId = $validatedData['commentable_id'];
44-
44+
4545
// Ensure that the model exists
4646
$model = $this->modelResolver->resolve($validatedData['commentable_key'], $commentableId);
4747
if (!$model) {
4848
return response()->json(['message' => 'Model not found'], 404);
49-
}
49+
}
5050
Log::debug("Resolved model class: " . $commentableType);
5151

5252
// Set the commentable type
@@ -64,7 +64,7 @@ public function store(StoreCommentRequest $request)
6464
else {
6565
$parent = Comment::find($parentCommentId);
6666
$new_comment_depth = $parent->depth + 1;
67-
67+
6868
// Check if the parent is the root comment
6969
if ($parent->depth == 1) {
7070
$root_comment = $parent;
@@ -79,7 +79,7 @@ public function store(StoreCommentRequest $request)
7979

8080
// Ensure that they are commenting to the same root
8181
// And the depth is not exceeded
82-
Validator::make(
82+
Validator::validate(
8383
[
8484
'commentable_id' => $commentableId,
8585
'commentable_type' => $commentableType,
@@ -108,14 +108,14 @@ public function store(StoreCommentRequest $request)
108108
'lt:' . (config('comment.max_replies'))
109109
]
110110
]
111-
)->validate();
111+
);
112112

113113
// Set the parent id
114114
$comment->parent_comment_id = $parentCommentId;
115-
115+
116116
// Set the parent's root as this comment's root, unless it is the root itself.
117117
$comment->root_comment_id = $root_comment_id;
118-
118+
119119
// Set the new depth
120120
$comment->depth = $new_comment_depth;
121121

@@ -148,10 +148,10 @@ public function show(Request $request, string $commentableKey, int $commentableI
148148
}
149149

150150
$sortBy = $request->query('sort_by', 'top');
151-
151+
152152
Log::debug("Request is, commentable_type: " . $commentableKey . ". id: " . $commentableId . ". index: " . $index . ". Sorting: " . $sortBy);
153153
$paginatedResults = $this->commentService->getPaginatedComments($commentableKey, $commentableId, $index, $paginationLimit, $sortBy);
154-
154+
155155
return $paginatedResults;
156156
}
157157
}

app/Http/Controllers/ComputerScienceResourceController.php

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,26 @@
88
use App\Models\ResourceEdits;
99
use App\Models\ResourceReview;
1010
use App\Services\CommentService;
11+
use App\Services\ResourceReviewService;
1112
use App\Services\UpvoteService;
1213
use Illuminate\Http\Request;
1314
use Illuminate\Support\Facades\Auth;
1415
use Illuminate\Support\Facades\Log;
16+
use Illuminate\Support\Facades\Validator;
17+
use Illuminate\Validation\Rule;
1518
use Inertia\Inertia;
1619

1720
class ComputerScienceResourceController extends Controller
1821
{
1922
protected $commentService;
2023
protected $upvoteService;
24+
protected $reviewService;
2125

22-
function __construct(CommentService $commentService, UpvoteService $upvoteService)
26+
function __construct(CommentService $commentService, UpvoteService $upvoteService, ResourceReviewService $reviewService)
2327
{
2428
$this->commentService = $commentService;
2529
$this->upvoteService = $upvoteService;
30+
$this->reviewService = $reviewService;
2631
}
2732

2833
/**
@@ -35,6 +40,43 @@ public function index(Request $request)
3540
// Eager load relations
3641
$query->with(['tags', 'votes', 'upvoteSummary', 'reviewSummary', 'commentsCountRelationship']);
3742

43+
$validator = Validator::make([
44+
'name' => $request->query('name'),
45+
'description' => $request->query('description'),
46+
'platforms' => $request->query('platforms'),
47+
'difficulty' => $request->query('difficulty'),
48+
'pricing' => $request->query('pricing'),
49+
'topics' => $request->query('topics'),
50+
'programming_languages' => $request->query('programming_languages'),
51+
'general_tags' => $request->query('general_tags'),
52+
53+
'community_rating' => $request->query('community_rating'),
54+
],
55+
[
56+
'name' => ['nullable', 'string', 'max:100'],
57+
'name' => ['nullable', 'string', 'max:1000'],
58+
'platforms' => ['nullable', 'array', 'min:1'],
59+
'platforms.*' => ['required', 'distinct', 'string', Rule::in(config('computerScienceResource.platforms'))],
60+
'difficulty' => ['nullable', 'string', Rule::in(config('computerScienceResource.difficulties'))],
61+
'pricing' => ['nullable', 'string', Rule::in(config('computerScienceResource.pricings'))],
62+
63+
'topic_tags' => ['nullable', 'array', 'min:3'],
64+
'topic_tags.*' => ['required', 'distinct', 'string', 'max:50'],
65+
66+
'general_tags' => ['nullable', 'array'],
67+
'general_tags.*' => ['required', 'distinct', 'string', 'max:50'],
68+
'programming_language_tags' => ['nullable', 'array'],
69+
'programming_language_tags.*' => ['required', 'distinct', 'string', 'max:50'],
70+
71+
'community_rating' => ['nullable', 'integer', 'between:1,4'],
72+
]);
73+
74+
if (!$validator->validate())
75+
{
76+
// TODO: actually show the error, need to flash instead
77+
return back()->with('error', 'Invalid query parameters data');
78+
}
79+
3880
// Fulltext search on name
3981
if ($name = $request->query('name')) {
4082
$query->whereFullText('name', $name);
@@ -79,7 +121,10 @@ public function index(Request $request)
79121
$query->withAnyTags((array) $generalTags, 'general_tags');
80122
}
81123

82-
124+
// Filter by reviews
125+
if ($commmunityRating = $request->query('community_rating')) {
126+
$query = $this->reviewService->applyRatingFilter($query, 'community', $commmunityRating);
127+
}
83128

84129
// Paginate and return
85130
$resources = $query->paginate(10)->appends($request->query());

app/Http/Requests/Shared/ComputerScienceResourceRequest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@ public function baseResourceRules(): array
1717
'image_url' => ['nullable', 'string', 'url:http,https', 'max:255'],
1818
'difficulty' => ['required', 'string', Rule::in(config('computerScienceResource.difficulties'))],
1919
'pricing' => ['required', 'string', Rule::in(config('computerScienceResource.pricings'))],
20-
20+
2121
'topic_tags' => ['required', 'array', 'min:3'],
2222
'topic_tags.*' => ['required', 'distinct', 'string', 'max:50'],
2323

24-
// Optional
24+
// Optional, can just be omitted
2525
'general_tags' => ['array'],
2626
'general_tags.*' => ['required', 'distinct', 'string', 'max:50'],
2727
'programming_language_tags' => ['array'],
2828
'programming_language_tags.*' => ['required', 'distinct', 'string', 'max:50'],
2929
];
3030
}
3131

32-
}
32+
}

app/Services/CommentService.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,24 @@ function __construct(ModelResolverService $resolver)
2727
* @param int $index
2828
* @return array
2929
*/
30-
// TODO: Refactor commentable types, and commentable types short for all other objects
3130
public function getPaginatedComments(string $commentableKey, int $commentableId, int $index, int $paginationLimit = -1, string $sortBy = 'top'): array
3231
{
3332
if ($paginationLimit == -1)
3433
{
3534
$paginationLimit = config('comment.default_pagination_limit');
3635
}
3736

38-
Validator::make([
37+
Validator::validate([
3938
'index' => $index,
4039
'commentable_key' => $commentableKey,
4140
'pagination_limit' => $paginationLimit,
4241
], [
4342
'index' => ['required', 'integer', 'min:0'],
4443
'commentable_key' => ['required', Rule::in(config('comment.commentable_keys'))],
4544
'pagination_limit' => ['required', 'integer', 'max:' . config('comment.pagination_limit')],
46-
])->validate();
45+
]);
4746

48-
$commentableType = $this->modelResolver->getModelClass($commentableKey);
47+
$commentableType = $this->modelResolver->getModelClass($commentableKey);
4948
Log::debug("Request is, commentable_type: {$commentableType}. id: {$commentableId}. index: {$index}");
5049

5150
// Get the root comments:
@@ -54,13 +53,13 @@ public function getPaginatedComments(string $commentableKey, int $commentableId,
5453
'commentable_id' => $commentableId,
5554
'depth' => 1,
5655
]);
57-
56+
5857
// Apply sorting on the comments
5958
$query = app(UpvoteService::class)->applySort($query, $sortBy, Comment::class);
6059

6160
$rootComments = $query->get();
6261
Log::debug("Root comments: " . json_encode($rootComments));
63-
62+
6463
// Initialize variables
6564
$currentCommentsSum = 0;
6665
$resultingPaginatedComments = [];

app/Services/ResourceEditsService.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
class ResourceEditsService
88
{
99
/**
10-
* Determines the amount of votes needed to merge the resource edit into the
11-
*
12-
* Policy: The policy is roughly the formula of:
13-
* min(log(total votes of resource)/log(1.25) + 1, -- Log dropoff
10+
* Determines the amount of votes needed to merge the resource edit into the
11+
*
12+
* Policy: The policy is roughly the formula of:
13+
* min(log(total votes of resource)/log(1.25) + 1, -- Log dropoff
1414
* total votes of resource) -- Dont want to require more votes than the resource's votes
1515
* )
1616
*/
@@ -25,7 +25,7 @@ public function requiredVotes(int $totalVotes): int
2525

2626
/**
2727
* Handles determining if a resource edit is mergeable, by getting the upvotes for the resource edit
28-
*
28+
*
2929
*/
3030
public function canMergeEdits(ResourceEdits $edits) : bool
3131
{
@@ -35,7 +35,7 @@ public function canMergeEdits(ResourceEdits $edits) : bool
3535

3636
$totalVotes = $edits->resource->votes_count;
3737
$neededApprovals = $this->requiredVotes($totalVotes);
38-
38+
3939
$approvals = $edits->vote_score;
4040

4141
return $approvals >= $neededApprovals;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
namespace App\Services;
4+
5+
use Illuminate\Database\Eloquent\Builder;
6+
use InvalidArgumentException;
7+
use App\Models\ResourceReviewSummary;
8+
9+
class ResourceReviewService
10+
{
11+
/**
12+
* These are the only rating fields we allow filtering on.
13+
*/
14+
protected array $allowedFields = [
15+
'community',
16+
'teaching_clarity',
17+
'engagement',
18+
'practicality',
19+
'user_friendliness',
20+
'updates',
21+
];
22+
23+
/**
24+
* Apply an average‐rating filter to a query for resources.
25+
*
26+
* @param Builder $query The query on your Resource model.
27+
* @param string $field One of the allowed rating fields.
28+
* @param int $minRating Minimum average rating (1–5).
29+
* @return Builder
30+
*
31+
* @throws InvalidArgumentException
32+
*/
33+
public function applyRatingFilter(Builder $query, string $field, int $minRating): Builder
34+
{
35+
if (! in_array($field, $this->allowedFields, true)) {
36+
throw new InvalidArgumentException("Invalid rating field “{$field}”.");
37+
}
38+
39+
if ($minRating < 1 || $minRating > 5) {
40+
throw new InvalidArgumentException("Rating must be between 1 and 5.");
41+
}
42+
43+
$resourceTable = $query->getModel()->getTable();
44+
$reviewTable = (new ResourceReviewSummary())->getTable();
45+
46+
return $query
47+
->join($reviewTable, "{$reviewTable}.computer_science_resource_id", '=', "{$resourceTable}.id")
48+
->select("{$resourceTable}.*")
49+
->whereRaw("{$reviewTable}.{$field} >= ? * {$reviewTable}.review_count", [$minRating]);
50+
}
51+
}

resources/js/Components/Resources/FilterBar.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ function search() {
7272
general_tags: selectedGeneralTags.value.length
7373
? selectedGeneralTags.value
7474
: undefined,
75+
community_rating: 1,
7576
}),
7677
{ preserveScroll: true }
7778
);

0 commit comments

Comments
 (0)