Skip to content

Commit

Permalink
Merge branch 'master' of github.com:Klaasie/laravel-scout-solr-engine
Browse files Browse the repository at this point in the history
  • Loading branch information
Klaasie committed Apr 30, 2024
2 parents 7d387cd + d49b93b commit 3060869
Show file tree
Hide file tree
Showing 11 changed files with 231 additions and 74 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
vendor/
.idea/
composer.lock
.phpunit.result.cache
.phpunit.result.cache
example/.phpunit.cache
26 changes: 20 additions & 6 deletions config/scout-solr.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@

declare(strict_types=1);

use Scout\Solr\ClientInterface;

return [
/*
|--------------------------------------------------------------------------
| Solr Admin ConfigSet
| Solr Cloud
|--------------------------------------------------------------------------
|
| Set a default ConfigSet used for the createIndex command.
| Without a ConfigSet Solr won't be able to create indexes through the command.
| Different Solr APIs are used depending on whether standalone or cloud is being used.
|
|
*/
'create' => [
'config_set' => env('SOLR_CONFIG_SET', '_default'),
],
'cloud' => env('SOLR_CLOUD', false),

/*
|--------------------------------------------------------------------------
Expand Down Expand Up @@ -64,14 +63,29 @@
'host' => env('SOLR_HOST', 'localhost'),
'port' => env('SOLR_PORT', 8983),
'path' => env('SOLR_PATH', '/'),
'config_set' => env('SOLR_CONFIG_SET', '_default'),
// Core is set through searchableAs()

/*
* These settings are used with SOLR cloud.
* When using router_name "compositeId" the num_shards config is required.
* When using router_name "implicit" the shards config is required.
*/
'router_name' => env('SOLR_ROUTER_NAME', ClientInterface::ROUTER_NAME_COMPOSITE_ID),
'num_shards' => env('SOLR_NUM_SHARDS', 1),
'shards' => env('SOLR_SHARDS', 'shard-x,shard-y,shard-z'),
],
// Example of a core defined through config
// 'books' => [
// 'host' => env('SOLR_HOST', 'solr2'),
// 'port' => env('SOLR_PORT', 8983),
// 'path' => env('SOLR_PATH', '/'),
// 'config_set' => env('SOLR_CONFIG_SET', '_default'),
// 'core' => env('SOLR_CORE', 'books'),

// 'router_name' => env('SOLR_ROUTER_NAME', ClientInterface::ROUTER_NAME_COMPOSITE_ID'),
// 'num_shards' => env('SOLR_NUM_SHARDS', 1),
// 'shards' => env('SOLR_SHARDS', 1),
// ],
],
];
16 changes: 11 additions & 5 deletions example/config/scout-solr.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

