Skip to content

Commit 71dad47

Browse files
authored
Merge pull request #66 from Arkitecht/feature/simple-search
Feature/simple search
2 parents f511a0f + 9dd41f8 commit 71dad47

19 files changed

+281
-11
lines changed

config/firefly.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,6 @@
103103
],
104104
],
105105
'correct_posts' => false,
106+
'search' => false,
106107
],
107108
];
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
@props(['search' => ''])
2+
3+
@if (\Firefly\Features::enabled('search'))
4+
<form method="GET">
5+
<div>
6+
<label for="search" class="sr-only">Quick search</label>
7+
<div class="relative mt-1 flex items-center">
8+
<input
9+
type="search"
10+
name="search"
11+
id="search"
12+
value="{{ $search }}"
13+
placeholder="Search"
14+
accesskey="k"
15+
class="block w-full rounded-md border-gray-300 pr-12 shadow-sm focus:border-gray-700 focus:ring-gray-700 sm:text-lg"
16+
/>
17+
<div class="absolute inset-y-0 right-0 flex py-1.5 pr-1.5">
18+
<kbd class="inline-flex items-center rounded border border-gray-200 px-2 font-sans text-sm font-medium text-gray-400">k</kbd>
19+
</div>
20+
</div>
21+
</div>
22+
</form>
23+
@endif

resources/views/discussions/show.blade.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
</div>
3333

3434
<div class="space-y-5">
35+
<x-search :search="$search" />
36+
3537
@if (! $posts->count())
3638
<x-no-results>
3739
{{ __('There are no posts; You could be the first to create one.') }}

resources/views/groups/show.blade.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
@endif
3535

3636
<div class="space-y-5">
37+
<x-search :search="$search" />
38+
3739
@foreach ($discussions as $discussion)
3840
<x-discussion-item :discussion="$discussion" :show-groups="false" />
3941
@endforeach

resources/views/index.blade.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
{{ __('Discussions') }}
66
</h2>
77

8+
<x-search :search="$search" />
9+
810
@if (! $discussions->count())
911
<x-no-results>
1012
{{ __('There are no groups; You could be the first to create one.') }}

src/FireflyServiceProvider.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ protected function loadViews()
8282
Blade::component('firefly::components.post-item', 'post-item');
8383
Blade::component('firefly::components.quill-js', 'quill-js');
8484
Blade::component('firefly::components.rich-textarea', 'rich-textarea');
85+
Blade::component('firefly::components.search', 'search');
8586
}
8687

8788
/**

src/Http/Controllers/Api/DiscussionController.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@ public function store(StoreDiscussionRequest $request)
6868
* @param \Firefly\Models\Discussion $discussion
6969
* @return \Illuminate\Http\Response
7070
*/
71-
public function show(Discussion $discussion)
71+
public function show(Discussion $discussion, Request $request)
7272
{
7373
return response()->json([
7474
'discussion' => $discussion,
75-
'posts' => $discussion->posts()
76-
->when(Features::enabled('correct_posts'), fn ($query) => $query->orderBy('is_initial_post', 'desc')->orderBy('corrected_at', 'desc'))
75+
'posts' => $discussion->posts()->withSearch($request->get('search'))
76+
->when(Features::enabled('correct_posts'), fn ($query) => $query->orderBy('is_initial_post', 'desc')->orderBy('corrected_at', 'desc')->orderBy('created_at', 'asc'))
7777
->paginate(config('firefly.pagination.posts')),
7878
]);
7979
}

src/Http/Controllers/Api/GroupController.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ public function store(StoreGroupRequest $request)
6262
* @param \Firefly\Models\Group $group
6363
* @return \Illuminate\Http\Response
6464
*/
65-
public function show(Group $group)
65+
public function show(Group $group, Request $request)
6666
{
6767
$discussions = $group->discussions()
68+
->withSearch($request->get('search'))
6869
->orderBy('pinned_at', 'asc')
6970
->orderBy('created_at', 'desc')
7071
->paginate(config('firefly.pagination.discussions'));

src/Http/Controllers/DiscussionController.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,16 @@ public function store(StoreDiscussionRequest $request, Group $group)
6666
* @param \Firefly\Models\Discussion $discussion
6767
* @return \Illuminate\View\View
6868
*/
69-
public function show(Discussion $discussion)
69+
public function show(Discussion $discussion, Request $request)
7070
{
7171
$posts = $discussion->posts()
72+
->withSearch($request->get('search'))
7273
->when(Features::enabled('correct_posts'), fn ($query) => $query->orderBy('is_initial_post', 'desc')->orderBy('corrected_at', 'desc')->orderBy('created_at', 'asc'))
7374
->paginate(config('firefly.pagination.posts'));
7475

75-
return view('firefly::discussions.show')->withDiscussion($discussion)
76+
return view('firefly::discussions.show')
77+
->withDiscussion($discussion)
78+
->with('search', $request->get('search'))
7679
->withPosts($posts);
7780
}
7881

src/Http/Controllers/ForumController.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@ public function index(Request $request)
2020
$discussions = Discussion::query()
2121
->withIsBeingWatched($request->user())
2222
->withIsAnswered()
23+
->withSearch($request->get('search'))
2324
->orderBy('created_at', 'desc')
2425
->paginate(config('firefly.pagination.discussions'));
2526

26-
return view('firefly::index')->with(compact('groups', 'discussions'));
27+
return view('firefly::index')
28+
->with(compact('groups', 'discussions'))
29+
->withSearch($request->get('search'));
2730
}
2831
}

