Skip to content

Commit

Permalink
Merge pull request #23 from amvisor/search
Browse files Browse the repository at this point in the history
introduce full-text search
  • Loading branch information
atmonshi authored Jul 5, 2022
2 parents a30b109 + b621af4 commit 4aa42c8
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 35 deletions.
5 changes: 5 additions & 0 deletions config/zeus-sky.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@
*/
'theme' => 'zeus',

/**
* css class to apply on found search result, e.g. `bg-yellow-400`.
*/
'search_result_highlight_css_class' => 'highlight',

/**
* available locales, this currently used only in tags manager.
*/
Expand Down
18 changes: 18 additions & 0 deletions database/migrations/2022_07_04_104832_add_indices_to_posts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up()
{
Schema::table('posts', function (Blueprint $table) {
$table->index('title');
$table->index('slug');
$table->index('description');
$table->fullText('content');
});
}
};
2 changes: 1 addition & 1 deletion resources/lang/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@
"Post Slug": "الرابط المختصر",
"Write an excerpt for your post": "اكتب ملخص للمقالة",
"Show All posts in": "هرض كافة المثالات في",
"No posts yet": "لاتوجد تدوينات حاليا"
"No posts found": "لاتوجد تدوينات حاليا"
}
2 changes: 1 addition & 1 deletion resources/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@
"Post Slug": "Post Slug",
"Write an excerpt for your post": "Write an excerpt for your post",
"Show All posts in": "Show All posts in",
"No posts yet": "No posts yet"
"No posts found": "No posts found"
}
32 changes: 16 additions & 16 deletions resources/views/themes/zeus/home.blade.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<div>
{{-- You can override the used class in config/zeus-sky.php 'search_result_highlight_css_class'' --}}
<style type="text/css">
span.highlight { background-color: yellow; }
</style>
@unless($stickies->isEmpty())
<div class="mt-10 grid @if($stickies->count() > 1) grid-cols-3 @endif gap-4">
@foreach($stickies as $post)
Expand All @@ -10,23 +14,19 @@
<div class="overflow-x-hidden">
<div class="px-6 py-8">
<div class="container flex justify-between mx-auto gap-6">
@unless ($posts->isEmpty() && $stickies->isEmpty())
<div class="w-3/4">
@unless ($posts->isEmpty())
<div class="flex items-center justify-between">
<h1 class="text-xl font-bold text-gray-700 md:text-2xl">Posts</h1>
</div>
@each($theme.'.partial.post', $posts, 'post')
@else
@include($theme.'.partial.empty')
@endunless
<div class="w-3/4">
@unless ($posts->isEmpty())
<div class="flex items-center justify-between">
<h1 class="text-xl font-bold text-gray-700 md:text-2xl">Posts</h1>
</div>
<div class="w-1/4">
@include($theme.'.partial.sidebar')
</div>
@else
@include($theme.'.partial.empty')
@endunless
@each($theme.'.partial.post', $posts, 'post')
@else
@include($theme.'.partial.empty')
@endunless
</div>
<div class="w-1/4">
@include($theme.'.partial.sidebar')
</div>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion resources/views/themes/zeus/partial/empty.blade.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="px-4 py-4 bg-gradient-to-br from-white via-white to-secondary-50 shadow-lg rounded-3xl hover:shadow-xl transition ease-in-out duration-300 flex gap-2 items-center justify-center w-full h-72 border border-gray-100">
<x-iconpark-wavesleft-o class="h-10 w-10 text-secondary-600" />
<span class="underline decoration-wavy underline-offset-4 decoration-primary-600">{{ __('No posts yet') }}!</span>
<span class="underline decoration-wavy underline-offset-4 decoration-primary-600">{{ __('No posts found') }}!</span>
</div>
1 change: 1 addition & 0 deletions resources/views/themes/zeus/partial/sidebar.blade.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{{--@include($theme.'.partial.authors')--}}
@include($theme.'.partial.sidebar.search')
@include($theme.'.partial.sidebar.categories')
@include($theme.'.partial.sidebar.recent')
@include($theme.'.partial.sidebar.pages')
8 changes: 8 additions & 0 deletions resources/views/themes/zeus/partial/sidebar/search.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div class="px-8">
<h1 class="mb-4 text-xl font-bold text-gray-700">Search</h1>
<div class="flex flex-col max-w-sm px-6 py-4 mx-auto bg-white rounded-lg shadow-md">
<form method="GET">
<input type="text" name="search" value="{{ request()->get('search') }}">
</form>
</div>
</div>
91 changes: 75 additions & 16 deletions src/Http/Livewire/Posts.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace LaraZeus\Sky\Http\Livewire;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\DB;
use LaraZeus\Sky\Models\Post;
use LaraZeus\Sky\Models\Tag;
use Livewire\Component;
Expand All @@ -10,28 +13,84 @@ class Posts extends Component
{
public function render()
{
return view(app('theme').'.home')
->with([
'posts' => Post::NotSticky()
->orderBy('published_at', 'desc')
->get(),
$search = strtolower(request()->get('search'));

'pages' => Post::page()
->orderBy('published_at', 'desc')
->whereNull('parent_id')
->get(),
$posts = Post::NotSticky();
$posts = $this->applySearch($posts, $search);
$posts = $posts
->orderBy('published_at', 'desc')
->get();

'tags' => Tag::withCount('postsPublished')
->where('type', 'category')
->get(), // $this->tag->postsPublished
$pages = Post::page();
$pages = $this->applySearch($pages, $search);
$pages = $pages
->orderBy('published_at', 'desc')
->whereNull('parent_id')
->get();

'stickies' => Post::sticky()->get(),
$pages = $this->highlightSearchResults($pages, $search);
$posts = $this->highlightSearchResults($posts, $search);

'recent' => Post::posts()
->take(config('zeus-sky.site_recent_count', 5))
$recent = Post::posts()
->limit(config('zeus-sky.site_recent_count', 5))
->orderBy('published_at', 'desc')
->get(),
->get();

return view(app('theme').'.home')
->with([
'posts' => $posts,
'pages' => $pages,
'recent' => $recent,
'tags' => Tag::withCount('postsPublished')->where('type', 'category')->get(),
'stickies' => Post::sticky()->get(),
])
->layout(config('zeus-sky.layout'));
}

private function applySearch(Builder $query, string $search): Builder
{
if ($search) {
return $query->where(function ($query) use ($search) {
foreach (['title', 'slug', 'content', 'description'] as $attribute) {
$query->orWhere(DB::raw("lower($attribute)"), 'like', "%$search%");
}

return $query;
});
}

return $query;
}

private function highlightSearchResults(Collection $posts, ?string $search = null): Collection
{
if (! $search) {
return $posts;
}

foreach ($posts as $i => $post) {
$posts[$i]->content = static::hl($post->content, [$search]);
}

return $posts;
}

/**
* Credits for this code goes to link below.
*
* @link https://stackoverflow.com/questions/8564578/php-search-text-highlight-function
*/
public static function hl(string $inp, array $words): string
{
$class = config('zeus-sky.search_result_highlight_css_class', 'highlight');
$replace = array_flip(array_flip($words));
$pattern = [];

foreach ($replace as $k => $fword) {
$pattern[] = '/\b('.$fword.')(?!>)\b/i';
$replace[$k] = sprintf('<span class="%s">$1</span>', $class);
}

return preg_replace($pattern, $replace, $inp);
}
}

0 comments on commit 4aa42c8

Please sign in to comment.