return [

'create' => [
'config_set' => env('SOLR_CONFIG_SET', '_default'),
],
'cloud' => env('SOLR_CLOUD', true),
'unload' => [
'delete_index' => env('SOLR_UNLOAD_DELETE_INDEX', true),
'delete_data_dir' => env('SOLR_UNLOAD_DELETE_DATA_DIR', true),
Expand All @@ -22,17 +20,25 @@
*/
'endpoints' => [
'default' => [
'host' => env('SOLR_HOST', 'solr'),
'host' => env('SOLR_HOST', 'solr.cloud'),
'port' => env('SOLR_PORT', 8983),
'path' => env('SOLR_PATH', '/'),
// Core is set through searchableAs()
'config_set' => env('SOLR_CONFIG_SET', '_default'),
'router_name' => env('SOLR_ROUTER_NAME', 'compositeId'),
'num_shards' => env('SOLR_NUM_SHARDS', 1),
'shards' => env('SOLR_SHARDS', 'shard-x,shard-y,shard-z'),
],
// Example of a core defined through config
'books' => [
'host' => env('SOLR_HOST', 'solr2'),
'host' => env('SOLR_HOST', 'solr.cloud'),
'port' => env('SOLR_PORT', 8983),
'path' => env('SOLR_PATH', '/'),
'core' => env('SOLR_CORE', 'books'),
'config_set' => env('SOLR_CONFIG_SET', '_default'),
'router_name' => env('SOLR_ROUTER_NAME', 'compositeId'),
'num_shards' => env('SOLR_NUM_SHARDS', 1),
'shards' => env('SOLR_SHARDS', 'shard-x,shard-y,shard-z'),
],
],
];
17 changes: 17 additions & 0 deletions example/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,21 @@ services:
- gettingstarted
networks:
- sail
solr.cloud:
image: solr
ports:
- "${FORWARD_ZOO_KEEPER_PORT:-9983}:9983"
- "${FORWARD_SOLR_PORT:-8985}:8983"
volumes:
- 'sailsolr2:/data.ms'
entrypoint:
- docker-entrypoint.sh
- solr
- start
- -c
- -f
networks:
- sail
mailhog:
image: 'mailhog/mailhog:latest'
ports:
Expand All @@ -110,3 +125,5 @@ volumes:
driver: local
sailsolr2:
driver: local
sailsolrcloud:
driver: local
55 changes: 26 additions & 29 deletions example/phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,31 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
</include>
</coverage>
<php>
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<!-- <server name="DB_CONNECTION" value="sqlite"/> -->
<!-- <server name="DB_DATABASE" value=":memory:"/> -->
<server name="MAIL_MAILER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
<server name="TELESCOPE_ENABLED" value="false"/>
</php>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.2/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true" cacheDirectory=".phpunit.cache">
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<coverage/>
<php>
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<!-- <server name="DB_CONNECTION" value="sqlite"/> -->
<!-- <server name="DB_DATABASE" value=":memory:"/> -->
<server name="MAIL_MAILER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
<server name="TELESCOPE_ENABLED" value="false"/>
</php>
<source>
<include>
<directory suffix=".php">./app</directory>
</include>
</source>
</phpunit>
90 changes: 90 additions & 0 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,29 @@

namespace Scout\Solr;

use Illuminate\Contracts\Config\Repository;
use Illuminate\Database\Eloquent\Model;
use Psr\EventDispatcher\EventDispatcherInterface;
use Scout\Solr\Exceptions\InvalidRouterNameSupplied;
use Solarium\Client as ClientBase;
use Solarium\Core\Client\Adapter\AdapterInterface;
use Solarium\Core\Client\Endpoint;
use Solarium\Core\Query\Result\ResultInterface;

class Client extends ClientBase implements ClientInterface
{
private Repository $config;

public function __construct(
AdapterInterface $adapter,
EventDispatcherInterface $eventDispatcher,
Repository $config,
array $options = null
) {
parent::__construct($adapter, $eventDispatcher, $options);
$this->config = $config;
}

public function setCore(Model $model): self
{
/** @noinspection PhpPossiblePolymorphicInvocationInspection */
Expand All @@ -21,4 +39,76 @@ public function setCore(Model $model): self
$this->getEndpoint()->setCore($searchableAs);
return $this;
}

public function createCore(string $name): ResultInterface
{
$key = $this->config->has('scout-solr.endpoints.' . $name) ? $name : 'default';

if ($this->config->get('scout-solr.cloud')) {
$routerName = $this->config->get('scout-solr.endpoints.' . $key . '.router_name');

$collectionAdminQuery = $this->createCollections();

$action = $collectionAdminQuery->createCreate();
$action->setName($name);
$action->setRouterName($routerName);

match ($routerName) {
ClientInterface::ROUTER_NAME_COMPOSITE_ID => $action->setNumShards(
$this->config->get('scout-solr.endpoints.' . $key . '.num_shards')
),
ClientInterface::ROUTER_NAME_IMPLICIT => $action->setShards(
$this->config->get('scout-solr.endpoints.' . $key . '.shards')
),
default => InvalidRouterNameSupplied::forRouterName($routerName),
};

$collectionAdminQuery->setAction($action);

return $this->collections($collectionAdminQuery, $this->getEndpointFromConfig($key));
}

$coreAdminQuery = $this->createCoreAdmin();
$action = $coreAdminQuery->createCreate();
$action->setCore($name);
$action->setConfigSet($this->config->get('scout-solr.endpoints.' . $key . '.config_set', '_default'));
$coreAdminQuery->setAction($action);

return $this->coreAdmin($coreAdminQuery, $this->getEndpointFromConfig($key));
}

public function deleteCore(string $name): ResultInterface
{
$key = $this->config->has('scout-solr.endpoints.' . $name) ? $name : 'default';

if ($this->config->get('scout-solr.cloud')) {
$collectionAdminQuery = $this->createCollections();

$action = $collectionAdminQuery->createDelete();
$action->setName($name);
$collectionAdminQuery->setAction($action);

return $this->collections($collectionAdminQuery, $this->getEndpointFromConfig($key));
}

$coreAdminQuery = $this->createCoreAdmin();

$action = $coreAdminQuery->createUnload();
$action->setCore($name);
$action->setDeleteIndex($this->config->get('scout-solr.unload.delete_index'));
$action->setDeleteDataDir($this->config->get('scout-solr.unload.delete_data_dir'));
$action->setDeleteInstanceDir($this->config->get('scout-solr.unload.delete_instance_dir'));
$coreAdminQuery->setAction($action);

return $this->coreAdmin($coreAdminQuery, $this->getEndpointFromConfig($name));
}

public function getEndpointFromConfig(string $name): ?Endpoint
{
if ($this->config->get('scout-solr.endpoints.' . $name) === null) {
return null;
}

return new Endpoint($this->config->get('scout-solr.endpoints.' . $name));
}
}
7 changes: 7 additions & 0 deletions src/ClientInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,12 @@

interface ClientInterface extends ClientInterfaceBase
{
public const ROUTER_NAME_COMPOSITE_ID = 'compositeId';
public const ROUTER_NAME_IMPLICIT = 'implicit';

public function setCore(Model $model): self;

public function createCore(string $name);

public function deleteCore(string $name);
}
37 changes: 7 additions & 30 deletions src/Engines/SolrEngine.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
use Scout\Solr\ClientInterface;
use Scout\Solr\Events\AfterSelect;
use Scout\Solr\Events\BeforeSelect;
use Solarium\Core\Client\Endpoint;
use Solarium\Core\Query\Result\ResultInterface;
use Solarium\QueryType\Select\Result\Document;
use Solarium\QueryType\Select\Result\Result;
Expand All @@ -33,8 +32,11 @@ class SolrEngine extends Engine
private Repository $config;
private Dispatcher $events;

public function __construct(ClientInterface $client, Repository $config, Dispatcher $events)
{
public function __construct(
ClientInterface $client,
Repository $config,
Dispatcher $events
) {
$this->client = $client;
$this->config = $config;
$this->events = $events;
Expand Down Expand Up @@ -172,28 +174,12 @@ public function flush($model): void

public function createIndex($name, array $options = [])
{
$coreAdminQuery = $this->client->createCoreAdmin();

$action = $coreAdminQuery->createCreate();
$action->setCore($name);
$action->setConfigSet($this->config->get('scout-solr.create.config_set'));

$coreAdminQuery->setAction($action);
return $this->client->coreAdmin($coreAdminQuery, $this->getEndpointFromConfig($name));
return $this->client->createCore($name);
}

public function deleteIndex($name)
{
$coreAdminQuery = $this->client->createCoreAdmin();

$action = $coreAdminQuery->createUnload();
$action->setCore($name);
$action->setDeleteIndex($this->config->get('scout-solr.unload.delete_index'));
$action->setDeleteDataDir($this->config->get('scout-solr.unload.delete_data_dir'));
$action->setDeleteInstanceDir($this->config->get('scout-solr.unload.delete_instance_dir'));

$coreAdminQuery->setAction($action);
return $this->client->coreAdmin($coreAdminQuery, $this->getEndpointFromConfig($name));
return $this->client->deleteCore($name);
}

protected function performSearch(Builder $builder, array $options = []): Result
Expand Down Expand Up @@ -247,15 +233,6 @@ protected function filters(Builder $builder): string
return $filters->values()->implode(' AND ');
}

public function getEndpointFromConfig(string $name): ?Endpoint
{
if ($this->config->get('scout-solr.endpoints.' . $name) === null) {
return null;
}

return new Endpoint($this->config->get('scout-solr.endpoints.' . $name));
}

/**
* Dynamically call the Solr client instance.
*
Expand Down
17 changes: 17 additions & 0 deletions src/Exceptions/InvalidRouterNameSupplied.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Scout\Solr\Exceptions;

use InvalidArgumentException;

class InvalidRouterNameSupplied extends InvalidArgumentException
{
public static function forRouterName(string $name): self
{
return new self(
sprintf('Router name %s is not supported', $name)
);
}
}
Loading

0 comments on commit 3060869

Please sign in to comment.