src/Http/Controllers/GroupController.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,17 @@ public function store(StoreGroupRequest $request)
7373
* @param \Firefly\Models\Group $group
7474
* @return \Illuminate\View\View
7575
*/
76-
public function show(Group $group)
76+
public function show(Group $group, Request $request)
7777
{
7878
$discussions = $group->discussions()
79+
->withSearch($request->get('search'))
7980
->orderBy('pinned_at', 'desc')
8081
->orderBy('created_at', 'desc')
8182
->paginate(config('firefly.pagination.discussions'));
8283

83-
return view('firefly::groups.show')->with(compact('group', 'discussions'));
84+
return view('firefly::groups.show')
85+
->with(compact('group', 'discussions'))
86+
->withSearch($request->get('search'));
8487
}
8588

8689
/**

src/Models/Discussion.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Illuminate\Database\Eloquent\Relations\HasMany;
1212
use Illuminate\Database\Eloquent\SoftDeletes;
1313
use Illuminate\Foundation\Auth\User;
14+
use Illuminate\Support\Facades\DB;
1415
use Spatie\Sluggable\HasSlug;
1516
use Spatie\Sluggable\SlugOptions;
1617

@@ -164,4 +165,21 @@ public function correctPost()
164165
return $this->hasOne(Post::class)
165166
->whereNotNull('corrected_at');
166167
}
168+
169+
public function scopeWithSearch(Builder $builder, ?string $search)
170+
{
171+
$search = strtr($search, ['%' => '\%', '_' => '\_', '\\' => '\\\\']);
172+
173+
$builder->when(Features::enabled('search') && $search, function ($query) use ($search) {
174+
$query->where(function ($query) use ($search) {
175+
$query->where('title', 'like', '%'.$search.'%')
176+
->orWhereExists(function ($query) use ($search) {
177+
$query->select(DB::raw(1))
178+
->from('posts')
179+
->whereColumn('discussion_id', 'discussions.id')
180+
->where('content', 'like', '%'.$search.'%');
181+
});
182+
});
183+
});
184+
}
167185
}

src/Models/Post.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace Firefly\Models;
44

5+
use Firefly\Features;
6+
use Illuminate\Database\Eloquent\Builder;
57
use Illuminate\Database\Eloquent\Factories\HasFactory;
68
use Illuminate\Database\Eloquent\Model;
79
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@@ -57,4 +59,13 @@ public function getIsCorrectAttribute()
5759
{
5860
return ! is_null($this->corrected_at);
5961
}
62+
63+
public function scopeWithSearch(Builder $builder, ?string $search)
64+
{
65+
$search = strtr($search, ['%' => '\%', '_' => '\_', '\\' => '\\\\']);
66+
67+
$builder->when(Features::enabled('search') && $search, function ($query) use ($search) {
68+
$query->where('content', 'like', '%'.$search.'%');
69+
});
70+
}
6071
}

tests/Feature/DiscussionTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,9 @@ public function test_gets_accurate_ordering_with_correct_post()
301301
'corrected_at' => Carbon::now(),
302302
]);
303303

304-
$view = (new DiscussionController(new DiscussionService()))->show($this->getDiscussion());
304+
$request = new \Illuminate\Http\Request();
305+
306+
$view = (new DiscussionController(new DiscussionService()))->show($this->getDiscussion(), $request);
305307
$data = $view->getData();
306308
$posts = $data['posts']->items();
307309

tests/Feature/ForumTest.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace Firefly\Test\Feature;
44

5+
use Firefly\Test\Fixtures\Discussion;
6+
use Firefly\Test\Fixtures\Post;
57
use Firefly\Test\TestCase;
68

79
class ForumTest extends TestCase
@@ -53,4 +55,55 @@ public function test_can_get_discussion_list_with_full_is_being_watched()
5355
$this->assertTrue(array_key_exists('is_being_watched', $discussions->first()->attributesToArray()));
5456
$this->assertNotNull($discussions->first()->is_being_watched);
5557
}
58+
59+
public function test_can_get_discussion_list_with_search()
60+
{
61+
$this->enableFeature('search');
62+
63+
Post::truncate();
64+
Discussion::truncate();
65+
66+
$discussion = Discussion::create([
67+
'user_id' => $this->getUser()->id,
68+
'title' => 'I want to search for content',
69+
]);
70+
71+
Post::create([
72+
'discussion_id' => $discussion->id,
73+
'user_id' => $this->getUser()->id,
74+
'content' => 'Does Not Match',
75+
]);
76+
77+
$discussionTwo = Discussion::create([
78+
'user_id' => $this->getUser()->id,
79+
'title' => 'I do not like finding content',
80+
]);
81+
82+
Post::create([
83+
'discussion_id' => $discussionTwo->id,
84+
'user_id' => $this->getUser()->id,
85+
'content' => 'Does Not Match',
86+
]);
87+
88+
$discussionThree = Discussion::create([
89+
'user_id' => $this->getUser()->id,
90+
'title' => 'I like finding content in posts',
91+
]);
92+
93+
Post::create([
94+
'discussion_id' => $discussionThree->id,
95+
'user_id' => $this->getUser()->id,
96+
'content' => 'Should search for a match',
97+
]);
98+
99+
$response = $this->actingAs($this->getUser())
100+
->get('forum/?search=search');
101+
102+
$discussions = $response->viewData('discussions');
103+
104+
$this->assertEquals(2, $discussions->count());
105+
106+
$this->assertEquals($discussion->id, $discussions->first()->id);
107+
$this->assertEquals($discussionThree->id, $discussions->skip(1)->first()->id);
108+
}
56109
}

tests/Feature/GroupTest.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
namespace Firefly\Test\Feature;
44

5+
use Firefly\Test\Fixtures\Discussion;
56
use Firefly\Test\Fixtures\Group;
7+
use Firefly\Test\Fixtures\Post;
68
use Firefly\Test\TestCase;
79
use Illuminate\Support\Str;
810

@@ -135,4 +137,66 @@ public function test_name_has_a_max_of_255_characters()
135137
$response->assertJsonValidationErrors('name');
136138
$response->assertJson($validJson);
137139
}
140+
141+
public function test_can_get_discussion_list_with_search()
142+
{
143+
$this->enableFeature('search');
144+
145+
Post::truncate();
146+
Discussion::truncate();
147+
148+
$group = $this->getGroup();
149+
150+
$discussion = Discussion::create([
151+
'user_id' => $this->getUser()->id,
152+
'title' => 'I want to search for content',
153+
]);
154+
155+
$group->discussions()->save($discussion);
156+
157+
Post::create([
158+
'discussion_id' => $discussion->id,
159+
'user_id' => $this->getUser()->id,
160+
'content' => 'Does Not Match',
161+
]);
162+
163+
$discussionTwo = Discussion::create([
164+
'user_id' => $this->getUser()->id,
165+
'title' => 'I do not like finding content',
166+
]);
167+
168+
$group->discussions()->save($discussionTwo);
169+
170+
Post::create([
171+
'discussion_id' => $discussionTwo->id,
172+
'user_id' => $this->getUser()->id,
173+
'content' => 'Does Not Match',
174+
]);
175+
176+
$discussionThree = Discussion::create([
177+
'user_id' => $this->getUser()->id,
178+
'title' => 'I like finding content in posts',
179+
]);
180+
181+
$group->discussions()->save($discussionThree);
182+
183+
Post::create([
184+
'discussion_id' => $discussionThree->id,
185+
'user_id' => $this->getUser()->id,
186+
'content' => 'Should search for a match',
187+
]);
188+
189+
$this->assertEquals(3, Discussion::count());
190+
$this->assertEquals(3, $this->getGroup()->discussions->count());
191+
192+
$response = $this->actingAs($this->getUser())
193+
->get('forum/g/'.$group->slug.'?search=search');
194+
195+
$discussions = $response->viewData('discussions');
196+
197+
$this->assertEquals(2, $discussions->count());
198+
199+
$this->assertEquals($discussion->id, $discussions->first()->id);
200+
$this->assertEquals($discussionThree->id, $discussions->skip(1)->first()->id);
201+
}
138202
}

tests/TestCase.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public function enableWatchersFeature()
5555
}
5656

5757
/**
58-
* Enable watchers feature in the app config.
58+
* Enable feature in the app config.
5959
*/
6060
public function enableFeature($feature)
6161
{

0 commit comments

Comments
 (0)