This repository has been archived by the owner on Aug 20, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5205913
Showing
11 changed files
with
520 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.DS_Store | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Use MeiliSearch to provide instant search | ||
|
||
[![Statamic 3.0+](https://img.shields.io/badge/Statamic-3.0%2B-FF269E)](https://statamic.com) | ||
[![Commercial License](https://img.shields.io/badge/License-Commercial-yellow)](#) | ||
|
||
This Statamic v3 addon provides an easy way to integrate with [MeiliSearch](https://www.meilisearch.com/), a powerful, fast, open-source, easy to use and deploy search engine. | ||
|
||
## Requirements | ||
|
||
* PHP 7.2+ | ||
* Statamic v3+ | ||
* Laravel 7+ | ||
|
||
## Installation | ||
|
||
You can install this addon via composer with the following command or from the Statamic control panel. | ||
|
||
```bash | ||
composer require kind-work/meili-search | ||
``` | ||
|
||
## Configuration | ||
|
||
### .env | ||
Configure the addon by setting your MeiliSearch URL and API Keys in your `.env` file. | ||
|
||
```yaml | ||
MEILI_URL=http://localhost:7700 | ||
MEILI_MASTER_KEY=your-master-key-here | ||
MEILI_PRIVATE_KEY=your-private-key-here | ||
MEILI_PUBLIC_KEY=your-public-key-here | ||
``` | ||
|
||
After you add your master key you can use the following command to get your private and public keys. | ||
|
||
`php please meili-search:keys` | ||
|
||
### Settings | ||
To configure what collections you would like to index, publish the config file too `config/meili_search.php` by running the following command. Then customize the indexes section of the file. | ||
|
||
```bash | ||
php artisan vendor:publish --tag="meili_search-config" | ||
``` | ||
|
||
## Changelog | ||
|
||
Please see the [Release Notes](https://statamic.com/addons/jrc9designstudio/meili-search/release-notes) for more information what has changed recently. | ||
|
||
## Security | ||
|
||
If you discover any security related issues, please email [security@kind.work](mailto:security@kind.work) instead of using the issue tracker. | ||
|
||
## License | ||
|
||
This is commercial software. You may use the package for your sites. Each site requires its own license. You can purchase a licence from [The Statamic Marketplace](https://statamic.com/addons/jrc9designstudio/meili-search). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{ | ||
"name": "kind-work/meili-search", | ||
"description": "Use MeiliSearch to provide instant search for Statamic V3.", | ||
"type": "statamic-addon", | ||
"require": { | ||
"meilisearch/meilisearch-php": "^0.13.3" | ||
}, | ||
"autoload": { | ||
"psr-4": { | ||
"KindWork\\MeiliSearch\\": "src" | ||
} | ||
}, | ||
"authors": [ | ||
{ | ||
"name": "Jonathan Cohlmeyer" | ||
} | ||
], | ||
"support": { | ||
"email": "help@kind.work" | ||
}, | ||
"extra": { | ||
"statamic": { | ||
"name": "Statamic V3 Meili Search Addon", | ||
"description": "Use MeiliSearch to provide instant search for Statamic V3." | ||
}, | ||
"laravel": { | ||
"providers": [ | ||
"KindWork\\MeiliSearch\\ServiceProvider" | ||
] | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
<?php | ||
|
||
return [ | ||
|
||
/* | ||
|-------------------------------------------------------------------------- | ||
| Meili Address | ||
|-------------------------------------------------------------------------- | ||
| | ||
| This full URL for the Meili server, including protocol and port number IE: | ||
| - http://localhost:7700 | ||
| - https://meili.example.com | ||
| - https://example.com/meili | ||
| | ||
*/ | ||
|
||
'url' => env('MEILI_URL', 'http://localhost:7700'), | ||
|
||
/* | ||
|-------------------------------------------------------------------------- | ||
| Meili Search Master Key | ||
|-------------------------------------------------------------------------- | ||
| | ||
| This master key for your Meili Search instance. Has access to everything! | ||
| | ||
*/ | ||
|
||
'master_key' => env('MEILI_MASTER_KEY', false), | ||
|
||
|
||
/* | ||
|-------------------------------------------------------------------------- | ||
| Meili Search Private Key | ||
|-------------------------------------------------------------------------- | ||
| | ||
| This private key for your Meili Search instance. | ||
| Has access to everything except can not list keys. | ||
| | ||
*/ | ||
|
||
'private_key' => env('MEILI_PRIVATE_KEY', false), | ||
|
||
|
||
/* | ||
|-------------------------------------------------------------------------- | ||
| Meili Search Public Key | ||
|-------------------------------------------------------------------------- | ||
| | ||
| This public key for your Meili Search instance. | ||
| Can search and retrieve documents and get the health status of Meili. | ||
| | ||
*/ | ||
|
||
'public_key' => env('MEILI_PUBLIC_KEY', false), | ||
|
||
|
||
/* | ||
|-------------------------------------------------------------------------- | ||
| Meili Indexes | ||
|-------------------------------------------------------------------------- | ||
| | ||
| Define the indexes you want to use, the collections you want to index | ||
| and the fields you want to index on those collections. | ||
| | ||
*/ | ||
|
||
'indexes' => [ | ||
'kindwork' => [ | ||
'collection:2fa_docs' => [ 'title', 'content' ], | ||
'collection:pages' => [ 'title', 'content' ], | ||
], | ||
], | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
<?php | ||
|
||
namespace KindWork\MeiliSearch\Console\Commands; | ||
|
||
use Config; | ||
use MeiliSearch\Client; | ||
use \Statamic\Facades\Entry; | ||
use Illuminate\Support\Arr; | ||
use Illuminate\Console\Command; | ||
use Statamic\Console\RunsInPlease; | ||
|
||
class DocumentsCommand extends Command { | ||
use RunsInPlease; | ||
|
||
protected $name = 'meili-search:documents'; | ||
protected $description = 'Document convenience commands'; | ||
protected $signature = 'meili-search:documents {method=null} {document=null}'; | ||
protected $methods = ['help', 'update']; | ||
protected $client; | ||
|
||
public function handle() { | ||
$this->client = new Client(Config::get('meili_search.url'), Config::get('meili_search.private_key')); | ||
$method = $this->argument('method'); | ||
|
||
if($method == 'null') { | ||
$this->help(); | ||
} elseif (!in_array($method, $this->methods, true)) { | ||
$this->warn('Method not supported. Supported methods are: ' . join(', ', $this->methods)); | ||
} else { | ||
$this->{$method}(); | ||
} | ||
} | ||
|
||
private function help() { | ||
$this->info('Usage:'); | ||
$this->line(' | ||
meili-search:documents [method=help] [document=null] | ||
'); | ||
$this->info('Methods:'); | ||
$this->line(' | ||
- help Show the help | ||
- update Update or remove documents from the indexes | ||
'); | ||
} | ||
|
||
private function update() { | ||
// Get the indexes configured | ||
$indexes = Config::get('meili_search.indexes'); | ||
|
||
// For each index lets get the documents and update | ||
foreach($indexes as $indexName => $indexConfigs) { | ||
// Say we have stared indexing a specific index | ||
$this->info('Updating index: ' . $indexName); | ||
|
||
// For each index map over the configured collections | ||
// Then collapse them into a 1 dimensional array | ||
$documents = Arr::collapse(array_map(function($config, $fields) { | ||
// Get the collection handle (Maybe get things other than collections later?) | ||
$collectionHandle = explode(':', $config)[1]; | ||
|
||
// Query for the entries in the collection | ||
$entries = Entry::query() | ||
->where('collection', $collectionHandle) | ||
->where('published', true) | ||
->get() | ||
->preProcessForIndex() | ||
->toArray(); | ||
|
||
// Return the document data for indexing with a map | ||
return array_map(function($entry) use($fields) { | ||
|
||
// Merge in the id and fields | ||
return array_merge( | ||
// Add in the entry ID | ||
[ 'id' => $entry ->id() ], | ||
|
||
// Filter to use only the keys defined in the config | ||
array_filter($entry->data()->toArray(), function($key) use($fields) { | ||
return in_array($key, $fields); | ||
}, ARRAY_FILTER_USE_KEY), | ||
|
||
// Add in the entry URLs | ||
[ | ||
'uri' => $entry->uri(), | ||
'api_url' => $entry->apiUrl(), | ||
] | ||
); | ||
}, $entries); | ||
}, array_keys($indexConfigs), $indexConfigs)); | ||
|
||
// Get the index (or make it if it does not exist) | ||
$index = $this->client->getOrCreateIndex($indexName, ['primaryKey' => 'id']); | ||
|
||
// Find the removed document ids | ||
$removedDocuments = array_merge( | ||
array_diff( | ||
array_map(function($entry) { return $entry['id']; }, $index->getDocuments()), | ||
array_map(function($entry) { return $entry['id']; }, $documents) | ||
) | ||
); | ||
|
||
// Delete all the removed documents | ||
$index->deleteDocuments($removedDocuments); | ||
|
||
// Add or update documents | ||
$index->addDocuments($documents); | ||
|
||
// Report back that we are done | ||
$this->info('Finished updating index: ' . $indexName); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
<?php | ||
|
||
namespace KindWork\MeiliSearch\Console\Commands; | ||
|
||
use Config; | ||
use MeiliSearch\Client; | ||
use Illuminate\Console\Command; | ||
use Statamic\Console\RunsInPlease; | ||
|
||
class IndexCommand extends Command { | ||
use RunsInPlease; | ||
|
||
protected $name = 'meili-search:index'; | ||
protected $description = 'Index convenience commands'; | ||
protected $signature = 'meili-search:index {method=null} {index=null}'; | ||
protected $methods = ['help', 'create', 'list', 'clear', 'delete']; | ||
protected $index; | ||
protected $client; | ||
|
||
public function handle() { | ||
$this->index = $this->argument('index'); | ||
$method = $this->argument('method'); | ||
$this->client = new Client(Config::get("meili_search.url"), Config::get("meili_search.private_key")); | ||
|
||
if ($method == 'null') { | ||
$this->help(); | ||
} elseif (!$this->index && $method != 'index') { | ||
$this->warn('A index name is required!'); | ||
} elseif (!in_array($method, $this->methods, true)) { | ||
$this->warn('Method not supported. Supported methods are: ' . join(', ', $this->methods)); | ||
} else { | ||
$this->{$method}(); | ||
} | ||
} | ||
|
||
private function help() { | ||
$this->info('Usage:'); | ||
$this->line(' | ||
meili-search:index [method=help] [index=null] [primaryKey=id] | ||
'); | ||
$this->info('Methods:'); | ||
$this->line(' | ||
- help Show the help | ||
- create Create an search index | ||
- list List all indexes | ||
- clear Clear all the enteries from an index | ||
- delete Delete a search index | ||
'); | ||
$this->info('Arguments:'); | ||
$this->line(' | ||
- index The uid of the index to use | ||
'); | ||
} | ||
|
||
private function create() { | ||
$this->client->createIndex($this->index, ['primaryKey' => 'id']); | ||
$this->info('Index ' . $this->index . ' created'); | ||
} | ||
|
||
private function list() { | ||
$indexes = $this->client->getAllIndexes(); | ||
$this->info('Indexes:'); | ||
foreach($indexes as $index) { | ||
$stats = $index->stats(); | ||
$this->line(' | ||
UID: ' . $index->getUid() . ' | ||
Primary Key: ' . $index->getPrimaryKey() . ' | ||
# of Documents: ' . $stats['numberOfDocuments'] . ' | ||
Is Indexing: ' . ($stats['isIndexing'] ? 'true' : 'false') . ' | ||
'); | ||
} | ||
} | ||
|
||
private function clear() { | ||
$index = $this->client->getIndex($this->index); | ||
$index->deleteAllDocuments(); | ||
$this->info('Index ' . $this->index . ' cleared'); | ||
} | ||
|
||
private function delete() { | ||
$index = $this->client->getIndex($this->index); | ||
$index->delete(); | ||
$this->info('Index ' . $this->index . ' deleted'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
|
||
namespace KindWork\MeiliSearch\Console\Commands; | ||
|
||
use Config; | ||
use MeiliSearch\Client; | ||
use Illuminate\Console\Command; | ||
use Statamic\Console\RunsInPlease; | ||
|
||
class KeysCommand extends Command { | ||
use RunsInPlease; | ||
|
||
protected $name = 'meili-search:keys'; | ||
protected $description = 'Get the master key derived private and public keys'; | ||
protected $signature = 'meili-search:keys'; | ||
protected $client; | ||
|
||
public function handle() { | ||
$this->client = new Client(Config::get("meili_search.url"), Config::get("meili_search.master_key")); | ||
$keys = $this->client->getKeys(); | ||
$this->info('Keys:'); | ||
$this->line(' | ||
Master: ' . Config::get("meili_search.master_key") . ' | ||
Private: ' . $keys['private'] . ' | ||
Public: ' . $keys['public'] . ' | ||
'); | ||
} | ||
} |
Oops, something went wrong.