From d85ef4458e4ac4170d5e6fd134b939dd53aab6df Mon Sep 17 00:00:00 2001 From: 3bd-ulrahman <abdulrahman198276301@gmail.com> Date: Tue, 15 Oct 2024 00:30:27 +0300 Subject: [PATCH 01/24] update to algoliasearch-client-php v4 --- composer.json | 2 +- src/EngineManager.php | 12 +++++++---- src/Engines/AlgoliaEngine.php | 34 +++++++++++++++----------------- tests/Unit/AlgoliaEngineTest.php | 2 +- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/composer.json b/composer.json index 7b59fed4..df0d3233 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "symfony/console": "^6.0|^7.0" }, "require-dev": { - "algolia/algoliasearch-client-php": "^3.2", + "algolia/algoliasearch-client-php": "^4.0", "typesense/typesense-php": "^4.9.3", "meilisearch/meilisearch-php": "^1.0", "mockery/mockery": "^1.0", diff --git a/src/EngineManager.php b/src/EngineManager.php index 10b1be8e..16d32354 100644 --- a/src/EngineManager.php +++ b/src/EngineManager.php @@ -2,8 +2,10 @@ namespace Laravel\Scout; -use Algolia\AlgoliaSearch\Config\SearchConfig; -use Algolia\AlgoliaSearch\SearchClient as Algolia; +use Algolia\AlgoliaSearch\Configuration\SearchConfig; +use Algolia\AlgoliaSearch\Api\SearchClient as Algolia; +use Algolia\AlgoliaSearch\Model\Ingestion\Event; +use Algolia\AlgoliaSearch\Support\AlgoliaAgent; use Algolia\AlgoliaSearch\Support\UserAgent; use Exception; use Illuminate\Support\Manager; @@ -39,7 +41,8 @@ public function createAlgoliaDriver() { $this->ensureAlgoliaClientIsInstalled(); - UserAgent::addCustomUserAgent('Laravel Scout', Scout::VERSION); + // UserAgent::addCustomUserAgent('Laravel Scout', Scout::VERSION); + AlgoliaAgent::addAlgoliaAgent('Laravel Scout', 'Laravel Scout', Scout::VERSION); $config = SearchConfig::create( config('scout.algolia.id'), @@ -61,7 +64,8 @@ public function createAlgoliaDriver() } if (is_int($batchSize = config('scout.algolia.batch_size'))) { - $config->setBatchSize($batchSize); + // $config->setBatchSize($batchSize); + (new Event())->setBatchSize($batchSize); } return new AlgoliaEngine(Algolia::createWithConfig($config), config('scout.soft_delete')); diff --git a/src/Engines/AlgoliaEngine.php b/src/Engines/AlgoliaEngine.php index cec72d48..8b5b6a41 100644 --- a/src/Engines/AlgoliaEngine.php +++ b/src/Engines/AlgoliaEngine.php @@ -2,7 +2,7 @@ namespace Laravel\Scout\Engines; -use Algolia\AlgoliaSearch\SearchClient as Algolia; +use Algolia\AlgoliaSearch\Api\SearchClient as Algolia; use Exception; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\LazyCollection; @@ -14,7 +14,7 @@ class AlgoliaEngine extends Engine /** * The Algolia client. * - * @var \Algolia\AlgoliaSearch\SearchClient + * @var \Algolia\AlgoliaSearch\Api\SearchClient */ protected $algolia; @@ -28,7 +28,7 @@ class AlgoliaEngine extends Engine /** * Create a new engine instance. * - * @param \Algolia\AlgoliaSearch\SearchClient $algolia + * @param \Algolia\AlgoliaSearch\Api\SearchClient $algolia * @param bool $softDelete * @return void */ @@ -52,7 +52,7 @@ public function update($models) return; } - $index = $this->algolia->initIndex($models->first()->indexableAs()); + $index = $models->first()->indexableAs(); if ($this->usesSoftDelete($models->first()) && $this->softDelete) { $models->each->pushSoftDeleteMetadata(); @@ -71,7 +71,7 @@ public function update($models) })->filter()->values()->all(); if (! empty($objects)) { - $index->saveObjects($objects); + $this->algolia->saveObjects($index, $objects); } } @@ -87,13 +87,11 @@ public function delete($models) return; } - $index = $this->algolia->initIndex($models->first()->indexableAs()); - $keys = $models instanceof RemoveableScoutCollection ? $models->pluck($models->first()->getScoutKeyName()) : $models->map->getScoutKey(); - $index->deleteObjects($keys->all()); + $this->algolia->deleteObjects($models->first()->indexableAs(), $keys->all()); } /** @@ -136,22 +134,24 @@ public function paginate(Builder $builder, $perPage, $page) */ protected function performSearch(Builder $builder, array $options = []) { - $algolia = $this->algolia->initIndex( - $builder->index ?: $builder->model->searchableAs() - ); - $options = array_merge($builder->options, $options); if ($builder->callback) { return call_user_func( $builder->callback, - $algolia, + $this->algolia, $builder->query, $options ); } - return $algolia->search($builder->query, $options); + $queryParams = ['query' => $builder->query]; + + return $this->algolia->searchSingleIndex( + $builder->index ?: $builder->model->searchableAs(), + $queryParams, + $options + ); } /** @@ -280,9 +280,7 @@ public function getTotalCount($results) */ public function flush($model) { - $index = $this->algolia->initIndex($model->indexableAs()); - - $index->clearObjects(); + $this->algolia->clearObjects($model->indexableAs()); } /** @@ -307,7 +305,7 @@ public function createIndex($name, array $options = []) */ public function deleteIndex($name) { - return $this->algolia->initIndex($name)->delete(); + return $this->algolia->deleteIndex($name); } /** diff --git a/tests/Unit/AlgoliaEngineTest.php b/tests/Unit/AlgoliaEngineTest.php index 98c991b1..fc27077a 100644 --- a/tests/Unit/AlgoliaEngineTest.php +++ b/tests/Unit/AlgoliaEngineTest.php @@ -2,7 +2,7 @@ namespace Laravel\Scout\Tests\Unit; -use Algolia\AlgoliaSearch\SearchClient; +use Algolia\AlgoliaSearch\Api\SearchClient; use Illuminate\Container\Container; use Illuminate\Database\Eloquent\Collection; use Illuminate\Support\Facades\Config; From 6f2cdee8ef9c6506fb2e3519bd71ce3331301806 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Thu, 7 Nov 2024 12:13:58 +0800 Subject: [PATCH 02/24] Fixes tests Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- tests/Unit/AlgoliaEngineTest.php | 42 +++++++++++++++----------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/tests/Unit/AlgoliaEngineTest.php b/tests/Unit/AlgoliaEngineTest.php index fc27077a..06177c6a 100644 --- a/tests/Unit/AlgoliaEngineTest.php +++ b/tests/Unit/AlgoliaEngineTest.php @@ -48,8 +48,7 @@ public function test_update_adds_objects_to_index() public function test_delete_removes_objects_to_index() { $client = m::mock(SearchClient::class); - $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); - $index->shouldReceive('deleteObjects')->with([1]); + $client->shouldReceive('deleteObjects')->with('table', [1]); $engine = new AlgoliaEngine($client); $engine->delete(Collection::make([new SearchableModel(['id' => 1])])); @@ -58,8 +57,7 @@ public function test_delete_removes_objects_to_index() public function test_delete_removes_objects_to_index_with_a_custom_search_key() { $client = m::mock(SearchClient::class); - $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(Indexes::class)); - $index->shouldReceive('deleteObjects')->once()->with(['my-algolia-key.5']); + $client->shouldReceive('deleteObjects')->once()->with('table', ['my-algolia-key.5']); $engine = new AlgoliaEngine($client); $engine->delete(Collection::make([new AlgoliaCustomKeySearchableModel(['id' => 5])])); @@ -74,8 +72,7 @@ public function test_delete_with_removeable_scout_collection_using_custom_search $job = unserialize(serialize($job)); $client = m::mock(SearchClient::class); - $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); - $index->shouldReceive('deleteObjects')->once()->with(['my-algolia-key.5']); + $client->shouldReceive('deleteObjects')->once()->with('table', ['my-algolia-key.5']); $engine = new AlgoliaEngine($client); $engine->delete($job->models); @@ -111,10 +108,11 @@ public function test_remove_from_search_job_uses_custom_search_key() public function test_search_sends_correct_parameters_to_algolia() { $client = m::mock(SearchClient::class); - $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); - $index->shouldReceive('search')->with('zonda', [ - 'numericFilters' => ['foo=1'], - ]); + $client->shouldReceive('searchSingleIndex')->with( + 'table', + ['query' => 'zonda'], + ['numericFilters' => ['foo=1']] + ); $engine = new AlgoliaEngine($client); $builder = new Builder(new SearchableModel, 'zonda'); @@ -125,10 +123,11 @@ public function test_search_sends_correct_parameters_to_algolia() public function test_search_sends_correct_parameters_to_algolia_for_where_in_search() { $client = m::mock(SearchClient::class); - $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); - $index->shouldReceive('search')->with('zonda', [ - 'numericFilters' => ['foo=1', ['bar=1', 'bar=2']], - ]); + $client->shouldReceive('searchSingleIndex')->with( + 'table', + ['query' => 'zonda'], + ['numericFilters' => ['foo=1', ['bar=1', 'bar=2']]] + ); $engine = new AlgoliaEngine($client); $builder = new Builder(new SearchableModel, 'zonda'); @@ -139,10 +138,11 @@ public function test_search_sends_correct_parameters_to_algolia_for_where_in_sea public function test_search_sends_correct_parameters_to_algolia_for_empty_where_in_search() { $client = m::mock(SearchClient::class); - $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); - $index->shouldReceive('search')->with('zonda', [ - 'numericFilters' => ['foo=1', '0=1'], - ]); + $client->shouldReceive('searchSingleIndex')->with( + 'table', + ['query' => 'zonda'], + ['numericFilters' => ['foo=1', '0=1']] + ); $engine = new AlgoliaEngine($client); $builder = new Builder(new SearchableModel, 'zonda'); @@ -280,8 +280,7 @@ public function test_a_model_is_indexed_with_a_custom_algolia_key() public function test_a_model_is_removed_with_a_custom_algolia_key() { $client = m::mock(SearchClient::class); - $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); - $index->shouldReceive('deleteObjects')->with(['my-algolia-key.1']); + $client->shouldReceive('deleteObjects')->with('table', ['my-algolia-key.1']); $engine = new AlgoliaEngine($client); $engine->delete(Collection::make([new AlgoliaCustomKeySearchableModel(['id' => 1])])); @@ -290,8 +289,7 @@ public function test_a_model_is_removed_with_a_custom_algolia_key() public function test_flush_a_model_with_a_custom_algolia_key() { $client = m::mock(SearchClient::class); - $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); - $index->shouldReceive('clearObjects'); + $client->shouldReceive('clearObjects')->with('table'); $engine = new AlgoliaEngine($client); $engine->flush(new AlgoliaCustomKeySearchableModel); From 1f89224665b9e177eabd85aae3566cb5700ea777 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Thu, 7 Nov 2024 12:16:00 +0800 Subject: [PATCH 03/24] wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- composer.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/composer.json b/composer.json index df0d3233..eed9db7f 100644 --- a/composer.json +++ b/composer.json @@ -34,6 +34,9 @@ "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9.3|^10.4" }, + "conflict": { + "algolia/algoliasearch-client-php": "<4.0.0|>=5.0.0" + }, "autoload": { "psr-4": { "Laravel\\Scout\\": "src/" From 8fce0d3a6aaee29eee879ddcdbe0ad10483d3691 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Thu, 7 Nov 2024 12:19:13 +0800 Subject: [PATCH 04/24] wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- tests/Integration/AlgoliaSearchableTest.php | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/tests/Integration/AlgoliaSearchableTest.php b/tests/Integration/AlgoliaSearchableTest.php index 42c1b23c..66d977fc 100644 --- a/tests/Integration/AlgoliaSearchableTest.php +++ b/tests/Integration/AlgoliaSearchableTest.php @@ -4,30 +4,17 @@ use Illuminate\Support\Env; use Laravel\Scout\Tests\Fixtures\User; +use Orchestra\Testbench\Attributes\RequiresEnv; /** * @group algolia * @group external-network */ +#[RequiresEnv('ALGOLIA_APP_ID')] class AlgoliaSearchableTest extends TestCase { use SearchableTests; - /** - * Define environment setup. - * - * @param \Illuminate\Foundation\Application $app - * @return void - */ - protected function defineEnvironment($app) - { - if (is_null(Env::get('ALGOLIA_APP_ID'))) { - $this->markTestSkipped(); - } - - $this->defineScoutEnvironment($app); - } - /** * Define database migrations. * From 7a253d2c413e0a97eb199c945d7b89814a596b14 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Thu, 7 Nov 2024 12:24:18 +0800 Subject: [PATCH 05/24] wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- tests/Integration/AlgoliaSearchableTest.php | 11 +++++++++++ tests/Integration/MeilisearchSearchableTest.php | 8 ++------ tests/Integration/TypesenseSearchableTest.php | 5 +---- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/tests/Integration/AlgoliaSearchableTest.php b/tests/Integration/AlgoliaSearchableTest.php index 66d977fc..5ddfa559 100644 --- a/tests/Integration/AlgoliaSearchableTest.php +++ b/tests/Integration/AlgoliaSearchableTest.php @@ -15,6 +15,17 @@ class AlgoliaSearchableTest extends TestCase { use SearchableTests; + /** + * Define environment setup. + * + * @param \Illuminate\Foundation\Application $app + * @return void + */ + protected function defineEnvironment($app) + { + $this->defineScoutEnvironment($app); + } + /** * Define database migrations. * diff --git a/tests/Integration/MeilisearchSearchableTest.php b/tests/Integration/MeilisearchSearchableTest.php index 2fd9ad41..322cfd20 100644 --- a/tests/Integration/MeilisearchSearchableTest.php +++ b/tests/Integration/MeilisearchSearchableTest.php @@ -11,11 +11,13 @@ use Meilisearch\Client; use Meilisearch\Endpoints\Indexes; use Mockery as m; +use Orchestra\Testbench\Attributes\RequiresEnv; /** * @group meilisearch * @group external-network */ +#[RequiresEnv('MEILISEARCH_HOST')] class MeilisearchSearchableTest extends TestCase { use SearchableTests { @@ -30,12 +32,6 @@ class MeilisearchSearchableTest extends TestCase */ protected function defineEnvironment($app) { - if (is_null(Env::get('MEILISEARCH_HOST'))) { - $this->markTestSkipped(); - - return; - } - $this->defineScoutEnvironment($app); } diff --git a/tests/Integration/TypesenseSearchableTest.php b/tests/Integration/TypesenseSearchableTest.php index c6405f25..a25c4fde 100644 --- a/tests/Integration/TypesenseSearchableTest.php +++ b/tests/Integration/TypesenseSearchableTest.php @@ -9,6 +9,7 @@ * @group typesense * @group external-network */ +#[RequiresEnv('TYPESENSE_API_KEY')] class TypesenseSearchableTest extends TestCase { use SearchableTests; @@ -21,10 +22,6 @@ class TypesenseSearchableTest extends TestCase */ protected function defineEnvironment($app) { - if (is_null(Env::get('TYPESENSE_API_KEY'))) { - $this->markTestSkipped(); - } - $this->defineScoutEnvironment($app); } From 43a7c8f5dcdf64c4bed30b0b25a79e68c64ecd73 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Thu, 7 Nov 2024 12:26:30 +0800 Subject: [PATCH 06/24] wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- src/EngineManager.php | 2 +- tests/Integration/AlgoliaSearchableTest.php | 1 - tests/Integration/MeilisearchSearchableTest.php | 1 - tests/Integration/TypesenseSearchableTest.php | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/EngineManager.php b/src/EngineManager.php index 16d32354..d2c48ab1 100644 --- a/src/EngineManager.php +++ b/src/EngineManager.php @@ -2,8 +2,8 @@ namespace Laravel\Scout; -use Algolia\AlgoliaSearch\Configuration\SearchConfig; use Algolia\AlgoliaSearch\Api\SearchClient as Algolia; +use Algolia\AlgoliaSearch\Configuration\SearchConfig; use Algolia\AlgoliaSearch\Model\Ingestion\Event; use Algolia\AlgoliaSearch\Support\AlgoliaAgent; use Algolia\AlgoliaSearch\Support\UserAgent; diff --git a/tests/Integration/AlgoliaSearchableTest.php b/tests/Integration/AlgoliaSearchableTest.php index 5ddfa559..76ce55d0 100644 --- a/tests/Integration/AlgoliaSearchableTest.php +++ b/tests/Integration/AlgoliaSearchableTest.php @@ -2,7 +2,6 @@ namespace Laravel\Scout\Tests\Integration; -use Illuminate\Support\Env; use Laravel\Scout\Tests\Fixtures\User; use Orchestra\Testbench\Attributes\RequiresEnv; diff --git a/tests/Integration/MeilisearchSearchableTest.php b/tests/Integration/MeilisearchSearchableTest.php index 322cfd20..0881fac1 100644 --- a/tests/Integration/MeilisearchSearchableTest.php +++ b/tests/Integration/MeilisearchSearchableTest.php @@ -3,7 +3,6 @@ namespace Laravel\Scout\Tests\Integration; use Illuminate\Database\Eloquent\Collection; -use Illuminate\Support\Env; use Laravel\Scout\Builder; use Laravel\Scout\Engines\MeilisearchEngine; use Laravel\Scout\Tests\Fixtures\User; diff --git a/tests/Integration/TypesenseSearchableTest.php b/tests/Integration/TypesenseSearchableTest.php index a25c4fde..c388f368 100644 --- a/tests/Integration/TypesenseSearchableTest.php +++ b/tests/Integration/TypesenseSearchableTest.php @@ -2,7 +2,6 @@ namespace Laravel\Scout\Tests\Integration; -use Illuminate\Support\Env; use Laravel\Scout\Tests\Fixtures\User; /** From 25605a352b9f47b82740f3b74166d795a9b02598 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Thu, 7 Nov 2024 12:28:28 +0800 Subject: [PATCH 07/24] wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- tests/Integration/TypesenseSearchableTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Integration/TypesenseSearchableTest.php b/tests/Integration/TypesenseSearchableTest.php index c388f368..237bd468 100644 --- a/tests/Integration/TypesenseSearchableTest.php +++ b/tests/Integration/TypesenseSearchableTest.php @@ -3,6 +3,7 @@ namespace Laravel\Scout\Tests\Integration; use Laravel\Scout\Tests\Fixtures\User; +use Orchestra\Testbench\Attributes\RequiresEnv; /** * @group typesense From a3689ab5da5caf11a0cd70472b8f018218144acb Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Thu, 7 Nov 2024 12:32:34 +0800 Subject: [PATCH 08/24] wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- tests/Integration/TestCase.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/Integration/TestCase.php b/tests/Integration/TestCase.php index 73f6be09..caad2db6 100644 --- a/tests/Integration/TestCase.php +++ b/tests/Integration/TestCase.php @@ -29,9 +29,11 @@ protected function importScoutIndexFrom($model = null) */ public static function tearDownAfterClass(): void { - remote('scout:delete-all-indexes', [ - 'SCOUT_DRIVER' => static::scoutDriver(), - ])->mustRun(); + rescue(function () { + remote('scout:delete-all-indexes', [ + 'SCOUT_DRIVER' => static::scoutDriver(), + ])->mustRun(); + }); parent::tearDownAfterClass(); } From 8e3e6288337d3fdeb04d0fb63df68fd27c4ed45c Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Thu, 7 Nov 2024 12:34:38 +0800 Subject: [PATCH 09/24] wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5f468fe3..692bc3a2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -90,7 +90,7 @@ jobs: composer update --prefer-dist --no-interaction --no-progress - name: Execute tests - run: vendor/bin/phpunit --group external-network,meilisearch + run: vendor/bin/phpunit --group meilisearch env: MEILISEARCH_HOST: "http://localhost:7700" MEILISEARCH_KEY: 'masterKey' From 2bf18d9c90bdacfc73499b0719f34efbea0b4de6 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Thu, 7 Nov 2024 12:35:11 +0800 Subject: [PATCH 10/24] wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- tests/Integration/TestCase.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/Integration/TestCase.php b/tests/Integration/TestCase.php index caad2db6..73f6be09 100644 --- a/tests/Integration/TestCase.php +++ b/tests/Integration/TestCase.php @@ -29,11 +29,9 @@ protected function importScoutIndexFrom($model = null) */ public static function tearDownAfterClass(): void { - rescue(function () { - remote('scout:delete-all-indexes', [ - 'SCOUT_DRIVER' => static::scoutDriver(), - ])->mustRun(); - }); + remote('scout:delete-all-indexes', [ + 'SCOUT_DRIVER' => static::scoutDriver(), + ])->mustRun(); parent::tearDownAfterClass(); } From cbc914f5df17064c20c7ea42c7584fb6cb20aaa9 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Thu, 7 Nov 2024 12:35:57 +0800 Subject: [PATCH 11/24] Apply suggestions from code review --- src/EngineManager.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/EngineManager.php b/src/EngineManager.php index d2c48ab1..930b26b3 100644 --- a/src/EngineManager.php +++ b/src/EngineManager.php @@ -41,7 +41,6 @@ public function createAlgoliaDriver() { $this->ensureAlgoliaClientIsInstalled(); - // UserAgent::addCustomUserAgent('Laravel Scout', Scout::VERSION); AlgoliaAgent::addAlgoliaAgent('Laravel Scout', 'Laravel Scout', Scout::VERSION); $config = SearchConfig::create( @@ -64,7 +63,6 @@ public function createAlgoliaDriver() } if (is_int($batchSize = config('scout.algolia.batch_size'))) { - // $config->setBatchSize($batchSize); (new Event())->setBatchSize($batchSize); } From 70480de377656252596fc88e1296da3871c98c6d Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Thu, 7 Nov 2024 12:38:29 +0800 Subject: [PATCH 12/24] Update EngineManager.php --- src/EngineManager.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/EngineManager.php b/src/EngineManager.php index 930b26b3..c199ce23 100644 --- a/src/EngineManager.php +++ b/src/EngineManager.php @@ -6,7 +6,6 @@ use Algolia\AlgoliaSearch\Configuration\SearchConfig; use Algolia\AlgoliaSearch\Model\Ingestion\Event; use Algolia\AlgoliaSearch\Support\AlgoliaAgent; -use Algolia\AlgoliaSearch\Support\UserAgent; use Exception; use Illuminate\Support\Manager; use Laravel\Scout\Engines\AlgoliaEngine; From f37d448d40bf6ce9be812cb33d882372468d9833 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Thu, 7 Nov 2024 14:32:27 +0800 Subject: [PATCH 13/24] Update composer.json --- composer.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/composer.json b/composer.json index eed9db7f..df0d3233 100644 --- a/composer.json +++ b/composer.json @@ -34,9 +34,6 @@ "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9.3|^10.4" }, - "conflict": { - "algolia/algoliasearch-client-php": "<4.0.0|>=5.0.0" - }, "autoload": { "psr-4": { "Laravel\\Scout\\": "src/" From 29e23c93e960671825effd669ee7ca72665db5c1 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Thu, 7 Nov 2024 14:57:14 +0800 Subject: [PATCH 14/24] wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- .github/workflows/tests.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 692bc3a2..bf4ab9aa 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -90,7 +90,8 @@ jobs: composer update --prefer-dist --no-interaction --no-progress - name: Execute tests - run: vendor/bin/phpunit --group meilisearch + run: vendor/bin/phpunit --no-configuration --no-coverage --color --bootstrap vendor/autoload.php --group meilisearch tests/Integration env: MEILISEARCH_HOST: "http://localhost:7700" MEILISEARCH_KEY: 'masterKey' + DB_CONNECTION: 'testing' From 096b330dc0045e86ff63d6ff83d1f21f43c80edd Mon Sep 17 00:00:00 2001 From: Taylor Otwell <taylor@laravel.com> Date: Fri, 8 Nov 2024 08:20:27 +1000 Subject: [PATCH 15/24] Update EngineManager.php --- src/EngineManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EngineManager.php b/src/EngineManager.php index c199ce23..3ac6fc6c 100644 --- a/src/EngineManager.php +++ b/src/EngineManager.php @@ -62,7 +62,7 @@ public function createAlgoliaDriver() } if (is_int($batchSize = config('scout.algolia.batch_size'))) { - (new Event())->setBatchSize($batchSize); + (new Event)->setBatchSize($batchSize); } return new AlgoliaEngine(Algolia::createWithConfig($config), config('scout.soft_delete')); From 827a97f8e3423a82c8438557a42cdc69811ae0ee Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Fri, 8 Nov 2024 07:24:04 +0800 Subject: [PATCH 16/24] wip --- src/EngineManager.php | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/EngineManager.php b/src/EngineManager.php index 3ac6fc6c..b03907cc 100644 --- a/src/EngineManager.php +++ b/src/EngineManager.php @@ -4,7 +4,6 @@ use Algolia\AlgoliaSearch\Api\SearchClient as Algolia; use Algolia\AlgoliaSearch\Configuration\SearchConfig; -use Algolia\AlgoliaSearch\Model\Ingestion\Event; use Algolia\AlgoliaSearch\Support\AlgoliaAgent; use Exception; use Illuminate\Support\Manager; @@ -42,10 +41,12 @@ public function createAlgoliaDriver() AlgoliaAgent::addAlgoliaAgent('Laravel Scout', 'Laravel Scout', Scout::VERSION); - $config = SearchConfig::create( - config('scout.algolia.id'), - config('scout.algolia.secret') - )->setDefaultHeaders( + $config = (new SearchConfig(array_merge([ + 'appId' => config('scout.algolia.id'), + 'apiKey' => config('scout.algolia.secret'), + ]), array_filter([ + 'batchSize' => config('scout.algolia.batch_size'), + ])))->setDefaultHeaders( $this->defaultAlgoliaHeaders() ); @@ -61,10 +62,6 @@ public function createAlgoliaDriver() $config->setWriteTimeout($writeTimeout); } - if (is_int($batchSize = config('scout.algolia.batch_size'))) { - (new Event)->setBatchSize($batchSize); - } - return new AlgoliaEngine(Algolia::createWithConfig($config), config('scout.soft_delete')); } From b487bea1bbeb7abc7194f1069984ed9169fe3729 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Fri, 8 Nov 2024 15:14:14 +0800 Subject: [PATCH 17/24] wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- .github/workflows/tests.yml | 5 +- composer.json | 2 +- src/EngineManager.php | 50 ++- src/Engines/Algolia3Engine.php | 173 +++++++++ src/Engines/Algolia4Engine.php | 170 +++++++++ src/Engines/AlgoliaEngine.php | 127 ++----- tests/Unit/Algolia3EngineTest.php | 327 ++++++++++++++++++ ...aEngineTest.php => Algolia4EngineTest.php} | 52 +-- 8 files changed, 769 insertions(+), 137 deletions(-) create mode 100644 src/Engines/Algolia3Engine.php create mode 100644 src/Engines/Algolia4Engine.php create mode 100644 tests/Unit/Algolia3EngineTest.php rename tests/Unit/{AlgoliaEngineTest.php => Algolia4EngineTest.php} (87%) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bf4ab9aa..b9922876 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,8 +19,6 @@ jobs: php: ['8.0', 8.1, 8.2, 8.3] laravel: [9, 10, 11] exclude: - - php: '8.0' - laravel: 9 - php: '8.0' laravel: 10 - php: '8.0' @@ -47,8 +45,7 @@ jobs: - name: Install dependencies run: | - composer require "illuminate/contracts=^${{ matrix.laravel }}" --no-update - composer update --prefer-dist --no-interaction --no-progress + composer update --prefer-dist --no-interaction --no-progress --with="illuminate/contracts=^${{ matrix.laravel }}" - name: Execute tests run: vendor/bin/phpunit diff --git a/composer.json b/composer.json index df0d3233..a86a6d4e 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "symfony/console": "^6.0|^7.0" }, "require-dev": { - "algolia/algoliasearch-client-php": "^4.0", + "algolia/algoliasearch-client-php": "^3.2|^4.0", "typesense/typesense-php": "^4.9.3", "meilisearch/meilisearch-php": "^1.0", "mockery/mockery": "^1.0", diff --git a/src/EngineManager.php b/src/EngineManager.php index b03907cc..b739a9b0 100644 --- a/src/EngineManager.php +++ b/src/EngineManager.php @@ -2,9 +2,9 @@ namespace Laravel\Scout; -use Algolia\AlgoliaSearch\Api\SearchClient as Algolia; -use Algolia\AlgoliaSearch\Configuration\SearchConfig; -use Algolia\AlgoliaSearch\Support\AlgoliaAgent; +use Algolia\AlgoliaSearch\Algolia; +use Algolia\AlgoliaSearch\Support\AlgoliaAgent as Algolia4UserAgent; +use Algolia\AlgoliaSearch\Support\UserAgent as Algolia3UserAgent; use Exception; use Illuminate\Support\Manager; use Laravel\Scout\Engines\AlgoliaEngine; @@ -31,7 +31,7 @@ public function engine($name = null) } /** - * Create an Algolia engine instance. + * Create a Meilisearch engine instance. * * @return \Laravel\Scout\Engines\AlgoliaEngine */ @@ -39,14 +39,24 @@ public function createAlgoliaDriver() { $this->ensureAlgoliaClientIsInstalled(); - AlgoliaAgent::addAlgoliaAgent('Laravel Scout', 'Laravel Scout', Scout::VERSION); + return version_compare(Algolia::VERSION, '4.0.0', '>=') + ? $this->configureAlgolia4Driver() + : $this->configureAlgolia3Driver(); + } + + /** + * Create an Algolia v4 engine instance. + * + * @return \Laravel\Scout\Engines\Algolia3Engine + */ + protected function configureAlgolia3Driver() + { + Algolia3UserAgent::addCustomUserAgent('Laravel Scout', Scout::VERSION); - $config = (new SearchConfig(array_merge([ - 'appId' => config('scout.algolia.id'), - 'apiKey' => config('scout.algolia.secret'), - ]), array_filter([ - 'batchSize' => config('scout.algolia.batch_size'), - ])))->setDefaultHeaders( + $config = SearchConfig::create( + config('scout.algolia.id'), + config('scout.algolia.secret') + )->setDefaultHeaders( $this->defaultAlgoliaHeaders() ); @@ -62,9 +72,25 @@ public function createAlgoliaDriver() $config->setWriteTimeout($writeTimeout); } + if (is_int($batchSize = config('scout.algolia.batch_size'))) { + $config->setBatchSize($batchSize); + } + return new AlgoliaEngine(Algolia::createWithConfig($config), config('scout.soft_delete')); } + /** + * Create an Algolia v4 engine instance. + * + * @return \Laravel\Scout\Engines\Algolia4Engine + */ + protected function configureAlgolia4Driver() + { + Algolia4UserAgent::addAlgoliaAgent('Laravel Scout', 'Laravel Scout', Scout::VERSION); + + return Algolia4Engine::make(config('scout.algolia'), config('scout.soft_delete')); + } + /** * Ensure the Algolia API client is installed. * @@ -79,7 +105,7 @@ protected function ensureAlgoliaClientIsInstalled() } if (class_exists('AlgoliaSearch\Client')) { - throw new Exception('Please upgrade your Algolia client to version: ^3.2.'); + throw new Exception('Please upgrade your Algolia client to version: ^3.2|^4.0.'); } throw new Exception('Please install the suggested Algolia client: algolia/algoliasearch-client-php.'); diff --git a/src/Engines/Algolia3Engine.php b/src/Engines/Algolia3Engine.php new file mode 100644 index 00000000..a4239fe8 --- /dev/null +++ b/src/Engines/Algolia3Engine.php @@ -0,0 +1,173 @@ +<?php + +namespace Laravel\Scout\Engines; + +use Algolia\AlgoliaSearch\Config\SearchConfig as Algolia3SearchConfig; +use Algolia\AlgoliaSearch\SearchClient as Algolia3SearchClient; +use Exception; +use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Support\LazyCollection; +use Laravel\Scout\Builder; +use Laravel\Scout\Jobs\RemoveableScoutCollection; + +/** + * @template TAlgoliaClient of \Algolia\AlgoliaSearch\SearchClient + */ +class Algolia3Engine extends AlgoliaEngine +{ + /** + * Create a new engine instance. + * + * @param TAlgoliaClient $algolia + * @param bool $softDelete + * @return void + */ + public function __construct(Algolia3SearchClient $algolia, $softDelete = false) + { + parent::__construct($algolia, $softDelete); + } + + /** + * Make a new engine instance. + * + * @param array $config + * @param bool $softDelete + * @return static + */ + public static function make(array $config, bool $softDelete = false) + { + $config = Algolia3SearchConfig::create([ + 'appId' => $config['id'], + 'apiKey' => $config['secret'], + ])->setDefaultHeaders( + $this->defaultAlgoliaHeaders() + ); + + if (is_int($connectTimeout = $config['connect_timeout'])) { + $configuration->setConnectTimeout($connectTimeout); + } + + if (is_int($readTimeout = $config['read_timeout'])) { + $configuration->setReadTimeout($readTimeout); + } + + if (is_int($writeTimeout = $config['write_timeout'])) { + $configuration->setWriteTimeout($writeTimeout); + } + + if (is_int($batchSize = $config['batch_size'])) { + $configuration->setBatchSize($batchSize); + } + + return new static(Algolia3SearchClient::createWithConfig($configuration), $softDelete); + } + + /** + * Update the given model in the index. + * + * @param \Illuminate\Database\Eloquent\Collection $models + * @return void + * + * @throws \Algolia\AlgoliaSearch\Exceptions\AlgoliaException + */ + public function update($models) + { + if ($models->isEmpty()) { + return; + } + + $index = $this->algolia->initIndex($models->first()->indexableAs()); + + if ($this->usesSoftDelete($models->first()) && $this->softDelete) { + $models->each->pushSoftDeleteMetadata(); + } + + $objects = $models->map(function ($model) { + if (empty($searchableData = $model->toSearchableArray())) { + return; + } + + return array_merge( + $searchableData, + $model->scoutMetadata(), + ['objectID' => $model->getScoutKey()], + ); + })->filter()->values()->all(); + + if (! empty($objects)) { + $index->saveObjects($objects); + } + } + + /** + * Remove the given model from the index. + * + * @param \Illuminate\Database\Eloquent\Collection $models + * @return void + */ + public function delete($models) + { + if ($models->isEmpty()) { + return; + } + + $index = $this->algolia->initIndex($models->first()->indexableAs()); + + $keys = $models instanceof RemoveableScoutCollection + ? $models->pluck($models->first()->getScoutKeyName()) + : $models->map->getScoutKey(); + + $index->deleteObjects($keys->all()); + } + + /** + * Delete a search index. + * + * @param string $name + * @return mixed + */ + public function deleteIndex($name) + { + return $this->algolia->initIndex($name)->delete(); + } + + /** + * Flush all of the model's records from the engine. + * + * @param \Illuminate\Database\Eloquent\Model $model + * @return void + */ + public function flush($model) + { + $index = $this->algolia->initIndex($model->indexableAs()); + + $index->clearObjects(); + } + + /** + * Perform the given search on the engine. + * + * @param \Laravel\Scout\Builder $builder + * @param array $options + * @return mixed + */ + protected function performSearch(Builder $builder, array $options = []) + { + $algolia = $this->algolia->initIndex( + $builder->index ?: $builder->model->searchableAs() + ); + + $options = array_merge($builder->options, $options); + + if ($builder->callback) { + return call_user_func( + $builder->callback, + $algolia, + $builder->query, + $options + ); + } + + return $algolia->search($builder->query, $options); + } +} diff --git a/src/Engines/Algolia4Engine.php b/src/Engines/Algolia4Engine.php new file mode 100644 index 00000000..d88857c6 --- /dev/null +++ b/src/Engines/Algolia4Engine.php @@ -0,0 +1,170 @@ +<?php + +namespace Laravel\Scout\Engines; + +use Algolia\AlgoliaSearch\Api\SearchClient as Algolia4SearchClient; +use Algolia\AlgoliaSearch\Configuration\SearchConfig as Algolia4SearchConfig; +use Algolia\AlgoliaSearch\Support\AlgoliaAgent as Algolia4UserAgent; +use Exception; +use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Support\LazyCollection; +use Laravel\Scout\Builder; +use Laravel\Scout\Jobs\RemoveableScoutCollection; + +/** + * @template TAlgoliaClient of \Algolia\AlgoliaSearch\Api\SearchClient + */ +class Algolia4Engine extends AlgoliaEngine +{ + /** + * Create a new engine instance. + * + * @param TAlgoliaClient $algolia + * @param bool $softDelete + * @return void + */ + public function __construct(Algolia4SearchClient $algolia, $softDelete = false) + { + parent::__construct($algolia, $softDelete); + } + + /** + * Make a new engine instance. + * + * @param array $config + * @param bool $softDelete + * @return static + */ + public static function make(array $config, bool $softDelete = false) + { + $configuration = (new Algolia4SearchConfig(array_merge([ + 'appId' => $config['id'], + 'apiKey' => $config['secret'], + ]), array_filter([ + 'batchSize' => $config['batch_size'], + ])))->setDefaultHeaders( + $this->defaultAlgoliaHeaders() + ); + + if (is_int($connectTimeout = $config['connect_timeout'])) { + $configuration->setConnectTimeout($connectTimeout); + } + + if (is_int($readTimeout = $config['read_timeout'])) { + $configuration->setReadTimeout($readTimeout); + } + + if (is_int($writeTimeout = $config['write_timeout'])) { + $configuration->setWriteTimeout($writeTimeout); + } + + return new static(Algolia4SearchClient::createWithConfig($configuration), $softDelete); + } + + /** + * Update the given model in the index. + * + * @param \Illuminate\Database\Eloquent\Collection $models + * @return void + * + * @throws \Algolia\AlgoliaSearch\Exceptions\AlgoliaException + */ + public function update($models) + { + if ($models->isEmpty()) { + return; + } + + $index = $models->first()->indexableAs(); + + if ($this->usesSoftDelete($models->first()) && $this->softDelete) { + $models->each->pushSoftDeleteMetadata(); + } + + $objects = $models->map(function ($model) { + if (empty($searchableData = $model->toSearchableArray())) { + return; + } + + return array_merge( + $searchableData, + $model->scoutMetadata(), + ['objectID' => $model->getScoutKey()], + ); + })->filter()->values()->all(); + + if (! empty($objects)) { + $this->algolia->saveObjects($index, $objects); + } + } + + /** + * Remove the given model from the index. + * + * @param \Illuminate\Database\Eloquent\Collection $models + * @return void + */ + public function delete($models) + { + if ($models->isEmpty()) { + return; + } + + $keys = $models instanceof RemoveableScoutCollection + ? $models->pluck($models->first()->getScoutKeyName()) + : $models->map->getScoutKey(); + + $this->algolia->deleteObjects($models->first()->indexableAs(), $keys->all()); + } + + /** + * Delete a search index. + * + * @param string $name + * @return mixed + */ + public function deleteIndex($name) + { + return $this->algolia->deleteIndex($name); + } + + /** + * Flush all of the model's records from the engine. + * + * @param \Illuminate\Database\Eloquent\Model $model + * @return void + */ + public function flush($model) + { + $this->algolia->clearObjects($model->indexableAs()); + } + + /** + * Perform the given search on the engine. + * + * @param \Laravel\Scout\Builder $builder + * @param array $options + * @return mixed + */ + protected function performSearch(Builder $builder, array $options = []) + { + $options = array_merge($builder->options, $options); + + if ($builder->callback) { + return call_user_func( + $builder->callback, + $this->algolia, + $builder->query, + $options + ); + } + + $queryParams = ['query' => $builder->query]; + + return $this->algolia->searchSingleIndex( + $builder->index ?: $builder->model->searchableAs(), + $queryParams, + $options + ); + } +} diff --git a/src/Engines/AlgoliaEngine.php b/src/Engines/AlgoliaEngine.php index 8b5b6a41..91d47b56 100644 --- a/src/Engines/AlgoliaEngine.php +++ b/src/Engines/AlgoliaEngine.php @@ -9,12 +9,15 @@ use Laravel\Scout\Builder; use Laravel\Scout\Jobs\RemoveableScoutCollection; -class AlgoliaEngine extends Engine +/** + * @template TAlgoliaClient of object + */ +abstract class AlgoliaEngine extends Engine { /** * The Algolia client. * - * @var \Algolia\AlgoliaSearch\Api\SearchClient + * @var TAlgoliaClient */ protected $algolia; @@ -23,16 +26,16 @@ class AlgoliaEngine extends Engine * * @var bool */ - protected $softDelete; + protected $softDelete = false; /** * Create a new engine instance. * - * @param \Algolia\AlgoliaSearch\Api\SearchClient $algolia + * @param TAlgoliaClient $algolia * @param bool $softDelete * @return void */ - public function __construct(Algolia $algolia, $softDelete = false) + public function __construct($algolia, $softDelete = false) { $this->algolia = $algolia; $this->softDelete = $softDelete; @@ -46,34 +49,7 @@ public function __construct(Algolia $algolia, $softDelete = false) * * @throws \Algolia\AlgoliaSearch\Exceptions\AlgoliaException */ - public function update($models) - { - if ($models->isEmpty()) { - return; - } - - $index = $models->first()->indexableAs(); - - if ($this->usesSoftDelete($models->first()) && $this->softDelete) { - $models->each->pushSoftDeleteMetadata(); - } - - $objects = $models->map(function ($model) { - if (empty($searchableData = $model->toSearchableArray())) { - return; - } - - return array_merge( - $searchableData, - $model->scoutMetadata(), - ['objectID' => $model->getScoutKey()], - ); - })->filter()->values()->all(); - - if (! empty($objects)) { - $this->algolia->saveObjects($index, $objects); - } - } + abstract public function update($models); /** * Remove the given model from the index. @@ -81,18 +57,32 @@ public function update($models) * @param \Illuminate\Database\Eloquent\Collection $models * @return void */ - public function delete($models) - { - if ($models->isEmpty()) { - return; - } + abstract public function delete($models); - $keys = $models instanceof RemoveableScoutCollection - ? $models->pluck($models->first()->getScoutKeyName()) - : $models->map->getScoutKey(); + /** + * Delete a search index. + * + * @param string $name + * @return mixed + */ + abstract public function deleteIndex($name); - $this->algolia->deleteObjects($models->first()->indexableAs(), $keys->all()); - } + /** + * Flush all of the model's records from the engine. + * + * @param \Illuminate\Database\Eloquent\Model $model + * @return void + */ + abstract public function flush($model); + + /** + * Perform the given search on the engine. + * + * @param \Laravel\Scout\Builder $builder + * @param array $options + * @return mixed + */ + abstract protected function performSearch(Builder $builder, array $options = []); /** * Perform the given search on the engine. @@ -125,35 +115,6 @@ public function paginate(Builder $builder, $perPage, $page) ]); } - /** - * Perform the given search on the engine. - * - * @param \Laravel\Scout\Builder $builder - * @param array $options - * @return mixed - */ - protected function performSearch(Builder $builder, array $options = []) - { - $options = array_merge($builder->options, $options); - - if ($builder->callback) { - return call_user_func( - $builder->callback, - $this->algolia, - $builder->query, - $options - ); - } - - $queryParams = ['query' => $builder->query]; - - return $this->algolia->searchSingleIndex( - $builder->index ?: $builder->model->searchableAs(), - $queryParams, - $options - ); - } - /** * Get the filter array for the query. * @@ -272,17 +233,6 @@ public function getTotalCount($results) return $results['nbHits']; } - /** - * Flush all of the model's records from the engine. - * - * @param \Illuminate\Database\Eloquent\Model $model - * @return void - */ - public function flush($model) - { - $this->algolia->clearObjects($model->indexableAs()); - } - /** * Create a search index. * @@ -297,17 +247,6 @@ public function createIndex($name, array $options = []) throw new Exception('Algolia indexes are created automatically upon adding objects.'); } - /** - * Delete a search index. - * - * @param string $name - * @return mixed - */ - public function deleteIndex($name) - { - return $this->algolia->deleteIndex($name); - } - /** * Determine if the given model uses soft deletes. * diff --git a/tests/Unit/Algolia3EngineTest.php b/tests/Unit/Algolia3EngineTest.php new file mode 100644 index 00000000..2b486bed --- /dev/null +++ b/tests/Unit/Algolia3EngineTest.php @@ -0,0 +1,327 @@ +<?php + +namespace Laravel\Scout\Tests\Unit; + +use Algolia\AlgoliaSearch\SearchClient; +use Illuminate\Container\Container; +use Illuminate\Database\Eloquent\Collection; +use Illuminate\Support\Facades\Config; +use Illuminate\Support\LazyCollection; +use Laravel\Scout\Builder; +use Laravel\Scout\EngineManager; +use Laravel\Scout\Engines\Algolia3Engine; +use Laravel\Scout\Jobs\RemoveFromSearch; +use Laravel\Scout\Tests\Fixtures\EmptySearchableModel; +use Laravel\Scout\Tests\Fixtures\SearchableModel; +use Laravel\Scout\Tests\Fixtures\SoftDeletedEmptySearchableModel; +use Mockery as m; +use PHPUnit\Framework\TestCase; +use stdClass; + +class Algolia3EngineTest extends TestCase +{ + protected function setUp(): void + { + Config::shouldReceive('get')->with('scout.after_commit', m::any())->andReturn(false); + Config::shouldReceive('get')->with('scout.soft_delete', m::any())->andReturn(false); + } + + protected function tearDown(): void + { + Container::getInstance()->flush(); + m::close(); + } + + public function test_update_adds_objects_to_index() + { + $client = m::mock(SearchClient::class); + $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); + $index->shouldReceive('saveObjects')->with([[ + 'id' => 1, + 'objectID' => 1, + ]]); + + $engine = new Algolia3Engine($client); + $engine->update(Collection::make([new SearchableModel])); + } + + public function test_delete_removes_objects_to_index() + { + $client = m::mock(SearchClient::class); + $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); + $index->shouldReceive('deleteObjects')->with([1]); + + $engine = new Algolia3Engine($client); + $engine->delete(Collection::make([new SearchableModel(['id' => 1])])); + } + + public function test_delete_removes_objects_to_index_with_a_custom_search_key() + { + $client = m::mock(SearchClient::class); + $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(Indexes::class)); + $index->shouldReceive('deleteObjects')->once()->with(['my-algolia-key.5']); + + $engine = new Algolia3Engine($client); + $engine->delete(Collection::make([new Algolia3CustomKeySearchableModel(['id' => 5])])); + } + + public function test_delete_with_removeable_scout_collection_using_custom_search_key() + { + $job = new RemoveFromSearch(Collection::make([ + new Algolia3CustomKeySearchableModel(['id' => 5]), + ])); + + $job = unserialize(serialize($job)); + + $client = m::mock(SearchClient::class); + $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); + $index->shouldReceive('deleteObjects')->once()->with(['my-algolia-key.5']); + + $engine = new Algolia3Engine($client); + $engine->delete($job->models); + } + + public function test_remove_from_search_job_uses_custom_search_key() + { + $job = new RemoveFromSearch(Collection::make([ + new Algolia3CustomKeySearchableModel(['id' => 5]), + ])); + + $job = unserialize(serialize($job)); + + Container::getInstance()->bind(EngineManager::class, function () { + $engine = m::mock(Algolia3Engine::class); + + $engine->shouldReceive('delete')->once()->with(m::on(function ($collection) { + $keyName = ($model = $collection->first())->getScoutKeyName(); + + return $model->getAttributes()[$keyName] === 'my-algolia-key.5'; + })); + + $manager = m::mock(EngineManager::class); + + $manager->shouldReceive('engine')->andReturn($engine); + + return $manager; + }); + + $job->handle(); + } + + public function test_search_sends_correct_parameters_to_algolia() + { + $client = m::mock(SearchClient::class); + $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); + $index->shouldReceive('search')->with('zonda', [ + 'numericFilters' => ['foo=1'], + ]); + + $engine = new Algolia3Engine($client); + $builder = new Builder(new SearchableModel, 'zonda'); + $builder->where('foo', 1); + $engine->search($builder); + } + + public function test_search_sends_correct_parameters_to_algolia_for_where_in_search() + { + $client = m::mock(SearchClient::class); + $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); + $index->shouldReceive('search')->with('zonda', [ + 'numericFilters' => ['foo=1', ['bar=1', 'bar=2']], + ]); + + $engine = new Algolia3Engine($client); + $builder = new Builder(new SearchableModel, 'zonda'); + $builder->where('foo', 1)->whereIn('bar', [1, 2]); + $engine->search($builder); + } + + public function test_search_sends_correct_parameters_to_algolia_for_empty_where_in_search() + { + $client = m::mock(SearchClient::class); + $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); + $index->shouldReceive('search')->with('zonda', [ + 'numericFilters' => ['foo=1', '0=1'], + ]); + + $engine = new Algolia3Engine($client); + $builder = new Builder(new SearchableModel, 'zonda'); + $builder->where('foo', 1)->whereIn('bar', []); + $engine->search($builder); + } + + public function test_map_correctly_maps_results_to_models() + { + $client = m::mock(SearchClient::class); + $engine = new Algolia3Engine($client); + + $model = m::mock(stdClass::class); + + $model->shouldReceive('getScoutModelsByIds')->andReturn($models = Collection::make([ + new SearchableModel(['id' => 1, 'name' => 'test']), + ])); + + $builder = m::mock(Builder::class); + + $results = $engine->map($builder, [ + 'nbHits' => 1, + 'hits' => [ + ['objectID' => 1, 'id' => 1, '_rankingInfo' => ['nbTypos' => 0]], + ], + ], $model); + + $this->assertCount(1, $results); + $this->assertEquals(['id' => 1, 'name' => 'test'], $results->first()->toArray()); + $this->assertEquals(['_rankingInfo' => ['nbTypos' => 0]], $results->first()->scoutMetaData()); + } + + public function test_map_method_respects_order() + { + $client = m::mock(SearchClient::class); + $engine = new Algolia3Engine($client); + + $model = m::mock(stdClass::class); + $model->shouldReceive('getScoutModelsByIds')->andReturn($models = Collection::make([ + new SearchableModel(['id' => 1]), + new SearchableModel(['id' => 2]), + new SearchableModel(['id' => 3]), + new SearchableModel(['id' => 4]), + ])); + + $builder = m::mock(Builder::class); + + $results = $engine->map($builder, ['nbHits' => 4, 'hits' => [ + ['objectID' => 1, 'id' => 1], + ['objectID' => 2, 'id' => 2], + ['objectID' => 4, 'id' => 4], + ['objectID' => 3, 'id' => 3], + ]], $model); + + $this->assertCount(4, $results); + + // It's important we assert with array keys to ensure + // they have been reset after sorting. + $this->assertEquals([ + 0 => ['id' => 1], + 1 => ['id' => 2], + 2 => ['id' => 4], + 3 => ['id' => 3], + ], $results->toArray()); + } + + public function test_lazy_map_correctly_maps_results_to_models() + { + $client = m::mock(SearchClient::class); + $engine = new Algolia3Engine($client); + + $model = m::mock(stdClass::class); + $model->shouldReceive('queryScoutModelsByIds->cursor')->andReturn($models = LazyCollection::make([ + new SearchableModel(['id' => 1, 'name' => 'test']), + ])); + + $builder = m::mock(Builder::class); + + $results = $engine->lazyMap($builder, ['nbHits' => 1, 'hits' => [ + ['objectID' => 1, 'id' => 1, '_rankingInfo' => ['nbTypos' => 0]], + ]], $model); + + $this->assertCount(1, $results); + $this->assertEquals(['id' => 1, 'name' => 'test'], $results->first()->toArray()); + $this->assertEquals(['_rankingInfo' => ['nbTypos' => 0]], $results->first()->scoutMetaData()); + } + + public function test_lazy_map_method_respects_order() + { + $client = m::mock(SearchClient::class); + $engine = new Algolia3Engine($client); + + $model = m::mock(stdClass::class); + $model->shouldReceive('queryScoutModelsByIds->cursor')->andReturn($models = LazyCollection::make([ + new SearchableModel(['id' => 1]), + new SearchableModel(['id' => 2]), + new SearchableModel(['id' => 3]), + new SearchableModel(['id' => 4]), + ])); + + $builder = m::mock(Builder::class); + + $results = $engine->lazyMap($builder, ['nbHits' => 4, 'hits' => [ + ['objectID' => 1, 'id' => 1], + ['objectID' => 2, 'id' => 2], + ['objectID' => 4, 'id' => 4], + ['objectID' => 3, 'id' => 3], + ]], $model); + + $this->assertCount(4, $results); + + // It's important we assert with array keys to ensure + // they have been reset after sorting. + $this->assertEquals([ + 0 => ['id' => 1], + 1 => ['id' => 2], + 2 => ['id' => 4], + 3 => ['id' => 3], + ], $results->toArray()); + } + + public function test_a_model_is_indexed_with_a_custom_algolia_key() + { + $client = m::mock(SearchClient::class); + $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); + $index->shouldReceive('saveObjects')->with([[ + 'id' => 1, + 'objectID' => 'my-algolia-key.1', + ]]); + + $engine = new Algolia3Engine($client); + $engine->update(Collection::make([new Algolia3CustomKeySearchableModel])); + } + + public function test_a_model_is_removed_with_a_custom_algolia_key() + { + $client = m::mock(SearchClient::class); + $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); + $index->shouldReceive('deleteObjects')->with(['my-algolia-key.1']); + + $engine = new Algolia3Engine($client); + $engine->delete(Collection::make([new Algolia3CustomKeySearchableModel(['id' => 1])])); + } + + public function test_flush_a_model_with_a_custom_algolia_key() + { + $client = m::mock(SearchClient::class); + $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); + $index->shouldReceive('clearObjects'); + + $engine = new Algolia3Engine($client); + $engine->flush(new Algolia3CustomKeySearchableModel); + } + + public function test_update_empty_searchable_array_does_not_add_objects_to_index() + { + $client = m::mock(SearchClient::class); + $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); + $index->shouldNotReceive('saveObjects'); + + $engine = new Algolia3Engine($client); + $engine->update(Collection::make([new EmptySearchableModel])); + } + + public function test_update_empty_searchable_array_from_soft_deleted_model_does_not_add_objects_to_index() + { + $client = m::mock(SearchClient::class); + $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock('StdClass')); + $index->shouldNotReceive('saveObjects'); + + $engine = new Algolia3Engine($client, true); + $engine->update(Collection::make([new SoftDeletedEmptySearchableModel])); + } +} + +class Algolia3CustomKeySearchableModel extends SearchableModel +{ + public function getScoutKey() + { + return 'my-algolia-key.'.$this->getKey(); + } +} diff --git a/tests/Unit/AlgoliaEngineTest.php b/tests/Unit/Algolia4EngineTest.php similarity index 87% rename from tests/Unit/AlgoliaEngineTest.php rename to tests/Unit/Algolia4EngineTest.php index 06177c6a..49da1075 100644 --- a/tests/Unit/AlgoliaEngineTest.php +++ b/tests/Unit/Algolia4EngineTest.php @@ -9,7 +9,7 @@ use Illuminate\Support\LazyCollection; use Laravel\Scout\Builder; use Laravel\Scout\EngineManager; -use Laravel\Scout\Engines\AlgoliaEngine; +use Laravel\Scout\Engines\Algolia4Engine; use Laravel\Scout\Jobs\RemoveFromSearch; use Laravel\Scout\Tests\Fixtures\EmptySearchableModel; use Laravel\Scout\Tests\Fixtures\SearchableModel; @@ -18,7 +18,7 @@ use PHPUnit\Framework\TestCase; use stdClass; -class AlgoliaEngineTest extends TestCase +class Algolia4EngineTest extends TestCase { protected function setUp(): void { @@ -41,7 +41,7 @@ public function test_update_adds_objects_to_index() 'objectID' => 1, ]]); - $engine = new AlgoliaEngine($client); + $engine = new Algolia4Engine($client); $engine->update(Collection::make([new SearchableModel])); } @@ -50,7 +50,7 @@ public function test_delete_removes_objects_to_index() $client = m::mock(SearchClient::class); $client->shouldReceive('deleteObjects')->with('table', [1]); - $engine = new AlgoliaEngine($client); + $engine = new Algolia4Engine($client); $engine->delete(Collection::make([new SearchableModel(['id' => 1])])); } @@ -59,14 +59,14 @@ public function test_delete_removes_objects_to_index_with_a_custom_search_key() $client = m::mock(SearchClient::class); $client->shouldReceive('deleteObjects')->once()->with('table', ['my-algolia-key.5']); - $engine = new AlgoliaEngine($client); - $engine->delete(Collection::make([new AlgoliaCustomKeySearchableModel(['id' => 5])])); + $engine = new Algolia4Engine($client); + $engine->delete(Collection::make([new Algolia4CustomKeySearchableModel(['id' => 5])])); } public function test_delete_with_removeable_scout_collection_using_custom_search_key() { $job = new RemoveFromSearch(Collection::make([ - new AlgoliaCustomKeySearchableModel(['id' => 5]), + new Algolia4CustomKeySearchableModel(['id' => 5]), ])); $job = unserialize(serialize($job)); @@ -74,20 +74,20 @@ public function test_delete_with_removeable_scout_collection_using_custom_search $client = m::mock(SearchClient::class); $client->shouldReceive('deleteObjects')->once()->with('table', ['my-algolia-key.5']); - $engine = new AlgoliaEngine($client); + $engine = new Algolia4Engine($client); $engine->delete($job->models); } public function test_remove_from_search_job_uses_custom_search_key() { $job = new RemoveFromSearch(Collection::make([ - new AlgoliaCustomKeySearchableModel(['id' => 5]), + new Algolia4CustomKeySearchableModel(['id' => 5]), ])); $job = unserialize(serialize($job)); Container::getInstance()->bind(EngineManager::class, function () { - $engine = m::mock(AlgoliaEngine::class); + $engine = m::mock(Algolia4Engine::class); $engine->shouldReceive('delete')->once()->with(m::on(function ($collection) { $keyName = ($model = $collection->first())->getScoutKeyName(); @@ -114,7 +114,7 @@ public function test_search_sends_correct_parameters_to_algolia() ['numericFilters' => ['foo=1']] ); - $engine = new AlgoliaEngine($client); + $engine = new Algolia4Engine($client); $builder = new Builder(new SearchableModel, 'zonda'); $builder->where('foo', 1); $engine->search($builder); @@ -129,7 +129,7 @@ public function test_search_sends_correct_parameters_to_algolia_for_where_in_sea ['numericFilters' => ['foo=1', ['bar=1', 'bar=2']]] ); - $engine = new AlgoliaEngine($client); + $engine = new Algolia4Engine($client); $builder = new Builder(new SearchableModel, 'zonda'); $builder->where('foo', 1)->whereIn('bar', [1, 2]); $engine->search($builder); @@ -144,7 +144,7 @@ public function test_search_sends_correct_parameters_to_algolia_for_empty_where_ ['numericFilters' => ['foo=1', '0=1']] ); - $engine = new AlgoliaEngine($client); + $engine = new Algolia4Engine($client); $builder = new Builder(new SearchableModel, 'zonda'); $builder->where('foo', 1)->whereIn('bar', []); $engine->search($builder); @@ -153,7 +153,7 @@ public function test_search_sends_correct_parameters_to_algolia_for_empty_where_ public function test_map_correctly_maps_results_to_models() { $client = m::mock(SearchClient::class); - $engine = new AlgoliaEngine($client); + $engine = new Algolia4Engine($client); $model = m::mock(stdClass::class); @@ -178,7 +178,7 @@ public function test_map_correctly_maps_results_to_models() public function test_map_method_respects_order() { $client = m::mock(SearchClient::class); - $engine = new AlgoliaEngine($client); + $engine = new Algolia4Engine($client); $model = m::mock(stdClass::class); $model->shouldReceive('getScoutModelsByIds')->andReturn($models = Collection::make([ @@ -212,7 +212,7 @@ public function test_map_method_respects_order() public function test_lazy_map_correctly_maps_results_to_models() { $client = m::mock(SearchClient::class); - $engine = new AlgoliaEngine($client); + $engine = new Algolia4Engine($client); $model = m::mock(stdClass::class); $model->shouldReceive('queryScoutModelsByIds->cursor')->andReturn($models = LazyCollection::make([ @@ -233,7 +233,7 @@ public function test_lazy_map_correctly_maps_results_to_models() public function test_lazy_map_method_respects_order() { $client = m::mock(SearchClient::class); - $engine = new AlgoliaEngine($client); + $engine = new Algolia4Engine($client); $model = m::mock(stdClass::class); $model->shouldReceive('queryScoutModelsByIds->cursor')->andReturn($models = LazyCollection::make([ @@ -273,8 +273,8 @@ public function test_a_model_is_indexed_with_a_custom_algolia_key() 'objectID' => 'my-algolia-key.1', ]]); - $engine = new AlgoliaEngine($client); - $engine->update(Collection::make([new AlgoliaCustomKeySearchableModel])); + $engine = new Algolia4Engine($client); + $engine->update(Collection::make([new Algolia4CustomKeySearchableModel])); } public function test_a_model_is_removed_with_a_custom_algolia_key() @@ -282,8 +282,8 @@ public function test_a_model_is_removed_with_a_custom_algolia_key() $client = m::mock(SearchClient::class); $client->shouldReceive('deleteObjects')->with('table', ['my-algolia-key.1']); - $engine = new AlgoliaEngine($client); - $engine->delete(Collection::make([new AlgoliaCustomKeySearchableModel(['id' => 1])])); + $engine = new Algolia4Engine($client); + $engine->delete(Collection::make([new Algolia4CustomKeySearchableModel(['id' => 1])])); } public function test_flush_a_model_with_a_custom_algolia_key() @@ -291,8 +291,8 @@ public function test_flush_a_model_with_a_custom_algolia_key() $client = m::mock(SearchClient::class); $client->shouldReceive('clearObjects')->with('table'); - $engine = new AlgoliaEngine($client); - $engine->flush(new AlgoliaCustomKeySearchableModel); + $engine = new Algolia4Engine($client); + $engine->flush(new Algolia4CustomKeySearchableModel); } public function test_update_empty_searchable_array_does_not_add_objects_to_index() @@ -301,7 +301,7 @@ public function test_update_empty_searchable_array_does_not_add_objects_to_index $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock(stdClass::class)); $index->shouldNotReceive('saveObjects'); - $engine = new AlgoliaEngine($client); + $engine = new Algolia4Engine($client); $engine->update(Collection::make([new EmptySearchableModel])); } @@ -311,12 +311,12 @@ public function test_update_empty_searchable_array_from_soft_deleted_model_does_ $client->shouldReceive('initIndex')->with('table')->andReturn($index = m::mock('StdClass')); $index->shouldNotReceive('saveObjects'); - $engine = new AlgoliaEngine($client, true); + $engine = new Algolia4Engine($client, true); $engine->update(Collection::make([new SoftDeletedEmptySearchableModel])); } } -class AlgoliaCustomKeySearchableModel extends SearchableModel +class Algolia4CustomKeySearchableModel extends SearchableModel { public function getScoutKey() { From b2568745ee7479e0ce1a4e2d108a2e2b36b304fe Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Fri, 8 Nov 2024 15:15:07 +0800 Subject: [PATCH 18/24] wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- src/EngineManager.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/EngineManager.php b/src/EngineManager.php index b739a9b0..897a6a0f 100644 --- a/src/EngineManager.php +++ b/src/EngineManager.php @@ -31,7 +31,7 @@ public function engine($name = null) } /** - * Create a Meilisearch engine instance. + * Create an Algolia engine instance. * * @return \Laravel\Scout\Engines\AlgoliaEngine */ @@ -45,7 +45,7 @@ public function createAlgoliaDriver() } /** - * Create an Algolia v4 engine instance. + * Create an Algolia v3 engine instance. * * @return \Laravel\Scout\Engines\Algolia3Engine */ From 97f40dd9dc0b8c85ef0e3057f557b0f94232684f Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Fri, 8 Nov 2024 15:16:22 +0800 Subject: [PATCH 19/24] wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- composer.json | 3 +++ src/EngineManager.php | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index a86a6d4e..bcc2cec0 100644 --- a/composer.json +++ b/composer.json @@ -34,6 +34,9 @@ "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9.3|^10.4" }, + "conflict": { + "algolia/algoliasearch-client-php": "<3.2.0|>=5.0.0" + }, "autoload": { "psr-4": { "Laravel\\Scout\\": "src/" diff --git a/src/EngineManager.php b/src/EngineManager.php index 897a6a0f..711067a0 100644 --- a/src/EngineManager.php +++ b/src/EngineManager.php @@ -104,10 +104,6 @@ protected function ensureAlgoliaClientIsInstalled() return; } - if (class_exists('AlgoliaSearch\Client')) { - throw new Exception('Please upgrade your Algolia client to version: ^3.2|^4.0.'); - } - throw new Exception('Please install the suggested Algolia client: algolia/algoliasearch-client-php.'); } From e77103decd99e9f09fbdcc7289f2e4808a02ad1f Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Fri, 8 Nov 2024 15:24:28 +0800 Subject: [PATCH 20/24] wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- phpstan.src.neon.dist | 4 ++++ src/EngineManager.php | 38 +++++++++++----------------------- src/Engines/Algolia3Engine.php | 7 +++---- src/Engines/Algolia4Engine.php | 7 +++---- 4 files changed, 22 insertions(+), 34 deletions(-) diff --git a/phpstan.src.neon.dist b/phpstan.src.neon.dist index fe17868f..e43f2c8c 100644 --- a/phpstan.src.neon.dist +++ b/phpstan.src.neon.dist @@ -6,4 +6,8 @@ parameters: level: 0 ignoreErrors: + - identifier: new.static - "#\\(void\\) is used.#" + + excludePaths: + - src/Engines/Algolia3Engine.php diff --git a/src/EngineManager.php b/src/EngineManager.php index 711067a0..9e461c37 100644 --- a/src/EngineManager.php +++ b/src/EngineManager.php @@ -7,7 +7,8 @@ use Algolia\AlgoliaSearch\Support\UserAgent as Algolia3UserAgent; use Exception; use Illuminate\Support\Manager; -use Laravel\Scout\Engines\AlgoliaEngine; +use Laravel\Scout\Engines\Algolia3Engine; +use Laravel\Scout\Engines\Algolia4Engine; use Laravel\Scout\Engines\CollectionEngine; use Laravel\Scout\Engines\DatabaseEngine; use Laravel\Scout\Engines\MeilisearchEngine; @@ -51,32 +52,13 @@ public function createAlgoliaDriver() */ protected function configureAlgolia3Driver() { - Algolia3UserAgent::addCustomUserAgent('Laravel Scout', Scout::VERSION); + Algolia3UserAgent::addCustomUserAgent('Laravel Scout', Scout::VERSION); // @phpstan-ignore class.notFound - $config = SearchConfig::create( - config('scout.algolia.id'), - config('scout.algolia.secret') - )->setDefaultHeaders( - $this->defaultAlgoliaHeaders() + return Algolia3Engine::make( + config: config('scout.algolia'), + headers: $this->defaultAlgoliaHeaders(), + softDelete: config('scout.soft_delete') ); - - if (is_int($connectTimeout = config('scout.algolia.connect_timeout'))) { - $config->setConnectTimeout($connectTimeout); - } - - if (is_int($readTimeout = config('scout.algolia.read_timeout'))) { - $config->setReadTimeout($readTimeout); - } - - if (is_int($writeTimeout = config('scout.algolia.write_timeout'))) { - $config->setWriteTimeout($writeTimeout); - } - - if (is_int($batchSize = config('scout.algolia.batch_size'))) { - $config->setBatchSize($batchSize); - } - - return new AlgoliaEngine(Algolia::createWithConfig($config), config('scout.soft_delete')); } /** @@ -88,7 +70,11 @@ protected function configureAlgolia4Driver() { Algolia4UserAgent::addAlgoliaAgent('Laravel Scout', 'Laravel Scout', Scout::VERSION); - return Algolia4Engine::make(config('scout.algolia'), config('scout.soft_delete')); + return Algolia4Engine::make( + config: config('scout.algolia'), + headers: $this->defaultAlgoliaHeaders(), + softDelete: config('scout.soft_delete') + ); } /** diff --git a/src/Engines/Algolia3Engine.php b/src/Engines/Algolia3Engine.php index a4239fe8..4df86cc1 100644 --- a/src/Engines/Algolia3Engine.php +++ b/src/Engines/Algolia3Engine.php @@ -31,17 +31,16 @@ public function __construct(Algolia3SearchClient $algolia, $softDelete = false) * Make a new engine instance. * * @param array $config + * @param array $headers * @param bool $softDelete * @return static */ - public static function make(array $config, bool $softDelete = false) + public static function make(array $config, array $headers, bool $softDelete = false) { $config = Algolia3SearchConfig::create([ 'appId' => $config['id'], 'apiKey' => $config['secret'], - ])->setDefaultHeaders( - $this->defaultAlgoliaHeaders() - ); + ])->setDefaultHeaders($headers); if (is_int($connectTimeout = $config['connect_timeout'])) { $configuration->setConnectTimeout($connectTimeout); diff --git a/src/Engines/Algolia4Engine.php b/src/Engines/Algolia4Engine.php index d88857c6..c1e88496 100644 --- a/src/Engines/Algolia4Engine.php +++ b/src/Engines/Algolia4Engine.php @@ -32,19 +32,18 @@ public function __construct(Algolia4SearchClient $algolia, $softDelete = false) * Make a new engine instance. * * @param array $config + * @param array $headers * @param bool $softDelete * @return static */ - public static function make(array $config, bool $softDelete = false) + public static function make(array $config, array $headers, bool $softDelete = false) { $configuration = (new Algolia4SearchConfig(array_merge([ 'appId' => $config['id'], 'apiKey' => $config['secret'], ]), array_filter([ 'batchSize' => $config['batch_size'], - ])))->setDefaultHeaders( - $this->defaultAlgoliaHeaders() - ); + ])))->setDefaultHeaders($headers); if (is_int($connectTimeout = $config['connect_timeout'])) { $configuration->setConnectTimeout($connectTimeout); From bedd3b79f9231af9286bdd4548f24ffafd217628 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Fri, 8 Nov 2024 15:25:43 +0800 Subject: [PATCH 21/24] wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- src/Engines/AlgoliaEngine.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Engines/AlgoliaEngine.php b/src/Engines/AlgoliaEngine.php index 91d47b56..11777fd3 100644 --- a/src/Engines/AlgoliaEngine.php +++ b/src/Engines/AlgoliaEngine.php @@ -26,7 +26,7 @@ abstract class AlgoliaEngine extends Engine * * @var bool */ - protected $softDelete = false; + protected $softDelete; /** * Create a new engine instance. From 7265a567ed03584b69f0b7c4e4104127b524686c Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Fri, 8 Nov 2024 15:28:17 +0800 Subject: [PATCH 22/24] wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- src/Engines/Algolia3Engine.php | 3 --- src/Engines/Algolia4Engine.php | 4 ---- src/Engines/AlgoliaEngine.php | 1 - 3 files changed, 8 deletions(-) diff --git a/src/Engines/Algolia3Engine.php b/src/Engines/Algolia3Engine.php index 4df86cc1..3710ca4f 100644 --- a/src/Engines/Algolia3Engine.php +++ b/src/Engines/Algolia3Engine.php @@ -4,9 +4,6 @@ use Algolia\AlgoliaSearch\Config\SearchConfig as Algolia3SearchConfig; use Algolia\AlgoliaSearch\SearchClient as Algolia3SearchClient; -use Exception; -use Illuminate\Database\Eloquent\SoftDeletes; -use Illuminate\Support\LazyCollection; use Laravel\Scout\Builder; use Laravel\Scout\Jobs\RemoveableScoutCollection; diff --git a/src/Engines/Algolia4Engine.php b/src/Engines/Algolia4Engine.php index c1e88496..0cb08e1f 100644 --- a/src/Engines/Algolia4Engine.php +++ b/src/Engines/Algolia4Engine.php @@ -4,10 +4,6 @@ use Algolia\AlgoliaSearch\Api\SearchClient as Algolia4SearchClient; use Algolia\AlgoliaSearch\Configuration\SearchConfig as Algolia4SearchConfig; -use Algolia\AlgoliaSearch\Support\AlgoliaAgent as Algolia4UserAgent; -use Exception; -use Illuminate\Database\Eloquent\SoftDeletes; -use Illuminate\Support\LazyCollection; use Laravel\Scout\Builder; use Laravel\Scout\Jobs\RemoveableScoutCollection; diff --git a/src/Engines/AlgoliaEngine.php b/src/Engines/AlgoliaEngine.php index 11777fd3..73cb2463 100644 --- a/src/Engines/AlgoliaEngine.php +++ b/src/Engines/AlgoliaEngine.php @@ -7,7 +7,6 @@ use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\LazyCollection; use Laravel\Scout\Builder; -use Laravel\Scout\Jobs\RemoveableScoutCollection; /** * @template TAlgoliaClient of object From 9723fc9c34042582a7082d450cf6a5d2f0359e8e Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki <crynobone@gmail.com> Date: Fri, 8 Nov 2024 15:30:13 +0800 Subject: [PATCH 23/24] wip Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com> --- src/Engines/AlgoliaEngine.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Engines/AlgoliaEngine.php b/src/Engines/AlgoliaEngine.php index 73cb2463..5990adda 100644 --- a/src/Engines/AlgoliaEngine.php +++ b/src/Engines/AlgoliaEngine.php @@ -2,7 +2,6 @@ namespace Laravel\Scout\Engines; -use Algolia\AlgoliaSearch\Api\SearchClient as Algolia; use Exception; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\LazyCollection; From 50665af7bf2da66c80749e5ba24ad3cfa852f89a Mon Sep 17 00:00:00 2001 From: Taylor Otwell <taylor@laravel.com> Date: Mon, 11 Nov 2024 15:07:26 -0600 Subject: [PATCH 24/24] Update AlgoliaEngine.php --- src/Engines/AlgoliaEngine.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Engines/AlgoliaEngine.php b/src/Engines/AlgoliaEngine.php index 5990adda..23d2f7cc 100644 --- a/src/Engines/AlgoliaEngine.php +++ b/src/Engines/AlgoliaEngine.php @@ -39,6 +39,15 @@ public function __construct($algolia, $softDelete = false) $this->softDelete = $softDelete; } + /** + * Perform the given search on the engine. + * + * @param \Laravel\Scout\Builder $builder + * @param array $options + * @return mixed + */ + abstract protected function performSearch(Builder $builder, array $options = []); + /** * Update the given model in the index. * @@ -73,15 +82,6 @@ abstract public function deleteIndex($name); */ abstract public function flush($model); - /** - * Perform the given search on the engine. - * - * @param \Laravel\Scout\Builder $builder - * @param array $options - * @return mixed - */ - abstract protected function performSearch(Builder $builder, array $options = []); - /** * Perform the given search on the engine. *